Compare commits

..

1 Commits

Author SHA1 Message Date
986030cc38 chore: failed attempt at adding custom field labels
I have spent all day on it and for some reason, I can't figure it out
2024-02-18 16:01:03 +00:00
1154 changed files with 67254 additions and 99153 deletions

View File

@ -1,48 +0,0 @@
Code Style and Structure:
- Write concise, technical TypeScript code with accurate examples
- Use functional and declarative programming patterns; avoid classes
- Prefer iteration and modularization over code duplication
- Use descriptive variable names with auxiliary verbs (e.g., isLoading, hasError)
- Structure files: exported component, subcomponents, helpers, static content, types
Naming Conventions:
- Use lowercase with dashes for directories (e.g., components/auth-wizard)
- Favor named exports for components
TypeScript Usage:
- Use TypeScript for all code; prefer interfaces over types
- Avoid enums; use maps instead
- Use functional components with TypeScript interfaces
Syntax and Formatting:
- Use the "function" keyword for pure functions
- Avoid unnecessary curly braces in conditionals; use concise syntax for simple statements
- Use declarative JSX
Error Handling and Validation:
- Prioritize error handling: handle errors and edge cases early
- Use early returns and guard clauses
- Implement proper error logging and user-friendly messages
- Use Zod for form validation
- Model expected errors as return values in Server Actions
- Use error boundaries for unexpected errors
UI and Styling:
- Use Shadcn UI, Radix, and Tailwind Aria for components and styling
- Implement responsive design with Tailwind CSS; use a mobile-first approach
Performance Optimization:
- Minimize 'use client', 'useEffect', and 'setState'; favor React Server Components (RSC)
- Wrap client components in Suspense with fallback
- Use dynamic loading for non-critical components
- Optimize images: use WebP format, include size data, implement lazy loading
Key Conventions:
- Use 'nuqs' for URL search parameter state management
- Optimize Web Vitals (LCP, CLS, FID)
- Limit 'use client':
- Favor server components and Next.js SSR
- Use only for Web API access in small components
- Avoid for data fetching or state management
Follow Next.js docs for Data Fetching, Rendering, and Routing

View File

@ -10,13 +10,7 @@
"ghcr.io/devcontainers/features/node:1": {}
},
"onCreateCommand": "./.devcontainer/on-create.sh",
"forwardPorts": [
3000,
54320,
9000,
2500,
1100
],
"forwardPorts": [3000, 54320, 9000, 2500, 1100],
"customizations": {
"vscode": {
"extensions": [
@ -31,8 +25,8 @@
"GitHub.copilot",
"GitHub.vscode-pull-request-github",
"Prisma.prisma",
"VisualStudioExptTeam.vscodeintellicode"
"VisualStudioExptTeam.vscodeintellicode",
]
}
}
}
}

View File

@ -1,10 +1,13 @@
#!/usr/bin/env bash
# Start the database and mailserver
docker compose -f ./docker/compose-without-app.yml up -d
# Install dependencies
npm install
# Copy the env file
cp .env.example .env
# Run the dev setup
npm run dx
# Run the migrations
npm run prisma:migrate-dev

View File

@ -10,57 +10,28 @@ NEXT_PRIVATE_ENCRYPTION_KEY="CAFEBABE"
NEXT_PRIVATE_ENCRYPTION_SECONDARY_KEY="DEADBEEF"
# [[AUTH OPTIONAL]]
# Find documentation on setting up Google OAuth here:
# https://docs.documenso.com/developers/self-hosting/setting-up-oauth-providers#google-oauth-gmail
NEXT_PRIVATE_GOOGLE_CLIENT_ID=""
NEXT_PRIVATE_GOOGLE_CLIENT_SECRET=""
NEXT_PRIVATE_OIDC_WELL_KNOWN=""
NEXT_PRIVATE_OIDC_CLIENT_ID=""
NEXT_PRIVATE_OIDC_CLIENT_SECRET=""
NEXT_PRIVATE_OIDC_PROVIDER_LABEL="OIDC"
# This can be used to still allow signups for OIDC connections
# when signup is disabled via `NEXT_PUBLIC_DISABLE_SIGNUP`
NEXT_PRIVATE_OIDC_ALLOW_SIGNUP=""
NEXT_PRIVATE_OIDC_SKIP_VERIFY=""
# [[URLS]]
NEXT_PUBLIC_WEBAPP_URL="http://localhost:3000"
NEXT_PUBLIC_MARKETING_URL="http://localhost:3001"
# URL used by the web app to request itself (e.g. local background jobs)
NEXT_PRIVATE_INTERNAL_WEBAPP_URL="http://localhost:3000"
# [[DATABASE]]
NEXT_PRIVATE_DATABASE_URL="postgres://documenso:password@127.0.0.1:54320/documenso"
# Defines the URL to use for the database when running migrations and other commands that won't work with a connection pool.
NEXT_PRIVATE_DIRECT_DATABASE_URL="postgres://documenso:password@127.0.0.1:54320/documenso"
# [[SIGNING]]
# The transport to use for document signing. Available options: local (default) | gcloud-hsm
NEXT_PRIVATE_SIGNING_TRANSPORT="local"
# OPTIONAL: The passphrase to use for the local file-based signing transport.
NEXT_PRIVATE_SIGNING_PASSPHRASE=
# OPTIONAL: The local file path to the .p12 file to use for the local signing transport.
NEXT_PRIVATE_SIGNING_LOCAL_FILE_PATH=
# OPTIONAL: The base64-encoded contents of the .p12 file to use for the local signing transport.
NEXT_PRIVATE_SIGNING_LOCAL_FILE_CONTENTS=
# OPTIONAL: The path to the Google Cloud HSM key to use for the gcloud-hsm signing transport.
NEXT_PRIVATE_SIGNING_GCLOUD_HSM_KEY_PATH=
# OPTIONAL: The path to the Google Cloud HSM public certificate file to use for the gcloud-hsm signing transport.
NEXT_PRIVATE_SIGNING_GCLOUD_HSM_PUBLIC_CRT_FILE_PATH=
# OPTIONAL: The base64-encoded contents of the Google Cloud HSM public certificate file to use for the gcloud-hsm signing transport.
NEXT_PRIVATE_SIGNING_GCLOUD_HSM_PUBLIC_CRT_FILE_CONTENTS=
# OPTIONAL: The path to the Google Cloud Credentials file to use for the gcloud-hsm signing transport.
NEXT_PRIVATE_SIGNING_GCLOUD_APPLICATION_CREDENTIALS_CONTENTS=
# [[E2E Tests]]
E2E_TEST_AUTHENTICATE_USERNAME="Test User"
E2E_TEST_AUTHENTICATE_USER_EMAIL="testuser@mail.com"
E2E_TEST_AUTHENTICATE_USER_PASSWORD="test_Password123"
# [[STORAGE]]
# OPTIONAL: Defines the storage transport to use. Available options: database (default) | s3
NEXT_PUBLIC_UPLOAD_TRANSPORT="database"
# OPTIONAL: Defines the endpoint to use for the S3 storage transport. Relevant when using third-party S3-compatible providers.
NEXT_PRIVATE_UPLOAD_ENDPOINT="http://127.0.0.1:9002"
# OPTIONAL: Defines the force path style to use for the S3 storage transport. Relevant when using third-party S3-compatible providers.
# This will change it from using virtual hosts <bucket>.domain.com/<path> to fully qualified paths domain.com/<bucket>/<path>
NEXT_PRIVATE_UPLOAD_FORCE_PATH_STYLE="false"
# OPTIONAL: Defines the region to use for the S3 storage transport. Defaults to us-east-1.
NEXT_PRIVATE_UPLOAD_REGION="unknown"
# REQUIRED: Defines the bucket to use for the S3 storage transport.
@ -87,10 +58,8 @@ NEXT_PRIVATE_SMTP_APIKEY_USER=
NEXT_PRIVATE_SMTP_APIKEY=
# OPTIONAL: Defines whether to force the use of TLS.
NEXT_PRIVATE_SMTP_SECURE=
# OPTIONAL: if this is true and NEXT_PRIVATE_SMTP_SECURE is false then TLS is not used even if the server supports STARTTLS extension
NEXT_PRIVATE_SMTP_UNSAFE_IGNORE_TLS=
# REQUIRED: Defines the sender name to use for the from address.
NEXT_PRIVATE_SMTP_FROM_NAME="Documenso"
NEXT_PRIVATE_SMTP_FROM_NAME="No Reply @ Documenso"
# REQUIRED: Defines the email address to use as the from address.
NEXT_PRIVATE_SMTP_FROM_ADDRESS="noreply@documenso.com"
# OPTIONAL: The API key to use for Resend.com
@ -112,13 +81,6 @@ NEXT_PUBLIC_DOCUMENT_SIZE_UPLOAD_LIMIT=5
NEXT_PRIVATE_STRIPE_API_KEY=
NEXT_PRIVATE_STRIPE_WEBHOOK_SECRET=
NEXT_PUBLIC_STRIPE_COMMUNITY_PLAN_MONTHLY_PRICE_ID=
NEXT_PUBLIC_STRIPE_ENTERPRISE_PLAN_MONTHLY_PRICE_ID=
# [[BACKGROUND JOBS]]
NEXT_PRIVATE_JOBS_PROVIDER="local"
NEXT_PRIVATE_TRIGGER_API_KEY=
NEXT_PRIVATE_TRIGGER_API_URL=
NEXT_PRIVATE_INNGEST_EVENT_KEY=
# [[FEATURES]]
# OPTIONAL: Leave blank to disable PostHog and feature flags.
@ -128,11 +90,6 @@ NEXT_PUBLIC_FEATURE_BILLING_ENABLED=
# OPTIONAL: Leave blank to allow users to signup through /signup page.
NEXT_PUBLIC_DISABLE_SIGNUP=
# [[E2E Tests]]
E2E_TEST_AUTHENTICATE_USERNAME="Test User"
E2E_TEST_AUTHENTICATE_USER_EMAIL="testuser@mail.com"
E2E_TEST_AUTHENTICATE_USER_PASSWORD="test_Password123"
# This is only required for the marketing site
# [[REDIS]]
NEXT_PRIVATE_REDIS_URL=

View File

@ -4,12 +4,10 @@ module.exports = {
extends: ['@documenso/eslint-config'],
rules: {
'@next/next/no-img-element': 'off',
'no-unreachable': 'error',
},
settings: {
next: {
rootDir: ['apps/*/'],
},
},
ignorePatterns: ['lingui.config.ts', 'packages/lib/translations/**/*.js'],
};

View File

@ -1,24 +0,0 @@
name: Cache production build binaries
description: 'Cache or restore if necessary'
inputs:
node_version:
required: false
default: v20.x
runs:
using: 'composite'
steps:
- name: Cache production build
uses: actions/cache@v3
id: production-build-cache
with:
path: |
${{ github.workspace }}/apps/web/.next
${{ github.workspace }}/apps/marketing/.next
**/.turbo/**
**/dist/**
key: prod-build-${{ github.run_id }}-${{ hashFiles('package-lock.json') }}
restore-keys: prod-build-
- run: npm run build
shell: bash

View File

@ -1,39 +0,0 @@
name: 'Setup node and cache node_modules'
inputs:
node_version:
required: false
default: v20.x
runs:
using: 'composite'
steps:
- name: Set up Node ${{ inputs.node_version }}
uses: actions/setup-node@v4
with:
node-version: ${{ inputs.node_version }}
- name: Cache npm
uses: actions/cache@v3
with:
path: ~/.npm
key: npm-${{ hashFiles('package-lock.json') }}
restore-keys: npm-
- name: Cache node_modules
uses: actions/cache@v3
id: cache-node-modules
with:
path: |
node_modules
packages/*/node_modules
apps/*/node_modules
key: modules-${{ hashFiles('package-lock.json') }}
- name: Install dependencies
if: steps.cache-node-modules.outputs.cache-hit != 'true'
shell: bash
run: |
npm ci --no-audit
npm run prisma:generate
env:
HUSKY: '0'

View File

@ -1,19 +0,0 @@
name: Install playwright binaries
description: 'Install playwright, cache and restore if necessary'
runs:
using: 'composite'
steps:
- name: Cache playwright
id: cache-playwright
uses: actions/cache@v3
with:
path: |
~/.cache/ms-playwright
${{ github.workspace }}/node_modules/playwright
key: playwright-${{ hashFiles('**/package-lock.json') }}
restore-keys: playwright-
- name: Install playwright
if: steps.cache-playwright.outputs.cache-hit != 'true'
run: npx playwright install --with-deps
shell: bash

View File

@ -1,7 +1,6 @@
name: 'Continuous Integration'
on:
workflow_call:
push:
branches: ['main']
pull_request:
@ -11,6 +10,9 @@ concurrency:
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
env:
HUSKY: 0
jobs:
build_app:
name: Build App
@ -21,12 +23,20 @@ jobs:
with:
fetch-depth: 2
- uses: ./.github/actions/node-install
- name: Install Node.js
uses: actions/setup-node@v4
with:
node-version: 18
cache: npm
- name: Install dependencies
run: npm ci
- name: Copy env
run: cp .env.example .env
- uses: ./.github/actions/cache-build
- name: Build
run: npm run build
build_docker:
name: Build Docker Image
@ -37,31 +47,5 @@ jobs:
with:
fetch-depth: 2
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Cache Docker layers
uses: actions/cache@v4
with:
path: /tmp/.buildx-cache
key: ${{ runner.os }}-buildx-${{ github.sha }}
restore-keys: |
${{ runner.os }}-buildx-
- name: Build Docker Image
uses: docker/build-push-action@v5
with:
push: false
context: .
file: ./docker/Dockerfile
tags: documenso-${{ github.sha }}
cache-from: type=local,src=/tmp/.buildx-cache
cache-to: type=local,dest=/tmp/.buildx-cache-new,mode=max
- # Temp fix
# https://github.com/docker/build-push-action/issues/252
# https://github.com/moby/buildkit/issues/1896
name: Move cache
run: |
rm -rf /tmp/.buildx-cache
mv /tmp/.buildx-cache-new /tmp/.buildx-cache
run: ./docker/build.sh

View File

@ -1,29 +0,0 @@
name: cleanup caches by a branch
on:
pull_request:
types:
- closed
jobs:
cleanup:
runs-on: ubuntu-latest
steps:
- name: Cleanup
run: |
gh extension install actions/gh-actions-cache
echo "Fetching list of cache key"
cacheKeysForPR=$(gh actions-cache list -R $REPO -B $BRANCH -L 100 | cut -f 1 )
## Setting this to not fail the workflow while deleting cache keys.
set +e
echo "Deleting caches..."
for cacheKey in $cacheKeysForPR
do
gh actions-cache delete $cacheKey -R $REPO -B $BRANCH --confirm
done
echo "Done"
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
REPO: ${{ github.repository }}
BRANCH: refs/pull/${{ github.event.pull_request.number }}/merge

View File

@ -25,17 +25,24 @@ jobs:
- name: Checkout repository
uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 18
cache: npm
- name: Install Dependencies
run: npm ci
- name: Copy env
run: cp .env.example .env
- uses: ./.github/actions/node-install
- uses: ./.github/actions/cache-build
- name: Build Documenso
run: npm run build
- name: Initialize CodeQL
uses: github/codeql-action/init@v3
uses: github/codeql-action/init@v2
with:
languages: ${{ matrix.language }}
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3
uses: github/codeql-action/analyze@v2

View File

@ -6,21 +6,29 @@ on:
branches: ['main']
jobs:
e2e_tests:
name: 'E2E Tests'
name: "E2E Tests"
timeout-minutes: 60
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 18
cache: npm
- name: Install dependencies
run: npm ci
- name: Copy env
run: cp .env.example .env
- uses: ./.github/actions/node-install
- name: Start Services
run: npm run dx:up
- uses: ./.github/actions/playwright-install
- name: Install Playwright Browsers
run: npx playwright install --with-deps
- name: Generate Prisma Client
run: npm run prisma:generate -w @documenso/prisma
- name: Create the database
run: npm run prisma:migrate-dev
@ -28,19 +36,14 @@ jobs:
- name: Seed the database
run: npm run prisma:seed
- uses: ./.github/actions/cache-build
- name: Run Playwright tests
run: npm run ci
env:
# Needed since we use next start which will set the NODE_ENV to production
NEXT_PRIVATE_SIGNING_LOCAL_FILE_PATH: './example/cert.p12'
- uses: actions/upload-artifact@v4
- uses: actions/upload-artifact@v3
if: always()
with:
name: test-results
path: 'packages/app-tests/**/test-results/*'
path: "packages/app-tests/**/test-results/*"
retention-days: 30
env:
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}

View File

@ -27,7 +27,7 @@ jobs:
- name: Check Assigned User's Issue Count
id: parse-comment
uses: actions/github-script@v6
uses: actions/github-script@v5
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |

View File

@ -1,25 +0,0 @@
name: Auto Label Assigned Issues
on:
issues:
types: [assigned]
jobs:
label-when-assigned:
runs-on: ubuntu-latest
steps:
- name: Label issue
uses: actions/github-script@v6
with:
github-token: ${{secrets.GITHUB_TOKEN}}
script: |
const issue = context.issue;
// To run only on issues and not on PR
if (github.context.payload.issue.pull_request === undefined) {
const labelResponse = await github.rest.issues.addLabels({
owner: issue.owner,
repo: issue.repo,
issue_number: issue.number,
labels: ['status: assigned']
});
}

View File

@ -17,5 +17,5 @@ jobs:
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
labels: ["status: triage"]
labels: ["needs triage"]
})

View File

@ -2,14 +2,14 @@ name: 'PR Review Reminder'
on:
pull_request:
types: ['opened', 'ready_for_review']
types: ['opened', 'reopened', 'ready_for_review', 'review_requested']
permissions:
pull-requests: write
jobs:
checkPRs:
if: ${{ github.event.pull_request.user.login }} && github.event.action == ('opened' || 'ready_for_review')
if: ${{ github.event.pull_request.user.login }} && github.event.action == ('opened' || 'reopened' || 'ready_for_review' || 'review_requested')
runs-on: ubuntu-latest
steps:
- name: Checkout

View File

@ -1,133 +0,0 @@
name: Publish Docker
on:
push:
branches: ['release']
jobs:
build_and_publish_platform_containers:
name: Build and publish platform containers
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os:
- warp-ubuntu-latest-x64-4x
- warp-ubuntu-latest-arm64-4x
steps:
- uses: actions/checkout@v4
with:
fetch-tags: true
- name: Login to DockerHub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GH_TOKEN }}
- name: Build the docker image
env:
BUILD_PLATFORM: ${{ matrix.os == 'warp-ubuntu-latest-arm64-4x' && 'arm64' || 'amd64' }}
run: |
APP_VERSION="$(git name-rev --tags --name-only $(git rev-parse HEAD) | head -n 1 | sed 's/\^0//')"
GIT_SHA="$(git rev-parse HEAD)"
docker build \
-f ./docker/Dockerfile \
--progress=plain \
-t "documenso/documenso-$BUILD_PLATFORM:latest" \
-t "documenso/documenso-$BUILD_PLATFORM:$GIT_SHA" \
-t "documenso/documenso-$BUILD_PLATFORM:$APP_VERSION" \
-t "ghcr.io/documenso/documenso-$BUILD_PLATFORM:latest" \
-t "ghcr.io/documenso/documenso-$BUILD_PLATFORM:$GIT_SHA" \
-t "ghcr.io/documenso/documenso-$BUILD_PLATFORM:$APP_VERSION" \
.
- name: Push the docker image to DockerHub
run: docker push --all-tags "documenso/documenso-$BUILD_PLATFORM"
env:
BUILD_PLATFORM: ${{ matrix.os == 'warp-ubuntu-latest-arm64-4x' && 'arm64' || 'amd64' }}
- name: Push the docker image to GitHub Container Registry
run: docker push --all-tags "ghcr.io/documenso/documenso-$BUILD_PLATFORM"
env:
BUILD_PLATFORM: ${{ matrix.os == 'warp-ubuntu-latest-arm64-4x' && 'arm64' || 'amd64' }}
create_and_publish_manifest:
name: Create and publish manifest
runs-on: ubuntu-latest
needs: build_and_publish_platform_containers
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-tags: true
- name: Login to DockerHub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GH_TOKEN }}
- name: Create and push DockerHub manifest
run: |
APP_VERSION="$(git name-rev --tags --name-only $(git rev-parse HEAD) | head -n 1 | sed 's/\^0//')"
GIT_SHA="$(git rev-parse HEAD)"
docker manifest create \
documenso/documenso:latest \
--amend documenso/documenso-amd64:latest \
--amend documenso/documenso-arm64:latest \
docker manifest create \
documenso/documenso:$GIT_SHA \
--amend documenso/documenso-amd64:$GIT_SHA \
--amend documenso/documenso-arm64:$GIT_SHA \
docker manifest create \
documenso/documenso:$APP_VERSION \
--amend documenso/documenso-amd64:$APP_VERSION \
--amend documenso/documenso-arm64:$APP_VERSION \
docker manifest push documenso/documenso:latest
docker manifest push documenso/documenso:$GIT_SHA
docker manifest push documenso/documenso:$APP_VERSION
- name: Create and push Github Container Registry manifest
run: |
APP_VERSION="$(git name-rev --tags --name-only $(git rev-parse HEAD) | head -n 1 | sed 's/\^0//')"
GIT_SHA="$(git rev-parse HEAD)"
docker manifest create \
ghcr.io/documenso/documenso:latest \
--amend ghcr.io/documenso/documenso-amd64:latest \
--amend ghcr.io/documenso/documenso-arm64:latest \
docker manifest create \
ghcr.io/documenso/documenso:$GIT_SHA \
--amend ghcr.io/documenso/documenso-amd64:$GIT_SHA \
--amend ghcr.io/documenso/documenso-arm64:$GIT_SHA \
docker manifest create \
ghcr.io/documenso/documenso:$APP_VERSION \
--amend ghcr.io/documenso/documenso-amd64:$APP_VERSION \
--amend ghcr.io/documenso/documenso-arm64:$APP_VERSION \
docker manifest push ghcr.io/documenso/documenso:latest
docker manifest push ghcr.io/documenso/documenso:$GIT_SHA
docker manifest push ghcr.io/documenso/documenso:$APP_VERSION

View File

@ -12,7 +12,7 @@ jobs:
pull-requests: write
steps:
- uses: actions/stale@v5
- uses: actions/stale@v4
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
days-before-pr-stale: 90

View File

@ -1,38 +0,0 @@
# Extract and compile translations for all PRs.
name: 'Extract and compile translations'
on:
workflow_call:
pull_request:
branches: ['main']
concurrency:
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
jobs:
extract_translations:
name: Extract and compile translations
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- name: Checkout
uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.ref }}
- uses: ./.github/actions/node-install
- name: Extract and compile translations
run: |
npm run translate:extract
npm run translate:compile
- name: Check and commit any files created
run: |
git config --global user.name 'github-actions'
git config --global user.email 'github-actions@documenso.com'
git add packages/lib/translations
git diff --staged --quiet --exit-code || (git commit -m "chore: extract translations" && git push)

View File

@ -1,51 +0,0 @@
# This is similar to the "Pull Translations" workflow, but without the conditional check to allow us to
# forcefully pull down translations from Crowdin and create a PR regardless if all the translations are fulfilled.
#
# Intended to be used when we manually update translations in Crowdin UI and want to pull those down when
# they already exist.
name: 'Force pull translations'
on:
workflow_dispatch:
workflow_call:
concurrency:
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
jobs:
pull_translations:
name: Force pull translations
runs-on: ubuntu-latest
environment: Translations
permissions:
contents: write
pull-requests: write
steps:
- name: Checkout
uses: actions/checkout@v4
- uses: ./.github/actions/node-install
- name: Pull translations from Crowdin
uses: crowdin/github-action@v2
with:
upload_sources: false
upload_translations: false
download_translations: true
export_only_approved: false
localization_branch_name: chore/translations
commit_message: 'chore: add translations'
pull_request_title: 'chore: add translations'
env:
# A classic GitHub Personal Access Token with the 'repo' scope selected (the user should have write access to the repository).
GITHUB_TOKEN: ${{ secrets.GH_PAT }}
# A numeric ID, found at https://crowdin.com/project/<projectName>/tools/api
CROWDIN_PROJECT_ID: ${{ secrets.CROWDIN_PROJECT_ID }}
# Visit https://crowdin.com/settings#api-key to create this token
CROWDIN_PERSONAL_TOKEN: ${{ secrets.CROWDIN_PERSONAL_TOKEN }}

View File

@ -1,55 +0,0 @@
# Pull down translations from Crowdin every two hours or when triggered manually.
name: 'Pull translations'
on:
schedule:
- cron: '0 */2 * * *' # Every two hours.
workflow_dispatch:
workflow_call:
concurrency:
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
jobs:
pull_translations:
name: Pull translations
runs-on: ubuntu-latest
environment: Translations
permissions:
contents: write
pull-requests: write
steps:
- name: Checkout
uses: actions/checkout@v4
- uses: ./.github/actions/node-install
- name: Compile translations
id: compile_translations
run: npm run translate:compile -- -- --strict
continue-on-error: true
- name: Pull translations from Crowdin
if: steps.compile_translations.outcome == 'failure'
uses: crowdin/github-action@v2
with:
upload_sources: false
upload_translations: false
download_translations: true
export_only_approved: false
localization_branch_name: chore/translations
commit_message: 'chore: add translations'
pull_request_title: 'chore: add translations'
env:
# A classic GitHub Personal Access Token with the 'repo' scope selected (the user should have write access to the repository).
GITHUB_TOKEN: ${{ secrets.GH_PAT }}
# A numeric ID, found at https://crowdin.com/project/<projectName>/tools/api
CROWDIN_PROJECT_ID: ${{ secrets.CROWDIN_PROJECT_ID }}
# Visit https://crowdin.com/settings#api-key to create this token
CROWDIN_PERSONAL_TOKEN: ${{ secrets.CROWDIN_PERSONAL_TOKEN }}

View File

@ -1,58 +0,0 @@
name: 'Extract and upload translations'
on:
workflow_dispatch:
workflow_call:
push:
branches: ['main']
concurrency:
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
jobs:
extract_translations:
name: Extract and upload translations
runs-on: ubuntu-latest
environment: Translations
permissions:
contents: write
steps:
- name: Checkout
uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.ref }}
- uses: ./.github/actions/node-install
- name: Extract and compile translations
run: |
npm run translate:extract
npm run translate:compile
- name: Check and commit any files created
run: |
git config --global user.name 'github-actions'
git config --global user.email 'github-actions@documenso.com'
git add packages/lib/translations
git diff --staged --quiet --exit-code || (git commit -m "chore: extract translations" && git push)
- name: Compile translations
id: compile_translations
run: npm run translate:compile -- -- --strict
continue-on-error: true
- name: Upload missing translations
if: ${{ steps.compile_translations.outcome == 'failure' }}
uses: crowdin/github-action@v2
with:
upload_sources: true
upload_translations: true
download_translations: false
localization_branch_name: chore/translations
env:
# A numeric ID, found at https://crowdin.com/project/<projectName>/tools/api
CROWDIN_PROJECT_ID: ${{ secrets.CROWDIN_PROJECT_ID }}
# Visit https://crowdin.com/settings#api-key to create this token
CROWDIN_PERSONAL_TOKEN: ${{ secrets.CROWDIN_PERSONAL_TOKEN }}

2
.gitignore vendored
View File

@ -1,7 +1,5 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
packages/prisma/generated/types.ts
# dependencies
node_modules
.pnp

View File

@ -6,7 +6,7 @@ tasks:
set -a; source .env &&
export NEXTAUTH_URL="$(gp url 3000)" &&
export NEXT_PUBLIC_WEBAPP_URL="$(gp url 3000)" &&
export NEXT_PUBLIC_MARKETING_URL="$(gp url 3001)"
export NEXT_PUBLIC_MARKETING_URL="$(gp url 3001)"
command: npm run d
ports:
@ -25,10 +25,20 @@ ports:
- port: 2500
visibility: private
onOpen: ignore
- port: 54320
visibility: private
- port: 54320
visibility: private
onOpen: ignore
github:
prebuilds:
master: true
pullRequests: true
pullRequestsFromForks: true
addCheck: true
addComment: true
addBadge: true
vscode:
extensions:
- aaron-bond.better-comments
@ -37,5 +47,9 @@ vscode:
- esbenp.prettier-vscode
- mikestead.dotenv
- unifiedjs.vscode-mdx
- GitHub.copilot-chat
- GitHub.copilot-labs
- GitHub.copilot
- GitHub.vscode-pull-request-github
- Prisma.prisma
- VisualStudioExptTeam.vscodeintellicode

View File

@ -13,9 +13,4 @@ node "$MONOREPO_ROOT/scripts/copy-wellknown.cjs"
git add "$MONOREPO_ROOT/apps/web/public/"
git add "$MONOREPO_ROOT/apps/marketing/public/"
echo "Extract and compile translations"
npm run translate:extract
npm run translate:compile
git add "$MONOREPO_ROOT/packages/lib/translations/"
npx lint-staged

View File

@ -4,7 +4,6 @@ public
**/**/node_modules
**/**/.next
**/**/public
packages/lib/translations/**/*.js
*.lock
*.log

12
.vscode/settings.json vendored
View File

@ -1,9 +1,7 @@
{
"typescript.tsdk": "node_modules/typescript/lib",
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"source.fixAll": "explicit"
"source.fixAll.eslint": "explicit"
},
"eslint.validate": ["typescript", "typescriptreact", "javascript", "javascriptreact"],
"javascript.preferences.importModuleSpecifier": "non-relative",
@ -11,11 +9,5 @@
"typescript.enablePromptUseWorkspaceTsdk": true,
"files.eol": "\n",
"editor.tabSize": 2,
"editor.insertSpaces": true,
"[prisma]": {
"editor.defaultFormatter": "Prisma.prisma"
},
"[typescriptreact]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
}
"editor.insertSpaces": true
}

View File

@ -1,3 +1,5 @@
>We are nominated for a Product Hunt Gold Kitty 😺✨ and appreciate any support: https://documen.so/kitty
<img src="https://github.com/documenso/documenso/assets/13398220/a643571f-0239-46a6-a73e-6bef38d1228b" alt="Documenso Logo">
<p align="center" style="margin-top: 20px">
@ -27,16 +29,29 @@
<a href="https://vscode.dev/redirect?url=vscode://ms-vscode-remote.remote-containers/cloneInVolume?url=https://github.com/documenso/documenso">
<img alt="open in devcontainer" src="https://img.shields.io/static/v1?label=Dev%20Containers&message=Enabled&color=blue&logo=visualstudiocode" />
</a>
<a href="CODE_OF_CONDUCT.md"><img src="https://img.shields.io/badge/Contributor%20Covenant-2.1-4baaaa.svg" alt="Contributor Covenant"></a>
<a href="code_of_conduct.md"><img src="https://img.shields.io/badge/Contributor%20Covenant-2.1-4baaaa.svg" alt="Contributor Covenant"></a>
</p>
<div align="center">
<img src="https://github.com/documenso/documenso/assets/13398220/d96ed533-6f34-4a97-be9b-442bdb189c69" style="width: 80%;" />
<div>
<img style="display: block; height: 120px; width: 24%"
src="https://github.com/documenso/documenso/assets/1309312/67e08c98-c153-4115-aa2d-77979bb12c94)">
<img style="display: block; height: 120px; width: 24%"
src="https://github.com/documenso/documenso/assets/1309312/040cfbae-3438-4ca3-87f2-ce52c793dcaf">
<img style="display: block; height: 120px; width: 24%"
src="https://github.com/documenso/documenso/assets/1309312/72d445be-41e5-4936-bdba-87ef8e70fa09">
<img style="display: block; height: 120px; width: 24%"
src="https://github.com/documenso/documenso/assets/1309312/d7b86c0f-a755-4476-a022-a608db2c4633">
<img style="display: block; height: 120px; width: 24%"
src=https://github.com/documenso/documenso/assets/1309312/c0f55116-ab82-433f-a266-f3fc8571d69f">
</div>
## About Documenso
## About this project
Signing documents digitally should be fast and easy and should be the best practice for every document signed worldwide. This is technically quite easy today, but it also introduces a new party to every signature: The signing tool providers. While this is not a problem in itself, it should make us think about how we want these providers of trust to work. Documenso aims to be the world's most trusted document-signing tool. This trust is built by empowering you to self-host Documenso and review how it works under the hood.
Signing documents digitally should be fast and easy and should be the best practice for every document signed worldwide.
This is technically quite easy today, but it also introduces a new party to every signature: The signing tool providers. While this is not a problem in itself, it should make us think about how we want these providers of trust to work.
Documenso aims to be the world's most trusted document-signing tool. This trust is built by empowering you to self-host Documenso and review how it works under the hood.
Join us in creating the next generation of open trust infrastructure.
@ -69,28 +84,16 @@ Contact us if you are interested in our Enterprise plan for large organizations
<a href="https://cal.com/timurercan/enterprise-customers?utm_source=banner&utm_campaign=oss"><img alt="Book us with Cal.com" src="https://cal.com/book-with-cal-dark.svg" /></a>
## Tech Stack
<p align="left">
<a href="https://www.typescriptlang.org"><img src="https://shields.io/badge/TypeScript-3178C6?logo=TypeScript&logoColor=FFF&style=flat-square" alt="TypeScript"></a>
<a href="https://nextjs.org/"><img src="https://img.shields.io/badge/next.js-000000?style=flat-square&logo=nextdotjs&logoColor=white" alt="NextJS"></a>
<a href="https://prisma.io"><img width="122" height="20" src="http://made-with.prisma.io/indigo.svg" alt="Made with Prisma" /></a>
<a href="https://tailwindcss.com/"><img src="https://img.shields.io/badge/tailwindcss-0F172A?&logo=tailwindcss" alt="Tailwind CSS"></a>
<a href=""><img src="" alt=""></a>
<a href=""><img src="" alt=""></a>
<a href=""><img src="" alt=""></a>
<a href=""><img src="" alt=""></a>
<a href=""><img src="" alt=""></a>
</p>
- [Typescript](https://www.typescriptlang.org/) - Language
- [Next.js](https://nextjs.org/) - Framework
- [Prisma](https://www.prisma.io/) - ORM
- [Prisma](https://www.prisma.io/) - ORM
- [Tailwind](https://tailwindcss.com/) - CSS
- [shadcn/ui](https://ui.shadcn.com/) - Component Library
- [NextAuth.js](https://next-auth.js.org/) - Authentication
- [react-email](https://react.email/) - Email Templates
- [tRPC](https://trpc.io/) - API
- [@documenso/pdf-sign](https://www.npmjs.com/package/@documenso/pdf-sign) - PDF Signatures (launching soon)
- [Node SignPDF](https://github.com/vbuch/node-signpdf) - Digital Signature
- [React-PDF](https://github.com/wojtekmaj/react-pdf) - Viewing PDFs
- [PDF-Lib](https://github.com/Hopding/pdf-lib) - PDF manipulation
- [Stripe](https://stripe.com/) - Payments
@ -104,7 +107,7 @@ Contact us if you are interested in our Enterprise plan for large organizations
To run Documenso locally, you will need
- Node.js (v18 or above)
- Node.js
- Postgres SQL Database
- Docker (optional)
@ -206,16 +209,7 @@ If you're a visual learner and prefer to watch a video walkthrough of setting up
## Docker
We provide a Docker container for Documenso, which is published on both DockerHub and GitHub Container Registry.
- DockerHub: [https://hub.docker.com/r/documenso/documenso](https://hub.docker.com/r/documenso/documenso)
- GitHub Container Registry: [https://ghcr.io/documenso/documenso](https://ghcr.io/documenso/documenso)
You can pull the Docker image from either of these registries and run it with your preferred container hosting provider.
Please note that you will need to provide environment variables for connecting to the database, mailserver, and so forth.
For detailed instructions on how to configure and run the Docker container, please refer to the [Docker README](./docker/README.md) in the `docker` directory.
🚧 Docker containers and images are current in progress. We are actively working on bringing a simple Docker build and publish pipeline for Documenso.
## Self Hosting
@ -239,14 +233,14 @@ cp .env.example .env
The following environment variables must be set:
- `NEXTAUTH_URL`
- `NEXTAUTH_SECRET`
- `NEXT_PUBLIC_WEBAPP_URL`
- `NEXT_PUBLIC_MARKETING_URL`
- `NEXT_PRIVATE_DATABASE_URL`
- `NEXT_PRIVATE_DIRECT_DATABASE_URL`
- `NEXT_PRIVATE_SMTP_FROM_NAME`
- `NEXT_PRIVATE_SMTP_FROM_ADDRESS`
* `NEXTAUTH_URL`
* `NEXTAUTH_SECRET`
* `NEXT_PUBLIC_WEBAPP_URL`
* `NEXT_PUBLIC_MARKETING_URL`
* `NEXT_PRIVATE_DATABASE_URL`
* `NEXT_PRIVATE_DIRECT_DATABASE_URL`
* `NEXT_PRIVATE_SMTP_FROM_NAME`
* `NEXT_PRIVATE_SMTP_FROM_ADDRESS`
> If you are using a reverse proxy in front of Documenso, don't forget to provide the public URL for both `NEXTAUTH_URL` and `NEXT_PUBLIC_WEBAPP_URL` variables!
@ -261,7 +255,6 @@ npm run prisma:migrate-deploy
Finally, you can start it with:
```
cd apps/web
npm run start
```
@ -303,10 +296,6 @@ WantedBy=multi-user.target
[![Deploy to Koyeb](https://www.koyeb.com/static/images/deploy/button.svg)](https://app.koyeb.com/deploy?type=git&repository=github.com/documenso/documenso&branch=main&name=documenso-app&builder=dockerfile&dockerfile=/docker/Dockerfile)
## Elestio
[![Deploy on Elestio](https://elest.io/images/logos/deploy-to-elestio-btn.png)](https://elest.io/open-source/documenso)
## Troubleshooting
### I'm not receiving any emails when using the developer quickstart.

View File

@ -17,8 +17,7 @@ For the digital signature of your documents you need a signing certificate in .p
`openssl pkcs12 -export -out certificate.p12 -inkey private.key -in certificate.crt`
4. You will be prompted to enter a password for the p12 file. Choose a strong password and remember it, as you will need it to use the certificate (**can be empty for dev certificates**)
5. Place the certificate `/apps/web/resources/certificate.p12` (If the path does not exist, it needs to be created)
5. Place the certificate `/apps/web/resources/certificate.p12`
## Docker

View File

@ -1,36 +0,0 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
/node_modules
/.pnp
.pnp.js
.yarn/install-state.gz
# testing
/coverage
# next.js
/.next/
/out/
# production
/build
# misc
.DS_Store
*.pem
# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# local env files
.env*.local
# vercel
.vercel
# typescript
*.tsbuildinfo
next-env.d.ts

View File

@ -1,36 +0,0 @@
This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app).
## Getting Started
First, run the development server:
```bash
npm run dev
# or
yarn dev
# or
pnpm dev
# or
bun dev
```
Open [http://localhost:3002](http://localhost:3002) with your browser to see the result.
You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file.
This project uses [`next/font`](https://nextjs.org/docs/basic-features/font-optimization) to automatically optimize and load Inter, a custom Google Font.
## Learn More
To learn more about Next.js, take a look at the following resources:
- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome!
## Deploy on Vercel
The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details.

View File

@ -1,17 +0,0 @@
/** @type {import('next').NextConfig} */
const nextConfig = {
transpilePackages: [
'@documenso/assets',
'@documenso/lib',
'@documenso/tailwind-config',
'@documenso/trpc',
'@documenso/ui',
],
};
const withNextra = require('nextra')({
theme: 'nextra-theme-docs',
themeConfig: './theme.config.tsx',
});
module.exports = withNextra(nextConfig);

View File

@ -1,35 +0,0 @@
{
"name": "@documenso/documentation",
"version": "0.1.0",
"private": true,
"scripts": {
"dev": "next dev -p 3002",
"build": "next build",
"start": "next start -p 3002",
"lint:fix": "next lint --fix",
"clean": "rimraf .next && rimraf node_modules",
"copy:pdfjs": "node ../../scripts/copy-pdfjs.cjs"
},
"dependencies": {
"@documenso/assets": "*",
"@documenso/lib": "*",
"@documenso/tailwind-config": "*",
"@documenso/trpc": "*",
"@documenso/ui": "*",
"next": "14.2.6",
"next-plausible": "^3.12.0",
"nextra": "^2.13.4",
"nextra-theme-docs": "^2.13.4",
"react": "^18",
"react-dom": "^18"
},
"devDependencies": {
"@types/node": "^20",
"@types/react": "^18",
"@types/react-dom": "^18",
"autoprefixer": "^10.0.1",
"postcss": "^8",
"tailwindcss": "^3.3.0",
"typescript": "^5"
}
}

View File

@ -1,10 +0,0 @@
import { PlausibleProvider } from '../providers/plausible.tsx';
import '../styles.css';
export default function App({ Component, pageProps }) {
return (
<PlausibleProvider>
<Component {...pageProps} />;
</PlausibleProvider>
);
}

View File

@ -1,34 +0,0 @@
{
"index": {
"type": "page",
"title": "Home",
"display": "hidden",
"theme": {
"timestamp": false
}
},
"users": {
"type": "page",
"title": "Users"
},
"developers": {
"type": "page",
"title": "Developers"
},
"updates": {
"title": "What's New",
"type": "menu",
"items": {
"changelog": {
"title": "Changelog",
"href": "https://documenso.com/changelog",
"newWindow": true
},
"blog": {
"title": "Blog",
"href": "https://documenso.com/blog",
"newWindow": true
}
}
}
}

View File

@ -1,17 +0,0 @@
{
"index": "Introduction",
"-- Development & Deployment": {
"type": "separator",
"title": "Development & Deployment"
},
"local-development": "Local Development",
"self-hosting": "Self Hosting",
"contributing": "Contributing",
"-- API & Integration Guides": {
"type": "separator",
"title": "API & Integration Guides"
},
"public-api": "Public API",
"embedding": "Embedding",
"webhooks": "Webhooks"
}

View File

@ -1,4 +0,0 @@
{
"index": "Getting Started",
"contributing-translations": "Contributing Translations"
}

View File

@ -1,69 +0,0 @@
---
title: Contributing Translations
description: Learn how to contribute translations to Documenso and become part of our community.
---
import { Callout, Steps } from 'nextra/components';
# Contributing Translations
We are always open for help with translations! Currently we utilise AI to generate the initial translations for new languages, which are then improved over time by our awesome community.
If you are looking for development notes on translations, you can find them [here](/developers/local-development/translations).
<Callout type="info">
Contributions are made through GitHub Pull Requests, so you will need a GitHub account to
contribute.
</Callout>
## Overview
We store our translations in PO files, which are located in our GitHub repository [here](https://github.com/documenso/documenso/tree/main/packages/lib/translations).
The translation files are organized into folders represented by their respective language codes (`en` for English, `de` for German, etc). Each language folder contains three PO files:
1. `web.po`: Translations for the web application
2. `marketing.po`: Translations for the marketing application
3. `common.po`: Shared translations between web and marketing
Each PO file contains translations which look like this:
```po
#: apps/web/src/app/(signing)/sign/[token]/no-longer-available.tsx:61
msgid "Want to send slick signing links like this one? <0>Check out Documenso.</0>"
msgstr "Möchten Sie auffällige Signatur-Links wie diesen senden? <0>Überprüfen Sie Documenso.</0>"
```
- `msgid`: The original text in English (never edit this manually)
- `msgstr`: The translated text in the target language
<Callout type="warning">
Notice the `<0>` tags? These represent HTML elements and must remain in both the `msgid` and `msgstr`. Make sure to translate the content between these tags while keeping the tags intact.
</Callout>
## How to Contribute
### Updating Existing Translations
1. Fork the repository.
2. Navigate to the appropriate language folder.
3. Open the PO file you want to update (web.po, marketing.po, or common.po).
4. Make your changes, ensuring you follow the PO file format.
5. Commit your changes with a message such as `chore: update German translations`
6. Create a Pull Request.
### Adding a New Language
If you want to add translations for a language that doesn't exist yet:
1. Create an issue in our GitHub repository requesting the addition of the new language.
2. Wait for our team to review and approve the request.
3. Once approved, we will set up the necessary files and kickstart the translations with AI to provide initial coverage.
## Need Help?
<Callout type="info">
If you have any questions, hop into our [Discord](https://documen.so/discord) and ask us directly!
</Callout>
Thank you for helping make Documenso more accessible to users around the world!

View File

@ -1,117 +0,0 @@
---
title: Getting started
description: Learn how to contribute to Documenso and become part of our community.
---
import { Callout, Steps } from 'nextra/components';
# Contributing to Documenso
If you plan to contribute to Documenso, please take a moment to feel awesome. People like you are what open source is about. Any contributions, no matter how big or small, are highly appreciated.
This guide will help you get started with contributing to Documenso.
## Before Getting Started
<Steps>
### Check the Existing Issues and Pull Requests
Search the existing [issues](https://github.com/documenso/documenso/issues) to see if someone else reported the same issue. Or, check the [existing PRs](https://github.com/documenso/documenso/pulls) to see if someone else is already working on the same thing.
### Creating a New Issue
If there is no issue or PR for the problem you are facing, feel free to create a new issue. Make sure to provide as much detail as possible, including the steps to reproduce the issue.
### Picking an Existing Issue
If you pick an existing issue, take into consideration the discussion on the issue.
### Contributor License Agreement
Accept the [Contributor License Agreement](https://documen.so/cla) to ensure we can accept your contributions.
</Steps>
## Taking Issues
Before taking an issue, ensure that:
- The issue has been assigned the public label.
- The issue is clearly defined and understood.
- No one has been assigned to the issue.
- No one has expressed the intention to work on it.
After that:
1. Comment on the issue with your intention to work on it.
2. Start working on the issue.
Feel free to ask for help, clarification or guidance if needed. We are here to help you.
## Developing
The development branch is `main`, and all pull requests should be made against this branch. Here's how you can get started with developing:
<Steps>
### Set Up Documenso Locally
To set up your local environment, check out the [local development](/developers/local-development) guide.
### Pick a Task
Find an issue to work on or create a new one.
> Before working on an issue, ensure that no one else is working on it. If no one is assigned to the issue, you can pick it up by leaving a comment and asking to assign it to you.
Before creating a new issue, check the existing issues to see if someone else has already reported it.
### Create a New Branch
After you're assigned an issue, you can start working on it. Create a new branch for your feature or bug fix.
When creating a branch, make sure that the branch name:
- starts with the correct prefix: `feat/` for new features, `fix/` for bug fixes, etc.
- includes the issue ID you are working on (if applicable).
- is descriptive.
```sh
git checkout -b feat/issue-id-your-branch-name
## Example
git checkout -b feat/1234-add-share-button-to-articles
```
In the pull request description, include `references #yyyy` or `fixes #yyyy` to link it to the issue you are working on.
### Implement Your Changes
Start working on the issue you picked up and implement the changes. Make sure to test your changes locally and ensure that they work as expected.
### Open a Pull Request
After implementing your changes, open a pull request against the `main` branch.
</Steps>
<Callout type="info">
If you need help getting started, [join us on Discord](https://documen.so/discord).
</Callout>
## Building
Before pushing code or creating pull requests, please ensure you can successfully create a successful production build. You can build the project by running the following command in your terminal:
```bash
npm run build
```
Once the project builds successfully, you can push your code changes or create a pull request.
<Callout type="info">
Remember to run tests and perform any necessary checks before finalizing your changes. As a
result, we can collaborate more effectively and maintain a high standard of code quality in our
project.
</Callout>

View File

@ -1,131 +0,0 @@
---
title: Get Started
description: Learn how to use embedding to bring signing to your own website or application
---
# Embedding
Our embedding feature lets you integrate our document signing experience into your own application or website. Whether you're building with React, Preact, Vue, Svelte, Solid, or using generalized web components, this guide will help you get started with embedding Documenso.
## Availability
Embedding is currently available for all users on a **Teams Plan** and above, as well as **Early Adopter's** within a team (Early Adopters can create a team for free).
In the future, we will roll out a **Platform Plan** that will offer additional enhancements for embedding, including the option to remove Documenso branding for a more customized experience.
## How Embedding Works
Embedding with Documenso allows you to handle document signing in two main ways:
1. **Using Direct Templates**: Using direct templates you can have an evergreen template that upon completion will create a new document within Documenso.
2. **Using a Signing Token**: A more advanced option for those running rich integrations with Documenso already. Given a recipients signing token you can embed the signing experience in your application rather than direct the recipient to Documenso.
_For most use-cases we recommend using direct templates, however if you have a need for a more advanced integration, we are happy to help you get started._
## Supported Frameworks
We support embedding across a range of popular JavaScript frameworks, including:
| Framework | Package |
| --------- | -------------------------------------------------------------------------------- |
| React | [@documenso/embed-react](https://www.npmjs.com/package/@documenso/embed-react) |
| Preact | [@documenso/embed-preact](https://www.npmjs.com/package/@documenso/embed-preact) |
| Vue | [@documenso/embed-vue](https://www.npmjs.com/package/@documenso/embed-vue) |
| Svelte | [@documenso/embed-svelte](https://www.npmjs.com/package/@documenso/embed-svelte) |
| Solid | [@documenso/embed-solid](https://www.npmjs.com/package/@documenso/embed-solid) |
Additionally, we provide **web components** for more generalized use. However, please note that web components are still in their early stages and haven't been extensively tested.
## Embedding with Direct Templates
#### Instructions
To get started with embedding using a Direct Template we will need the URL segment which is also referred to as the token for the template.
You can find your URL/Token by performing the following steps:
1. **Navigate to your team's templates within Documenso**
![Team Templates](/embedding/team-templates.png)
2. **Click on the direct link template you want to embed**
This will copy the URL to your clipboard, e.g. `https://stg-app.documenso.com/d/-WoSwWVT-fYOERS2MI37k`
**For the above url the token is `-WoSwWVT-fYOERS2MI37k`**
3. Provide the token to the `EmbedDirectTemplate` component in your frameworks SDK
```jsx
import { EmbedDirectTemplate } from '@documenso/embed-react';
const MyEmbeddingComponent = () => {
const token = 'YOUR_TOKEN_HERE'; // Replace with the actual token
return <EmbedDirectTemplate token={token} />;
};
```
---
**Converting a regular template to a direct link template**
If you don't currently have any direct link templates you can easily create one by selecting the "Direct Link" option within the actions dropdown on the templates table.
This will show a dialog which will ask you to configure which recipient should be used as the direct link signer.
![Enable Direct Link Template](/embedding/enable-direct-link.png)
---
## Embedding with Signing Tokens
To embed the signing process for an ordinary document, youll need a **document signing token** for the recipient. This token provides the necessary access to load the document and facilitate the signing process securely.
#### Instructions
1. Retrieve the signing token for the recipient document you want to embed
This will typically be done using an API integration where signing tokens are provided as part of the response when creating a document. Alternatively you can manually get a signing link by clicking hovering over a recipients avatar and clicking their email on a document that you own.
![Copy Recipient Token](/embedding/copy-recipient-token.png)
With the signing url on our clipboard we can extract the token the same way we did for the direct link template.
So `https://stg-app.documenso.com/sign/lm7Tp2_yhvFfzdeJQzYQF` will become `lm7Tp2_yhvFfzdeJQzYQF`
2. Provide the token to the `EmbedSignDocument` component in your frameworks SDK
```jsx
import { EmbedSignDocument } from '@documenso/embed-react';
const MyEmbeddingComponent = () => {
const token = 'YOUR_TOKEN_HERE'; // Replace with the actual token
return <EmbedSignDocument token={token} />;
};
```
---
## Using Embedding in Your Application
Once you've obtained the appropriate tokens, you can integrate the signing experience into your application. For framework-specific instructions, please refer to the guides provided in our documentation for:
- [React](/developers/embedding/react)
- [Preact](/developers/embedding/preact)
- [Vue](/developers/embedding/vue)
- [Svelte](/developers/embedding/svelte)
- [Solid](/developers/embedding/solid)
If you're using **web components**, the integration process is slightly different. Keep in mind that web components are currently less tested but can still provide flexibility for general use cases.
## Stay Tuned for the Platform Plan
While embedding is already a powerful tool, we're working on a **Platform Plan** that will introduce even more functionality. This plan will offer:
- Additional customization options
- The ability to remove Documenso branding
- Additional controls for the signing experience
More details will be shared as we approach the release.

View File

@ -1,77 +0,0 @@
---
title: Preact Integration
description: Learn how to use our embedding SDK within your Preact application.
---
# Preact Integration
Our Preact SDK provides a simple way to embed a signing experience within your Preact application. It supports both direct link templates and signing tokens.
## Installation
To install the SDK, run the following command:
```bash
npm install @documenso/embed-preact
```
## Usage
To embed a signing experience, you'll need to provide the token for the document you want to embed. This can be done in a few different ways, depending on your use case.
### Direct Link Template
If you have a direct link template, you can simply provide the token for the template to the `EmbedDirectTemplate` component.
```jsx
import { EmbedDirectTemplate } from '@documenso/embed-preact';
const MyEmbeddingComponent = () => {
const token = 'YOUR_TOKEN_HERE'; // Replace with the actual token
return <EmbedDirectTemplate token={token} />;
};
```
#### Props
| Prop | Type | Description |
| ------------------- | ------------------- | ------------------------------------------------------------------------------------------ |
| token | string | The token for the document you want to embed |
| host | string (optional) | The host to be used for the signing experience, relevant for self-hosters |
| name | string (optional) | The name the signer that will be used by default for signing |
| lockName | boolean (optional) | Whether or not the name field should be locked disallowing modifications |
| email | string (optional) | The email the signer that will be used by default for signing |
| lockEmail | boolean (optional) | Whether or not the email field should be locked disallowing modifications |
| externalId | string (optional) | The external ID to be used for the document that will be created upon completion |
| onDocumentReady | function (optional) | A callback function that will be called when the document is loaded and ready to be signed |
| onDocumentCompleted | function (optional) | A callback function that will be called when the document has been completed |
| onDocumentError | function (optional) | A callback function that will be called when an error occurs with the document |
| onFieldSigned | function (optional) | A callback function that will be called when a field has been signed |
| onFieldUnsigned | function (optional) | A callback function that will be called when a field has been unsigned |
### Signing Token
If you have a signing token, you can provide it to the `EmbedSignDocument` component.
```jsx
import { EmbedSignDocument } from '@documenso/embed-preact';
const MyEmbeddingComponent = () => {
const token = 'YOUR_TOKEN_HERE'; // Replace with the actual token
return <EmbedSignDocument token={token} />;
};
```
#### Props
| Prop | Type | Description |
| ------------------- | ------------------- | ------------------------------------------------------------------------------------------ |
| token | string | The token for the document you want to embed |
| host | string (optional) | The host to be used for the signing experience, relevant for self-hosters |
| name | string (optional) | The name the signer that will be used by default for signing |
| lockName | boolean (optional) | Whether or not the name field should be locked disallowing modifications |
| onDocumentReady | function (optional) | A callback function that will be called when the document is loaded and ready to be signed |
| onDocumentCompleted | function (optional) | A callback function that will be called when the document has been completed |
| onDocumentError | function (optional) | A callback function that will be called when an error occurs with the document |

View File

@ -1,77 +0,0 @@
---
title: React Integration
description: Learn how to use our embedding SDK within your React application.
---
# React Integration
Our React SDK provides a simple way to embed a signing experience within your React application. It supports both direct link templates and signing tokens.
## Installation
To install the SDK, run the following command:
```bash
npm install @documenso/embed-react
```
## Usage
To embed a signing experience, you'll need to provide the token for the document you want to embed. This can be done in a few different ways, depending on your use case.
### Direct Link Template
If you have a direct link template, you can simply provide the token for the template to the `EmbedDirectTemplate` component.
```jsx
import { EmbedDirectTemplate } from '@documenso/embed-react';
const MyEmbeddingComponent = () => {
const token = 'YOUR_TOKEN_HERE'; // Replace with the actual token
return <EmbedDirectTemplate token={token} />;
};
```
#### Props
| Prop | Type | Description |
| ------------------- | ------------------- | ------------------------------------------------------------------------------------------ |
| token | string | The token for the document you want to embed |
| host | string (optional) | The host to be used for the signing experience, relevant for self-hosters |
| name | string (optional) | The name the signer that will be used by default for signing |
| lockName | boolean (optional) | Whether or not the name field should be locked disallowing modifications |
| email | string (optional) | The email the signer that will be used by default for signing |
| lockEmail | boolean (optional) | Whether or not the email field should be locked disallowing modifications |
| externalId | string (optional) | The external ID to be used for the document that will be created upon completion |
| onDocumentReady | function (optional) | A callback function that will be called when the document is loaded and ready to be signed |
| onDocumentCompleted | function (optional) | A callback function that will be called when the document has been completed |
| onDocumentError | function (optional) | A callback function that will be called when an error occurs with the document |
| onFieldSigned | function (optional) | A callback function that will be called when a field has been signed |
| onFieldUnsigned | function (optional) | A callback function that will be called when a field has been unsigned |
### Signing Token
If you have a signing token, you can provide it to the `EmbedSignDocument` component.
```jsx
import { EmbedSignDocument } from '@documenso/embed-react';
const MyEmbeddingComponent = () => {
const token = 'YOUR_TOKEN_HERE'; // Replace with the actual token
return <EmbedSignDocument token={token} />;
};
```
#### Props
| Prop | Type | Description |
| ------------------- | ------------------- | ------------------------------------------------------------------------------------------ |
| token | string | The token for the document you want to embed |
| host | string (optional) | The host to be used for the signing experience, relevant for self-hosters |
| name | string (optional) | The name the signer that will be used by default for signing |
| lockName | boolean (optional) | Whether or not the name field should be locked disallowing modifications |
| onDocumentReady | function (optional) | A callback function that will be called when the document is loaded and ready to be signed |
| onDocumentCompleted | function (optional) | A callback function that will be called when the document has been completed |
| onDocumentError | function (optional) | A callback function that will be called when an error occurs with the document |

View File

@ -1,77 +0,0 @@
---
title: Solid.js Integration
description: Learn how to use our embedding SDK within your Solid.js application.
---
# Solid.js Integration
Our Solid.js SDK provides a simple way to embed a signing experience within your Solid.js application. It supports both direct link templates and signing tokens.
## Installation
To install the SDK, run the following command:
```bash
npm install @documenso/embed-solid
```
## Usage
To embed a signing experience, you'll need to provide the token for the document you want to embed. This can be done in a few different ways, depending on your use case.
### Direct Link Template
If you have a direct link template, you can simply provide the token for the template to the `EmbedDirectTemplate` component.
```jsx
import { EmbedDirectTemplate } from '@documenso/embed-solid';
const MyEmbeddingComponent = () => {
const token = 'YOUR_TOKEN_HERE'; // Replace with the actual token
return <EmbedDirectTemplate token={token} />;
};
```
#### Props
| Prop | Type | Description |
| ------------------- | ------------------- | ------------------------------------------------------------------------------------------ |
| token | string | The token for the document you want to embed |
| host | string (optional) | The host to be used for the signing experience, relevant for self-hosters |
| name | string (optional) | The name the signer that will be used by default for signing |
| lockName | boolean (optional) | Whether or not the name field should be locked disallowing modifications |
| email | string (optional) | The email the signer that will be used by default for signing |
| lockEmail | boolean (optional) | Whether or not the email field should be locked disallowing modifications |
| externalId | string (optional) | The external ID to be used for the document that will be created upon completion |
| onDocumentReady | function (optional) | A callback function that will be called when the document is loaded and ready to be signed |
| onDocumentCompleted | function (optional) | A callback function that will be called when the document has been completed |
| onDocumentError | function (optional) | A callback function that will be called when an error occurs with the document |
| onFieldSigned | function (optional) | A callback function that will be called when a field has been signed |
| onFieldUnsigned | function (optional) | A callback function that will be called when a field has been unsigned |
### Signing Token
If you have a signing token, you can provide it to the `EmbedSignDocument` component.
```jsx
import { EmbedSignDocument } from '@documenso/embed-solid';
const MyEmbeddingComponent = () => {
const token = 'YOUR_TOKEN_HERE'; // Replace with the actual token
return <EmbedSignDocument token={token} />;
};
```
#### Props
| Prop | Type | Description |
| ------------------- | ------------------- | ------------------------------------------------------------------------------------------ |
| token | string | The token for the document you want to embed |
| host | string (optional) | The host to be used for the signing experience, relevant for self-hosters |
| name | string (optional) | The name the signer that will be used by default for signing |
| lockName | boolean (optional) | Whether or not the name field should be locked disallowing modifications |
| onDocumentReady | function (optional) | A callback function that will be called when the document is loaded and ready to be signed |
| onDocumentCompleted | function (optional) | A callback function that will be called when the document has been completed |
| onDocumentError | function (optional) | A callback function that will be called when an error occurs with the document |

View File

@ -1,79 +0,0 @@
---
title: Svelte Integration
description: Learn how to use our embedding SDK within your Svelte application.
---
# Svelte Integration
Our Svelte SDK provides a simple way to embed a signing experience within your Svelte application. It supports both direct link templates and signing tokens.
## Installation
To install the SDK, run the following command:
```bash
npm install @documenso/embed-svelte
```
## Usage
To embed a signing experience, you'll need to provide the token for the document you want to embed. This can be done in a few different ways, depending on your use case.
### Direct Link Template
If you have a direct link template, you can simply provide the token for the template to the `EmbedDirectTemplate` component.
```html
<script lang="ts">
import { EmbedDirectTemplate } from '@documenso/embed-svelte';
const token = 'YOUR_TOKEN_HERE'; // Replace with the actual token
</script>
<template>
<EmbedDirectTemplate {token} />
</template>
```
#### Props
| Prop | Type | Description |
| ------------------- | ------------------- | ------------------------------------------------------------------------------------------ |
| token | string | The token for the document you want to embed |
| host | string (optional) | The host to be used for the signing experience, relevant for self-hosters |
| name | string (optional) | The name the signer that will be used by default for signing |
| lockName | boolean (optional) | Whether or not the name field should be locked disallowing modifications |
| email | string (optional) | The email the signer that will be used by default for signing |
| lockEmail | boolean (optional) | Whether or not the email field should be locked disallowing modifications |
| externalId | string (optional) | The external ID to be used for the document that will be created upon completion |
| onDocumentReady | function (optional) | A callback function that will be called when the document is loaded and ready to be signed |
| onDocumentCompleted | function (optional) | A callback function that will be called when the document has been completed |
| onDocumentError | function (optional) | A callback function that will be called when an error occurs with the document |
| onFieldSigned | function (optional) | A callback function that will be called when a field has been signed |
| onFieldUnsigned | function (optional) | A callback function that will be called when a field has been unsigned |
### Signing Token
If you have a signing token, you can provide it to the `EmbedSignDocument` component.
```jsx
import { EmbedSignDocument } from '@documenso/embed-svelte';
const MyEmbeddingComponent = () => {
const token = 'YOUR_TOKEN_HERE'; // Replace with the actual token
return <EmbedSignDocument token={token} />;
};
```
#### Props
| Prop | Type | Description |
| ------------------- | ------------------- | ------------------------------------------------------------------------------------------ |
| token | string | The token for the document you want to embed |
| host | string (optional) | The host to be used for the signing experience, relevant for self-hosters |
| name | string (optional) | The name the signer that will be used by default for signing |
| lockName | boolean (optional) | Whether or not the name field should be locked disallowing modifications |
| onDocumentReady | function (optional) | A callback function that will be called when the document is loaded and ready to be signed |
| onDocumentCompleted | function (optional) | A callback function that will be called when the document has been completed |
| onDocumentError | function (optional) | A callback function that will be called when an error occurs with the document |

View File

@ -1,79 +0,0 @@
---
title: Vue Integration
description: Learn how to use our embedding SDK within your Vue application.
---
# Vue Integration
Our Vue SDK provides a simple way to embed a signing experience within your Vue application. It supports both direct link templates and signing tokens.
## Installation
To install the SDK, run the following command:
```bash
npm install @documenso/embed-vue
```
## Usage
To embed a signing experience, you'll need to provide the token for the document you want to embed. This can be done in a few different ways, depending on your use case.
### Direct Link Template
If you have a direct link template, you can simply provide the token for the template to the `EmbedDirectTemplate` component.
```html
<script setup lang="ts">
import { EmbedDirectTemplate } from '@documenso/embed-vue';
const token = ref('YOUR_TOKEN_HERE'); // Replace with the actual token
</script>
<template>
<EmbedDirectTemplate :token="token" />
</template>
```
#### Props
| Prop | Type | Description |
| ------------------- | ------------------- | ------------------------------------------------------------------------------------------ |
| token | string | The token for the document you want to embed |
| host | string (optional) | The host to be used for the signing experience, relevant for self-hosters |
| name | string (optional) | The name the signer that will be used by default for signing |
| lockName | boolean (optional) | Whether or not the name field should be locked disallowing modifications |
| email | string (optional) | The email the signer that will be used by default for signing |
| lockEmail | boolean (optional) | Whether or not the email field should be locked disallowing modifications |
| externalId | string (optional) | The external ID to be used for the document that will be created upon completion |
| onDocumentReady | function (optional) | A callback function that will be called when the document is loaded and ready to be signed |
| onDocumentCompleted | function (optional) | A callback function that will be called when the document has been completed |
| onDocumentError | function (optional) | A callback function that will be called when an error occurs with the document |
| onFieldSigned | function (optional) | A callback function that will be called when a field has been signed |
| onFieldUnsigned | function (optional) | A callback function that will be called when a field has been unsigned |
### Signing Token
If you have a signing token, you can provide it to the `EmbedSignDocument` component.
```jsx
import { EmbedSignDocument } from '@documenso/embed-vue';
const MyEmbeddingComponent = () => {
const token = 'YOUR_TOKEN_HERE'; // Replace with the actual token
return <EmbedSignDocument token={token} />;
};
```
#### Props
| Prop | Type | Description |
| ------------------- | ------------------- | ------------------------------------------------------------------------------------------ |
| token | string | The token for the document you want to embed |
| host | string (optional) | The host to be used for the signing experience, relevant for self-hosters |
| name | string (optional) | The name the signer that will be used by default for signing |
| lockName | boolean (optional) | Whether or not the name field should be locked disallowing modifications |
| onDocumentReady | function (optional) | A callback function that will be called when the document is loaded and ready to be signed |
| onDocumentCompleted | function (optional) | A callback function that will be called when the document has been completed |
| onDocumentError | function (optional) | A callback function that will be called when an error occurs with the document |

View File

@ -1,18 +0,0 @@
---
title: Developer Documentation
description: Learn how to run Documenso locally, use our API, integrate webhooks, contribute to the project, and self-host Documenso.
---
import { Card, Cards } from 'nextra/components';
# Developer Documentation
The developer documentation is a comprehensive guide to help you:
<Cards>
<Card title="Set up dev environment" href="/developers/local-development" />
<Card title="Use the API" href="/developers/public-api" />
<Card title="Integrate webhooks" href="/developers/webhooks" />
<Card title="Contribute to the project" href="/developers/contributing" />
<Card title="Self-host Documenso" href="/developers/self-hosting" />
</Cards>

View File

@ -1,8 +0,0 @@
{
"index": "Get Started",
"quickstart": "Developer Quickstart",
"manual": "Manual Setup",
"gitpod": "Gitpod",
"signing-certificate": "Signing Certificate",
"translations": "Translations"
}

View File

@ -1,10 +0,0 @@
---
title: Run in Gitpod
description: Get started with Documenso in a ready-to-use Gitpod workspace in your browser.
---
# Run in Gitpod
Click below to launch a ready-to-use Gitpod workspace in your browser.
[![Open in Gitpod](https://gitpod.io/button/open-in-gitpod.svg)](https://gitpod.io/#https://github.com/documenso/documenso)

View File

@ -1,63 +0,0 @@
---
title: Local Development
description: Learn how to set up Documenso for local development.
---
# Local development
There are multiple ways of setting up Documenso for local development. At the moment of writing this documentation, there are 3 ways of running Documenso locally:
- [Using the developer quickstart with Docker](/developers/local-development/quickstart)
- [Manually setting up the development environment](/developers/local-development/manual)
- [Using Gitpod](/developers/local-development/gitpod)
Pick the one that fits your needs the best.
## Tech Stack
- [Typescript](https://www.typescriptlang.org/) - Language
- [Next.js](https://nextjs.org/) - Framework
- [Prisma](https://www.prisma.io/) - ORM
- [Tailwind](https://tailwindcss.com/) - CSS
- [shadcn/ui](https://ui.shadcn.com/) - Component Library
- [NextAuth.js](https://next-auth.js.org/) - Authentication
- [react-email](https://react.email/) - Email Templates
- [tRPC](https://trpc.io/) - API
- [@documenso/pdf-sign](https://www.npmjs.com/package/@documenso/pdf-sign) - PDF Signatures
- [React-PDF](https://github.com/wojtekmaj/react-pdf) - Viewing PDFs
- [PDF-Lib](https://github.com/Hopding/pdf-lib) - PDF manipulation
- [Stripe](https://stripe.com/) - Payments
- [Vercel](https://vercel.com) - Hosting
<div className="mt-16 flex items-center justify-center gap-4">
<a href="https://documen.so/discord">
<img
src="https://img.shields.io/badge/Discord-documen.so/discord-%235865F2"
alt="Join Documenso on Discord"
/>
</a>
<a href="https://github.com/documenso/documenso/stargazers">
<img src="https://img.shields.io/github/stars/documenso/documenso" alt="Github Stars" />
</a>
<a href="https://github.com/documenso/documenso/blob/main/LICENSE">
<img src="https://img.shields.io/badge/license-AGPLv3-purple" alt="License" />
</a>
<a href="https://github.com/documenso/documenso/pulse">
<img
src="https://img.shields.io/github/commit-activity/m/documenso/documenso"
alt="Commits-per-month"
/>
</a>
<a href="https://vscode.dev/redirect?url=vscode://ms-vscode-remote.remote-containers/cloneInVolume?url=https://github.com/documenso/documenso">
<img
alt="open in devcontainer"
src="https://img.shields.io/static/v1?label=Dev%20Containers&message=Enabled&color=blue&logo=visualstudiocode"
/>
</a>
<a href="https://github.com/documenso/documenso/blob/main/CODE_OF_CONDUCT.md">
<img
src="https://img.shields.io/badge/Contributor%20Covenant-2.1-4baaaa.svg"
alt="Contributor Covenant"
/>
</a>
</div>

View File

@ -1,77 +0,0 @@
---
title: Manual Setup
description: Manually set up Documenso on your machine for local development.
---
import { Callout, Steps } from 'nextra/components';
# Manual Setup
Follow these steps to set up Documenso on your local machine:
<Steps>
### Fork Documenso
Fork the [Documenso repository](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/about-forks) to your GitHub account.
### Clone Repository
After forking the repository, clone it to your local device by using the following command:
```bash
git clone https://github.com/<your-username>/documenso
```
### Install Dependencies
Run `npm i` in the root directory to install the dependencies required for the project.
### Set Up Environment Variables
Set up the following environment variables in the `.env` file:
```bash
NEXTAUTH_URL
NEXTAUTH_SECRET
NEXT_PUBLIC_WEBAPP_URL
NEXT_PUBLIC_MARKETING_URL
NEXT_PRIVATE_DATABASE_URL
NEXT_PRIVATE_DIRECT_DATABASE_URL
NEXT_PRIVATE_SMTP_FROM_NAME
NEXT_PRIVATE_SMTP_FROM_ADDRESS
```
Alternatively, you can run `cp .env.example .env` to get started with our handpicked defaults.
### Create Database Schema
Create the database schema by running the following command:
```bash
npm run prisma:migrate-dev
```
### Optional: Seed the Database
Seed the database with test data by running the following command:
```bash
npm run prisma:seed -w @documenso/prisma
```
### Start the Application
Run `npm run dev` in the root directory to start the application.
### Access the Application
Access the Documenso application by visiting `http://localhost:3000` in your web browser.
</Steps>
<Callout type="info">
Optional: Create your signing certificate. To generate your own using these steps and a Linux
Terminal or Windows Subsystem for Linux (WSL), see **[Create your signing
certificate](/developers/local-development/signing-certificate)**.
</Callout>

View File

@ -1,66 +0,0 @@
---
title: Developer Quickstart
description: Quickly set up Documenso on your machine for local development with Docker and Docker Compose.
---
import { Callout, Steps } from 'nextra/components';
# Developer Quickstart
<Callout type="info">
**Note**: This guide assumes that you have both [docker](https://docs.docker.com/get-docker/) and
[docker-compose](https://docs.docker.com/compose/) installed on your machine.
</Callout>
Want to get up and running quickly? Follow these steps:
<Steps>
### Fork Documenso
Fork the [Documenso repository](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/about-forks) to your GitHub account.
### Clone Repository
After forking the repository, clone it to your local device by using the following command:
```bash
git clone https://github.com/<your-username>/documenso
```
### Set Up Environment Variables
Set up your environment variables in the `.env` file using the `.env.example` file as a reference.
Alternatively, you can run `cp .env.example .env` to get started with our handpicked defaults.
### Start Database and Mail Server
Run `npm run dx` in the root directory.
This will spin up a Postgres database and inbucket mailserver in a docker container.
### Start the Application
Run `npm run dev` in the root directory to start the application.
### (Optional) Fasten the Process
Want it even faster? Just use:
```sh
npm run d
```
</Steps>
### Access Points for the Project
You can access the following services:
- Main application - http://localhost:3000
- Incoming Mail Access - http://localhost:9000
- Database Connection Details:
- Port: 54320
- Connection: Use your favourite database client to connect to the database.
- S3 Storage Dashboard - http://localhost:9001

View File

@ -1,61 +0,0 @@
---
title: Signing Certificate
description: Learn how to create a free, self-signed certificate for local development.
---
import { Callout, Steps } from 'nextra/components';
# Create Your Signing Certificate
Digitally signing documents requires a signing certificate in `.p12` format. You can either purchase one or create a free self-signed certificate.
Follow the steps below to create a free, self-signed certificate for local development.
<Steps>
### Generate Private Key
Generate a private key using OpenSSL by running the following command:
```bash
openssl genrsa -out private.key 2048
```
This command generates a 2048-bit RSA key.
### Generate Self-Signed Certificate
Using the private key, generate a self-signed certificate by running the following command:
```bash
openssl req -new -x509 -key private.key -out certificate.crt -days 365
```
You will be prompted to enter some information, such as the certificate's Common Name (CN). Ensure that you provide the correct details. The `—days` parameter specifies the certificate's validity period.
### Create `p12` Certificate
Combine the private key and the self-signed certificate to create a `.p12` certificate. Use the following command:
```bash
openssl pkcs12 -export -out certificate.p12 -inkey private.key -in certificate.crt
```
<Callout type="warning">
If you get the error "Error: Failed to get private key bags", add the `-legacy` flag to the command `openssl pkcs12 -export -out certificate.p12 -inkey private.key -in certificate.crt -legacy`.
</Callout>
### `p12` Certificate Password
When you create the `.p12` certificate, you will be prompted to enter a password. Enter a strong password and keep it secure. Remember this password, as it will be required when using the certificate.
Note that for local development, the password can be left empty.
### Add Certificate to the Project
Finally, add the certificate to the project. Place the `certificate.p12` file in the `/apps/web/resources` directory. If the directory doesn't exist, create it.
The final file path should be `/apps/web/resources/certificate.p12`.
</Steps>

View File

@ -1,128 +0,0 @@
---
title: Translations
description: Handling translations in code.
---
# About
Documenso uses the following stack to handle translations:
- [Lingui](https://lingui.dev/) - React i10n library
- [Crowdin](https://crowdin.com/) - Handles syncing translations
- [OpenAI](https://openai.com/) - Provides AI translations
Additional reading can be found in the [Lingui documentation](https://lingui.dev/introduction).
## Requirements
You **must** insert **`setupI18nSSR()`** when creating any of the following files:
- Server layout.tsx
- Server page.tsx
- Server loading.tsx
Server meaning it does not have `'use client'` in it.
```tsx
import { setupI18nSSR } from '@documenso/lib/client-only/providers/i18n.server';
export default function SomePage() {
setupI18nSSR(); // Required if there are translations within the page, or nested in components.
// Rest of code...
}
```
Additional information can be found [here.](https://lingui.dev/tutorials/react-rsc#pages-layouts-and-lingui)
## Quick guide
If you require more in-depth information, please see the [Lingui documentation](https://lingui.dev/introduction).
### HTML
Wrap all text to translate in **`<Trans></Trans>`** tags exported from **@lingui/macro** (not @lingui/react).
```html
<h1>
<Trans>Title</Trans>
</h1>
```
For text that is broken into elements, but represent a whole sentence, you must wrap it in a Trans tag so ensure the full message is extracted correctly.
```html
<h1>
<Trans>
This is one
<span className="text-foreground/60">full</span>
<a href="https://documenso.com">sentence</a>
</Trans>
</h1>
```
### Constants outside of react components
```tsx
import { Trans, msg } from '@lingui/macro';
import { useLingui } from '@lingui/react';
// Wrap text in msg`text to translate` when it's in a constant here, or another file/package.
export const CONSTANT_WITH_MSG = {
foo: msg`Hello`,
bar: msg`World`,
};
export const SomeComponent = () => {
const { _ } = useLingui();
return (
<div>
{/* This will render the correct translated text. */}
<p>{_(CONSTANT_WITH_MSG.foo)}</p>
</div>
);
};
```
### Plurals
Lingui provides a Plural component to make it easy. See full documentation [here.](https://lingui.dev/ref/macro#plural-1)
```tsx
// Basic usage.
<Plural one="1 Recipient" other="# Recipients" value={recipients.length} />
```
### Dates
Lingui provides a [DateTime instance](https://lingui.dev/ref/core#i18n.date) with the configured locale.
#### Server components
Note that the i18n instance is coming from **setupI18nSSR**.
```tsx
import { Trans } from '@lingui/macro';
import { useLingui } from '@lingui/react';
export const SomeComponent = () => {
const { i18n } = setupI18nSSR();
return <Trans>The current date is {i18n.date(new Date(), { dateStyle: 'short' })}</Trans>;
};
```
#### Client components
Note that the i18n instance is coming from the **import**.
```tsx
import { i18n } from '@lingui/core';
import { Trans } from '@lingui/macro';
import { useLingui } from '@lingui/react';
export const SomeComponent = () => {
return <Trans>The current date is {i18n.date(new Date(), { dateStyle: 'short' })}</Trans>;
};
```

View File

@ -1,5 +0,0 @@
{
"index": "Get Started",
"authentication": "Authentication",
"versioning": "Versioning"
}

View File

@ -1,67 +0,0 @@
---
title: API Authentication
description: Learn how to create a Documenso API key and authenticate your API requests.
---
# API Authentication
Documenso uses API keys for authentication. An API key is a unique token that is generated for each client. The client must provide the key whenever it makes an API call. This way, Documenso can identify the clients making the requests and authorize their access to the API.
## Creating an API Key
To create an API key, navigate to the user settings page. Click on your avatar in the top right corner of the dashboard and select "**[User settings](https://app.documenso.com/settings)**" from the dropdown menu.
![A screenshot of the Documenso's dashboard that shows the dropdown menu when you click on your user avatar](/public-api-images/documenso-user-dropdown-menu.webp)
Once you're on the user settings page, navigate to the "**[API Tokens](https://app.documenso.com/settings/tokens)**" tab. The "API Token" page lists your existing keys and enables you to create new ones.
![A screenshot of the Documenso's user settings page that shows the API Tokens page](/public-api-images/api-tokens-page-documenso.webp)
To create a new API key, you must:
- Choose a name (e.g. "zapier-key")
- We recommend using a descriptive name that helps you quickly identify the key and its purpose.
- Choose an expiration date
- You can set the key never to expire or choose when to become invalid: 7 days, 1 month, 3 months, 6 months, or 1 year.
After providing the required information, click the "Create token" button to generate the API key.
![A screenshot of the newly created API token in the Documenso dashboard](/public-api-images/documenso-api-key-blurred.webp)
Once you've created the token, Documenso will display the key on the screen. Make sure to copy the key and store it securely. You won't be able to see the key again once you refresh/leave the page.
## Using the API Key
You must include the API key in the `Authorization` request header to authenticate your API requests. The format is `Authorization: api_xxxxxxxxxxxxxxxx`.
Here's a sample API request using cURL:
```bash
curl --location 'https://app.documenso.com/api/v1/documents?page=1&perPage=1' \
--header 'Authorization: api_xxxxxxxxxxxxxxxx'
```
Here's a sample response from the API based on the above cURL request:
```json
{
"documents": [
{
"id": 11,
"userId": 2,
"teamId": null,
"title": "documenso",
"status": "PENDING",
"documentDataId": "ab2ecm1npk11rt5sp398waf7h",
"createdAt": "2024-04-25T11:05:18.420Z",
"updatedAt": "2024-04-25T11:05:36.328Z",
"completedAt": null
}
],
"totalPages": 1
}
```
![A screenshot of a cURL request to the Documenso public API with the API key in the Authorization header](/public-api-images/documenso-api-authorization.webp)
The API key has access to your account and all its resources. Please keep it secure and do not share it with others. If you suspect your key has been compromised, you can revoke it from the "API Tokens" page in your user settings.

View File

@ -1,22 +0,0 @@
---
title: Public API
description: Learn how to interact with your documents programmatically using the Documenso public API.
---
# Public API
Documenso provides a public REST API enabling you to interact with your documents programmatically. The API exposes various HTTP endpoints that allow you to perform operations such as:
- retrieving, uploading, deleting, and sending documents for signing
- creating, updating, and deleting recipients
- creating, updating, and deleting document fields
The documentation walks you through creating API keys and using them to authenticate your API requests. You'll also learn about the available endpoints, request and response formats, and how to use the API.
## Swagger Documentation
The [Swagger documentation](https://app.documenso.com/api/v1/openapi) also provides information about the API endpoints, request parameters, response formats, and authentication methods.
## Availability
The API is available to individual users and teams.

View File

@ -1,18 +0,0 @@
---
title: API Versioning
description: Versioning information for the Documenso public API.
---
import { Callout } from 'nextra/components';
# API Versioning
Documenso uses API versioning to manage changes to the public API. This allows us to introduce new features, fix bugs, and make other changes without breaking existing integrations.
<Callout type="info">The current version of the API is `v1`.</Callout>
The API version is specified in the URL. For example, the base URL for the `v1` API is `https://app.documenso.com/api/v1`.
We may make changes to the API without incrementing the version number. We will always try to avoid breaking changes, but in some cases, it may be necessary to make changes that are not backward compatible. In these cases, we will increment the version number and provide information about the changes in the release notes.
Also, we may deprecate certain features or endpoints in the API. When we deprecate a feature or endpoint, we will provide information about the deprecation in the release notes and give a timeline for when the feature or endpoint will be removed.

View File

@ -1,6 +0,0 @@
{
"index": "Getting Started",
"signing-certificate": "Signing Certificate",
"how-to": "How To",
"setting-up-oauth-providers": "Setting up OAuth Providers"
}

View File

@ -1,279 +0,0 @@
---
title: How to Self-Host Documenso
description: Learn how to self-host Documenso on your server or cloud infrastructure using Docker or other deployment methods.
---
import { Callout, Steps } from 'nextra/components';
import { CallToAction } from '@documenso/ui/components/call-to-action';
# Self Hosting
We support various deployment methods and are actively working on adding more. Please let us know if you have a specific deployment method in mind!
## Manual Deployment
The following guide will walk you through setting up Documenso manually on your server or cloud infrastructure.
<Steps>
### Clone the Repository
The first step is to clone the repository:
```bash
git clone https://github.com/documenso/documenso.git
```
### Configure the Environment Variables
Navigate to the `documenso` folder and create a `.env` file from the example `.env.example` file:
```bash
cp .env.example .env
```
Open the `.env` file and fill in the following variables:
```bash
- NEXTAUTH_URL
- NEXTAUTH_SECRET
- NEXT_PUBLIC_WEBAPP_URL
- NEXT_PUBLIC_MARKETING_URL
- NEXT_PRIVATE_DATABASE_URL
- NEXT_PRIVATE_DIRECT_DATABASE_URL
- NEXT_PRIVATE_SMTP_FROM_NAME
- NEXT_PRIVATE_SMTP_FROM_ADDRESS
```
<Callout type="info">
If you use a reverse proxy in front of Documenso, don't forget to provide the public URL for both
the `NEXTAUTH_URL` and `NEXT_PUBLIC_WEBAPP_URL` variables!
</Callout>
### Install the Dependencies
Install the project dependencies as follows:
```bash
npm i
npm run build:web
npm run prisma:migrate-deploy
```
### Start the Application
Finally, start the application:
```bash
npm run start
```
This will start the server on `localhost:3000`. Any reverse proxy can handle the front end and SSL termination.
<Callout type="info">
If you want to run with another port than `3000`, you can start the application with `next -p <ANY PORT>` from the `apps/web` folder.
</Callout>
</Steps>
## Docker
The following guide will walk you through setting up Documenso using Docker. You can choose between a Docker Compose production setup or a standalone container.
We provide a Docker container for Documenso, published on both DockerHub and GitHub Container Registry.
- [DockerHub](https://hub.docker.com/r/documenso/documenso)
- [GitHub Container Registry](https://ghcr.io/documenso/documenso)
You can pull the Docker image from either of these registries and run it with your preferred container hosting provider.
Please note that you must provide environment variables for connecting to the database, mail server, and other services.
### Option 1: Production Docker Compose Setup
This setup includes a PostgreSQL database and the Documenso application. You will need to provide your own SMTP details using environment variables.
<Steps>
### Download the Docker Compose File
Download the Docker Compose file from the Documenso repository - [compose.yml](https://raw.githubusercontent.com/documenso/documenso/release/docker/production/compose.yml).
### Navigate to the `compose.yml` File
Once downloaded, navigate to the directory containing the `compose.yml` file.
### Set Up Environment Variables
Create a `.env` file in the same directory as the `compose.yml` file.
Then add your SMTP details as well as the following environment variables:
```bash
NEXTAUTH_SECRET="<your-secret>"
NEXT_PRIVATE_ENCRYPTION_KEY="<your-key>"
NEXT_PRIVATE_ENCRYPTION_SECONDARY_KEY="<your-secondary-key>"
NEXT_PUBLIC_WEBAPP_URL="<your-url>"
NEXT_PRIVATE_SMTP_TRANSPORT="smtp-auth"
NEXT_PRIVATE_SMTP_HOST="<your-host>"
NEXT_PRIVATE_SMTP_PORT=<your-port>
NEXT_PRIVATE_SMTP_USERNAME="<your-username>"
NEXT_PRIVATE_SMTP_PASSWORD="<your-password>"
```
### Update the Volume Binding
The `cert.p12` file is required to sign and encrypt documents, so you must provide your key file. Update the volume binding in the `compose.yml` file to point to your key file:
```yaml
volumes:
- /path/to/your/keyfile.p12:/opt/documenso/cert.p12
```
After updating the volume binding, save the `compose.yml` file and run the following command to start the containers:
```bash
docker-compose --env-file ./.env -d up
```
The command will start the PostgreSQL database and the Documenso application containers.
### Access the Application
Access the Documenso application by visiting `http://localhost:3000` in your web browser.
</Steps>
### Option 2: Standalone Docker Container
If you prefer to host the Documenso application on a specific container provider, use the pre-built Docker image from DockerHub or GitHub's Package Registry. You will need to provide your own database and SMTP host.
<Steps>
### Pull the Docker Image
Pull the Documenso Docker image from DockerHub:
```bash
docker pull documenso/documenso
```
Or, pull the image from GitHub Container Registry:
```bash
docker pull ghcr.io/documenso/documenso
```
### Run the Docker Container
Run the Docker container with the required environment variables:
```bash
docker run -d \
-p 3000:3000 \
-e NEXTAUTH_URL="<your-nextauth-url>"
-e NEXTAUTH_SECRET="<your-nextauth-secret>"
-e NEXT_PRIVATE_ENCRYPTION_KEY="<your-next-private-encryption-key>"
-e NEXT_PRIVATE_ENCRYPTION_SECONDARY_KEY="<your-next-private-encryption-secondary-key>"
-e NEXT_PUBLIC_WEBAPP_URL="<your-next-public-webapp-url>"
-e NEXT_PRIVATE_DATABASE_URL="<your-next-private-database-url>"
-e NEXT_PRIVATE_DIRECT_DATABASE_URL="<your-next-private-database-url>"
-e NEXT_PRIVATE_SMTP_TRANSPORT="<your-next-private-smtp-transport>"
-e NEXT_PRIVATE_SMTP_FROM_NAME="<your-next-private-smtp-from-name>"
-e NEXT_PRIVATE_SMTP_FROM_ADDRESS="<your-next-private-smtp-from-address>"
-v /path/to/your/keyfile.p12:/opt/documenso/cert.p12
documenso/documenso
```
Replace the placeholders with the actual values.
### Access the Application
You can access the Documenso application by visiting the URL you provided for the `NEXT_PUBLIC_WEBAPP_URL` environment variable in your web browser.
</Steps>
### Advanced Configuration
The environment variables listed above are a subset of those available for configuring Documenso. The table below provides a complete list of environment variables and their descriptions.
| Variable | Description |
| -------------------------------------------- | --------------------------------------------------------------------------------------------------- |
| `PORT` | The port on which the Documenso application runs. It defaults to `3000`. |
| `NEXTAUTH_URL` | The URL for the NextAuth.js authentication service. |
| `NEXTAUTH_SECRET` | The secret key used by NextAuth.js for encryption and signing. |
| `NEXT_PRIVATE_ENCRYPTION_KEY` | The primary encryption key for symmetric encryption and decryption (at least 32 characters). |
| `NEXT_PRIVATE_ENCRYPTION_SECONDARY_KEY` | The secondary encryption key for symmetric encryption and decryption (at least 32 characters). |
| `NEXT_PRIVATE_GOOGLE_CLIENT_ID` | The Google client ID for Google authentication (optional). |
| `NEXT_PRIVATE_GOOGLE_CLIENT_SECRET` | The Google client secret for Google authentication (optional). |
| `NEXT_PUBLIC_WEBAPP_URL` | The URL for the web application. |
| `NEXT_PRIVATE_DATABASE_URL` | The URL for the primary database connection (with connection pooling). |
| `NEXT_PRIVATE_DIRECT_DATABASE_URL` | The URL for the direct database connection (without connection pooling). |
| `NEXT_PRIVATE_SIGNING_TRANSPORT` | The signing transport to use. Available options: local (default) |
| `NEXT_PRIVATE_SIGNING_PASSPHRASE` | The passphrase for the key file. |
| `NEXT_PRIVATE_SIGNING_LOCAL_FILE_CONTENTS` | The base64-encoded contents of the key file will be used instead of the file path. |
| `NEXT_PRIVATE_SIGNING_LOCAL_FILE_PATH` | The path to the key file, default `/opt/documenso/cert.p12`. |
| `NEXT_PUBLIC_UPLOAD_TRANSPORT` | The transport for file uploads (database or s3). |
| `NEXT_PRIVATE_UPLOAD_ENDPOINT` | The endpoint for the S3 storage transport (for third-party S3-compatible providers). |
| `NEXT_PRIVATE_UPLOAD_FORCE_PATH_STYLE` | Whether to force path-style URLs for the S3 storage transport. |
| `NEXT_PRIVATE_UPLOAD_REGION` | The region for the S3 storage transport (defaults to us-east-1). |
| `NEXT_PRIVATE_UPLOAD_BUCKET` | The bucket to use for the S3 storage transport. |
| `NEXT_PRIVATE_UPLOAD_ACCESS_KEY_ID` | The access key ID for the S3 storage transport. |
| `NEXT_PRIVATE_UPLOAD_SECRET_ACCESS_KEY` | The secret access key for the S3 storage transport. |
| `NEXT_PRIVATE_SMTP_TRANSPORT` | The transport to send emails (smtp-auth, smtp-api, resend, or mailchannels). |
| `NEXT_PRIVATE_SMTP_HOST` | The host for the SMTP server for SMTP transports. |
| `NEXT_PRIVATE_SMTP_PORT` | The port for the SMTP server for SMTP transports. |
| `NEXT_PRIVATE_SMTP_USERNAME` | The username for the SMTP server for the `smtp-auth` transport. |
| `NEXT_PRIVATE_SMTP_PASSWORD` | The password for the SMTP server for the `smtp-auth` transport. |
| `NEXT_PRIVATE_SMTP_APIKEY_USER` | The API key user for the SMTP server for the `smtp-api` transport. |
| `NEXT_PRIVATE_SMTP_APIKEY` | The API key for the SMTP server for the `smtp-api` transport. |
| `NEXT_PRIVATE_SMTP_SECURE` | Whether to force the use of TLS for the SMTP server for SMTP transports. |
| `NEXT_PRIVATE_SMTP_FROM_ADDRESS` | The email address for the "from" address. |
| `NEXT_PRIVATE_SMTP_FROM_NAME` | The sender name for the "from" address. |
| `NEXT_PRIVATE_RESEND_API_KEY` | The API key for Resend.com for the `resend` transport. |
| `NEXT_PRIVATE_MAILCHANNELS_API_KEY` | The optional API key for MailChannels (if using a proxy) for the `mailchannels` transport. |
| `NEXT_PRIVATE_MAILCHANNELS_ENDPOINT` | The optional endpoint for the MailChannels API (if using a proxy) for the `mailchannels` transport. |
| `NEXT_PRIVATE_MAILCHANNELS_DKIM_DOMAIN` | The domain for DKIM signing with MailChannels for the `mailchannels` transport. |
| `NEXT_PRIVATE_MAILCHANNELS_DKIM_SELECTOR` | The selector for DKIM signing with MailChannels for the `mailchannels` transport. |
| `NEXT_PRIVATE_MAILCHANNELS_DKIM_PRIVATE_KEY` | The private key for DKIM signing with MailChannels for the `mailchannels` transport. |
| `NEXT_PUBLIC_DOCUMENT_SIZE_UPLOAD_LIMIT` | The maximum document upload limit displayed to the user (in MB). |
| `NEXT_PUBLIC_POSTHOG_KEY` | The optional PostHog key for analytics and feature flags. |
| `NEXT_PUBLIC_DISABLE_SIGNUP` | Whether to disable user signups through the /signup page. |
## Run as a Service
You can run the application using a `systemd.service` file. Here is a simple example of the service running on port `3500` (using `3000` by default):
```bash
[Unit]
Description=documenso
After=network.target
[Service]
Environment=PATH=/path/to/your/node/binaries
Type=simple
User=www-data
WorkingDirectory=/var/www/documenso/apps/web
ExecStart=/usr/bin/next start -p 3500
TimeoutSec=15
Restart=always
[Install]
WantedBy=multi-user.target
```
We offer several alternative deployment methods for Documenso if you need more options.
## Railway
[![Deploy on Railway](https://railway.app/button.svg)](https://railway.app/template/bG6D4p)
## Render
[![Deploy to Render](https://render.com/images/deploy-to-render-button.svg)](https://render.com/deploy?repo=https://github.com/documenso/documenso)
## Koyeb
[![Deploy to Koyeb](https://www.koyeb.com/static/images/deploy/button.svg)](https://app.koyeb.com/deploy?type=git&repository=github.com/documenso/documenso&branch=main&name=documenso-app&builder=dockerfile&dockerfile=/docker/Dockerfile)
<CallToAction className="mt-12" utmSource="self-hosting" />

View File

@ -1,12 +0,0 @@
---
title: Getting Started with Self-Hosting
description: A step-by-step guide to setting up and hosting your own Documenso instance.
---
import { CallToAction } from '@documenso/ui/components/call-to-action';
# Getting Started with Self-Hosting
This is a step-by-step guide to setting up and hosting your own Documenso instance. Before getting started, [select the right license for you](/users/licenses).
<CallToAction className="mt-12" utmSource="self-hosting" />

View File

@ -1,29 +0,0 @@
---
title: Setting up OAuth Providers
description: Learn how to set up OAuth providers for your own instance of Documenso.
---
## Google OAuth (Gmail)
To use Google OAuth, you will need to create a Google Cloud Platform project and enable the Google Identity and Access Management (IAM) API. You will also need to create a new OAuth client ID and download the client secret.
### Create and configure a new OAuth client ID
1. Go to the [Google Cloud Platform Console](https://console.cloud.google.com/)
2. From the projects list, select a project or create a new one
3. If the APIs & services page isn't already open, open the console left side menu and select APIs & services
4. On the left, click Credentials
5. Click New Credentials, then select OAuth client ID
6. When prompted to select an application type, select Web application
7. Enter a name for your client ID, and click Create
8. Click the download button to download the client secret
9. Set the authorized javascript origins to `https://<documenso-domain>`
10. Set the authorized redirect URIs to `https://<documenso-domain>/api/auth/callback/google`
11. In the Documenso environment variables, set the following:
```
NEXT_PRIVATE_GOOGLE_CLIENT_ID=<your-client-id>
NEXT_PRIVATE_GOOGLE_CLIENT_SECRET=<your-client-secret>
```
Finally verify the signing in with Google works by signing in with your Google account and checking the email address in your profile.

View File

@ -1,67 +0,0 @@
---
title: Signing Certificate
description: Learn how to generate or buy a signing certificate for your Documenso instance.
---
import { Callout, Steps } from 'nextra/components';
# Generate or Buy
Self-hosting your Documenso instance requires your own certificate to sign documents. [This article](https://documenso.com/blog/building-documenso-pt1) explains why.
When it comes to certificates, you have two options:
- generate your certificate
- buy one from the Certificate Authority (CA)
<Callout type="info" emoji="">
A self-signed certificate should suffice if your industry has no special signing regulation. For
example, Deel.com makes hundreds of millions in revenue based on a platform without any signing
certificate, making your self-signed instance technically more secure. Of course, this is not
legal advice.
</Callout>
## Generating A Certificate
If you don't have special requirements for the signature of your signed documents, you can use a self-generated (self-signed) certificate.
The main drawback is that mainstream PDF readers like Adobe won't recognize the signature as a trusted source or show a green checkmark. The certificate will still include your company/personal data to prove your Documenso instance signed the document. It also guarantees that the document wasn't altered after signing.
You can generate your signing certificate by following [this guide](/developers/local-development/signing-certificate).
## Buying a Certificate
If you want more "officially backed" _(for lack of a better word)_ signatures, you will need to buy a certificate from a CA (Certificate Authority). If you want a green checkmark in Adobe PDF, you will need a vendor trusted by Adobe. Check out all Adobe vendors with a green checkmark for the signature on the [Adobe Trust List](https://helpx.adobe.com/acrobat/kb/approved-trust-list1.html).
If you are based in Europe, it might make sense to go with a European one, though there is no hard requirement. While the pricing can vary from vendor to vendor, the certificate's properties don't. The usual case would be a corporate certificate detailing the company's name to which it was issued.
### Technical Process
Receiving your signing certificate is similar to receiving an SSL certificate. Since you need the actual certificate as part of the Documenso config, you must generate a secret private key and a CSR (Certificate Signing Request).
<Steps>
### Generate a private key
Generate a private key (on a secure machine or in an HSM, depending on your security needs and the provider's requirements).
### Create a CSR
Have the Certificate Authority sign the Certificate Signing Request.
### Configure Documenso to use the certificate
Configure your instance to use the new certificate by configuring the following environment variables in your `.env` file:
| Environment Variable | Description |
| :-------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------------------------------------- |
| `NEXT_PRIVATE_SIGNING_TRANSPORT` | The transport used for document signing. Available options: local (default), gcloud-hsm |
| `NEXT_PRIVATE_SIGNING_PASSPHRASE` | The passphrase for the local file-based signing transport. This field is optional. |
| `NEXT_PRIVATE_SIGNING_LOCAL_FILE_PATH` | The local file path to the .p12 file to use for the local signing transport. This field is optional. |
| `NEXT_PRIVATE_SIGNING_LOCAL_FILE_CONTENTS` | The base64-encoded contents of the .p12 file to use for the local signing transport. This field is optional. |
| `NEXT_PRIVATE_SIGNING_GCLOUD_HSM_KEY_PATH` | The Google Cloud HSM key path for the gcloud-hsm signing transport. This field is optional. |
| `NEXT_PRIVATE_SIGNING_GCLOUD_HSM _PUBLIC_CRT_FILE_PATH` | The path to the Google Cloud HSM public certificate file to use for the gcloud-hsm signing transport. This field is optional. |
| `NEXT_PRIVATE_SIGNING_GCLOUD_HSM _PUBLIC_CRT_FILE_CONTENTS` | The base64-encoded contents of the Google Cloud HSM public certificate file for the gcloud-hsm signing transport. This field is optional. |
| `NEXT_PRIVATE_SIGNING_GCLOUD_ APPLICATION_CREDENTIALS_CONTENTS` | The Google Cloud Credentials file path for the gcloud-hsm signing transport. This field is optional. |
</Steps>

View File

@ -1,350 +0,0 @@
---
title: Webhooks
description: Learn how to use webhooks to receive real-time notifications about your documents.
---
# Webhooks
Webhooks are HTTP callbacks triggered by specific events. When the user subscribes to a specific event, and that event occurs, the webhook makes an HTTP request to the URL provided by the user. The request can be a simple notification or carry a payload with more information about the event.
Some of the common use cases for webhooks include:
1. **Real-time Data Syncing**: Webhooks provide a way to keep data in sync across different platforms. For example, you can keep your system up-to-date with your Documenso documents by subscribing to events like document creation or signing.
2. **Automating Workflows**: They can trigger automated workflows that start when an event occurs. For example, the webhook could trigger an email when a document is signed.
3. **Integrating Third-Party Services**: Webhooks can be used to integrate Documenso with third-party services. For example, you could use a webhook to send data to a CRM system when a document is signed.
Documenso supports Webhooks and allows you to subscribe to the following events:
- `document.created`
- `document.sent`
- `document.opened`
- `document.signed`
- `document.completed`
## Create a webhook subscription
You can create a webhook subscription from the user settings page. Click on your avatar in the top right corner of the dashboard and select "**[User settings](https://app.documenso.com/settings)**" from the dropdown menu.
![A screenshot of the Documenso's dashboard that shows the dropdown menu when you click on your user avatar](/webhook-images/dashboard-user-dropdown-menu.webp)
Then, navigate to the "**[Webhooks](https://app.documenso.com/settings/webhooks)**" tab, where you can see a list of your existing webhooks and create new ones.
![A screenshot of the Documenso's user settings page that shows the Webhooks tab and the Create Webhook button](/webhook-images/webhooks-settings-page.webp)
Clicking on the "**Create Webhook**" button opens a modal to create a new webhook subscription.
To create a new webhook subscription, you need to provide the following information:
- Enter the webhook URL that will receive the event payload.
- Select the event(s) you want to subscribe to: `document.created`, `document.sent`, `document.opened`, `document.signed`, `document.completed`.
- Optionally, you can provide a secret key that will be used to sign the payload. This key will be included in the `X-Documenso-Secret` header of the request.
![A screenshot of the Create Webhook modal that shows the URL input field and the event checkboxes](/webhook-images/webhooks-page-create-webhook-modal.webp)
After you have filled in the required information, click on the "**Create Webhook**" button to save your subscription.
The screenshot below illustrates a newly created webhook subscription.
![A screenshot of the Documenso's user settings page that shows the newly created webhook subscription](/webhook-images/webhooks-page.webp)
You can edit or delete your webhook subscriptions by clicking the "**Edit**" or "**Delete**" buttons next to the webhook.
## Webhook fields
The payload sent to the webhook URL contains the following fields:
| Field | Type | Description |
| -------------------------------------------- | --------- | ---------------------------------------------------- |
| `event` | string | The type of event that triggered the webhook. |
| `payload.id` | number | The id of the document. |
| `payload.userId` | number | The id of the user who owns the document. |
| `payload.authOptions` | json? | Authentication options for the document. |
| `payload.formValues` | json? | Form values for the document. |
| `payload.title` | string | The name of the document. |
| `payload.status` | string | The current status of the document. |
| `payload.documentDataId` | string | The identifier for the document data. |
| `payload.createdAt` | datetime | The creation date and time of the document. |
| `payload.updatedAt` | datetime | The last update date and time of the document. |
| `payload.completedAt` | datetime? | The completion date and time of the document. |
| `payload.deletedAt` | datetime? | The deletion date and time of the document. |
| `payload.teamId` | number? | The id of the team. |
| `payload.documentData.id` | string | The id of the document data. |
| `payload.documentData.type` | string | The type of the document data. |
| `payload.documentData.data` | string | The data of the document. |
| `payload.documentData.initialData` | string | The initial data of the document. |
| `payload.Recipient[].id` | number | The id of the recipient. |
| `payload.Recipient[].documentId` | number? | The id the document associated with the recipient. |
| `payload.Recipient[].templateId` | number? | The template identifier for the recipient. |
| `payload.Recipient[].email` | string | The email address of the recipient. |
| `payload.Recipient[].name` | string | The name of the recipient. |
| `payload.Recipient[].token` | string | The token associated with the recipient. |
| `payload.Recipient[].expired` | datetime? | The expiration status of the recipient. |
| `payload.Recipient[].signedAt` | datetime? | The date and time the recipient signed the document. |
| `payload.Recipient[].authOptions.accessAuth` | json? | Access authentication options. |
| `payload.Recipient[].authOptions.actionAuth` | json? | Action authentication options. |
| `payload.Recipient[].role` | string | The role of the recipient. |
| `payload.Recipient[].readStatus` | string | The read status of the document by the recipient. |
| `payload.Recipient[].signingStatus` | string | The signing status of the recipient. |
| `payload.Recipient[].sendStatus` | string | The send status of the document to the recipient. |
| `createdAt` | datetime | The creation date and time of the webhook event. |
| `webhookEndpoint` | string | The endpoint URL where the webhook is sent. |
## Webhook event payload example
When an event that you have subscribed to occurs, Documenso will send a POST request to the specified webhook URL with a payload containing information about the event.
## Example payloads
Below are examples of the payloads that are sent for each of the supported events. The payloads are sent as JSON data in the body of the POST request.
Example payload for the `document.created` event:
```json
{
"event": "DOCUMENT_CREATED",
"payload": {
"id": 10,
"userId": 1,
"authOptions": null,
"formValues": null,
"title": "documenso.pdf",
"status": "DRAFT",
"documentDataId": "hs8qz1ktr9204jn7mg6c5dxy0",
"createdAt": "2024-04-22T11:44:43.341Z",
"updatedAt": "2024-04-22T11:44:43.341Z",
"completedAt": null,
"deletedAt": null,
"teamId": null
},
"createdAt": "2024-04-22T11:44:44.779Z",
"webhookEndpoint": "https://mywebhooksite.com/mywebhook"
}
```
Example payload for the `document.sent` event:
```json
{
"event": "DOCUMENT_SENT",
"payload": {
"id": 10,
"userId": 1,
"authOptions": null,
"formValues": null,
"title": "documenso.pdf",
"status": "PENDING",
"documentDataId": "hs8qz1ktr9204jn7mg6c5dxy0",
"createdAt": "2024-04-22T11:44:43.341Z",
"updatedAt": "2024-04-22T11:48:07.569Z",
"completedAt": null,
"deletedAt": null,
"teamId": null,
"Recipient": [
{
"id": 52,
"documentId": 10,
"templateId": null,
"email": "signer2@documenso.com",
"name": "Signer 2",
"token": "vbT8hi3jKQmrFP_LN1WcS",
"expired": null,
"signedAt": null,
"authOptions": {
"accessAuth": null,
"actionAuth": null
},
"role": "VIEWER",
"readStatus": "NOT_OPENED",
"signingStatus": "NOT_SIGNED",
"sendStatus": "SENT"
},
{
"id": 53,
"documentId": 10,
"templateId": null,
"email": "signer1@documenso.com",
"name": "Signer 1",
"token": "HkrptwS42ZBXdRKj1TyUo",
"expired": null,
"signedAt": null,
"authOptions": {
"accessAuth": null,
"actionAuth": null
},
"role": "SIGNER",
"readStatus": "NOT_OPENED",
"signingStatus": "NOT_SIGNED",
"sendStatus": "SENT"
}
]
},
"createdAt": "2024-04-22T11:48:07.945Z",
"webhookEndpoint": "https://mywebhooksite.com/mywebhook"
}
```
Example payload for the `document.opened` event:
```json
{
"event": "DOCUMENT_OPENED",
"payload": {
"id": 10,
"userId": 1,
"authOptions": null,
"formValues": null,
"title": "documenso.pdf",
"status": "PENDING",
"documentDataId": "hs8qz1ktr9204jn7mg6c5dxy0",
"createdAt": "2024-04-22T11:44:43.341Z",
"updatedAt": "2024-04-22T11:48:07.569Z",
"completedAt": null,
"deletedAt": null,
"teamId": null,
"Recipient": [
{
"id": 52,
"documentId": 10,
"templateId": null,
"email": "signer2@documenso.com",
"name": "Signer 2",
"token": "vbT8hi3jKQmrFP_LN1WcS",
"expired": null,
"signedAt": null,
"authOptions": {
"accessAuth": null,
"actionAuth": null
},
"role": "VIEWER",
"readStatus": "OPENED",
"signingStatus": "NOT_SIGNED",
"sendStatus": "SENT"
}
],
"documentData": {
"id": "hs8qz1ktr9204jn7mg6c5dxy0",
"type": "S3_PATH",
"data": "9753/xzqrshtlpokm/documenso.pdf",
"initialData": "9753/xzqrshtlpokm/documenso.pdf"
}
},
"createdAt": "2024-04-22T11:50:26.174Z",
"webhookEndpoint": "https://mywebhooksite.com/mywebhook"
}
```
Example payload for the `document.signed` event:
```json
{
"event": "DOCUMENT_SIGNED",
"payload": {
"id": 10,
"userId": 1,
"authOptions": null,
"formValues": null,
"title": "documenso.pdf",
"status": "COMPLETED",
"documentDataId": "hs8qz1ktr9204jn7mg6c5dxy0",
"createdAt": "2024-04-22T11:44:43.341Z",
"updatedAt": "2024-04-22T11:52:05.708Z",
"completedAt": "2024-04-22T11:52:05.707Z",
"deletedAt": null,
"teamId": null,
"Recipient": [
{
"id": 51,
"documentId": 10,
"templateId": null,
"email": "signer1@documenso.com",
"name": "Signer 1",
"token": "HkrptwS42ZBXdRKj1TyUo",
"expired": null,
"signedAt": "2024-04-22T11:52:05.688Z",
"authOptions": {
"accessAuth": null,
"actionAuth": null
},
"role": "SIGNER",
"readStatus": "OPENED",
"signingStatus": "SIGNED",
"sendStatus": "SENT"
}
]
},
"createdAt": "2024-04-22T11:52:18.577Z",
"webhookEndpoint": "https://mywebhooksite.com/mywebhook"
}
```
Example payload for the `document.completed` event:
```json
{
"event": "DOCUMENT_COMPLETED",
"payload": {
"id": 10,
"userId": 1,
"authOptions": null,
"formValues": null,
"title": "documenso.pdf",
"status": "COMPLETED",
"documentDataId": "hs8qz1ktr9204jn7mg6c5dxy0",
"createdAt": "2024-04-22T11:44:43.341Z",
"updatedAt": "2024-04-22T11:52:05.708Z",
"completedAt": "2024-04-22T11:52:05.707Z",
"deletedAt": null,
"teamId": null,
"documentData": {
"id": "hs8qz1ktr9204jn7mg6c5dxy0",
"type": "S3_PATH",
"data": "bk9p1h7x0s3m/documenso-signed.pdf",
"initialData": "9753/xzqrshtlpokm/documenso.pdf"
},
"Recipient": [
{
"id": 50,
"documentId": 10,
"templateId": null,
"email": "signer2@documenso.com",
"name": "Signer 2",
"token": "vbT8hi3jKQmrFP_LN1WcS",
"expired": null,
"signedAt": "2024-04-22T11:51:10.055Z",
"authOptions": {
"accessAuth": null,
"actionAuth": null
},
"role": "VIEWER",
"readStatus": "OPENED",
"signingStatus": "SIGNED",
"sendStatus": "SENT"
},
{
"id": 51,
"documentId": 10,
"templateId": null,
"email": "signer1@documenso.com",
"name": "Signer 1",
"token": "HkrptwS42ZBXdRKj1TyUo",
"expired": null,
"signedAt": "2024-04-22T11:52:05.688Z",
"authOptions": {
"accessAuth": null,
"actionAuth": null
},
"role": "SIGNER",
"readStatus": "OPENED",
"signingStatus": "SIGNED",
"sendStatus": "SENT"
}
]
},
"createdAt": "2024-04-22T11:52:18.277Z",
"webhookEndpoint": "https://mywebhooksite.com/mywebhook"
}
```
## Availability
Webhooks are available to individual users and teams.

View File

@ -1,73 +0,0 @@
---
title: Home
description: Documenso aims to be the world's most trusted document-signing tool. Join us in creating the next generation of open trust infrastructure.
---
import Image from 'next/image';
import Link from 'next/link';
import backgroundPattern from '@documenso/assets/images/background-pattern.png';
import cardBeautifulFigure from '@documenso/assets/images/card-beautiful-figure.png';
import cardConnectionsFigure from '@documenso/assets/images/card-connections-figure.png';
import cardPaidFigure from '@documenso/assets/images/card-paid-figure.png';
import cardSharingFigure from '@documenso/assets/images/card-sharing-figure.png';
import { cn } from '@documenso/ui/lib/utils';
import { Card, CardContent, CardTitle } from '@documenso/ui/primitives/card';
export const Wrapper = ({ children }) => {
return <div className="mt-20">{children}</div>;
};
<Wrapper>
<div
className="fixed inset-0 -z-10 bg-center -mt-[15vh] h-full scale-125 object-cover dark:contrast-[70%] dark:invert dark:sepia md:scale-150 lg:scale-[175%] opacity-40 dark:opacity-20"
style={{
backgroundImage: `url('${backgroundPattern.src}')`,
}}
/>
<div className="flex flex-col items-center mb-16">
<span className="text-center text-4xl font-bold leading-tight tracking-tight md:text-[48px] lg:text-[64px]">Document signing, finally open source</span>
<span className="text-muted-foreground mx-auto mt-4 max-w-2xl text-center leading-normal tracking-tight">Documenso aims to be the world's most trusted document-signing tool. Join us in creating the next generation of open trust infrastructure.</span>
</div>
<div className="mt-6 grid grid-cols-1 md:grid-cols-2 gap-8 md:mt-8">
<Link href="/users">
<Card className="col-span-2 lg:col-span-1 h-full dark:bg-black/10 dark:border dark:border-stone-800">
<CardContent className="grid grid-cols-1 gap-8 p-6 max-h-[460px]">
<span className="text-foreground/80 leading-relaxed">
<strong className="block text-2xl font-normal mb-2 tracking-tight">Learn</strong>
Learn how to get started with your account and leverage our advanced features to level up your productivity.
</span>
<div className="flex items-center justify-center p-8 flex-grow">
<Image
src={cardBeautifulFigure}
alt="its fast"
className="w-full max-w-xs dark:contrast-[70%] dark:hue-rotate-180 dark:invert"
/>
</div>
</CardContent>
</Card>
</Link>
<Link href='/developers'>
<Card className="col-span-2 lg:col-span-1 h-full dark:bg-black/10 dark:border dark:border-stone-800">
<CardContent className="grid grid-cols-1 gap-8 p-6 max-h-[460px]">
<span className="text-foreground/80 leading-relaxed">
<strong className="block text-2xl font-normal mb-2 tracking-tight">Build</strong>
Everything you need to set up your local development environment.
Use our API and utilize webhooks for seamless integration.
</span>
<div className="flex items-center justify-center p-8 flex-grow">
<Image
src={cardConnectionsFigure}
alt="its fast"
className="w-full max-w-sm dark:contrast-[70%] dark:hue-rotate-180 dark:invert"
/>
</div>
</CardContent>
</Card>
</Link>
</div>
</Wrapper>

View File

@ -1,21 +0,0 @@
{
"index": "Introduction",
"support": "Support",
"-- How To Use": {
"type": "separator",
"title": "How To Use"
},
"get-started": "Get Started",
"profile": "User Profile",
"signing-documents": "Signing Documents",
"templates": "Templates",
"direct-links": "Direct Signing Links",
"document-visibility": "Document Visibility",
"-- Legal Overview": {
"type": "separator",
"title": "Legal Overview"
},
"fair-use": "Fair Use Policy",
"licenses": "Licenses",
"compliance": "Compliance"
}

View File

@ -1,4 +0,0 @@
{
"signature-levels": "Signature Levels",
"standards-and-regulations": "Standards and Regulations"
}

View File

@ -1,105 +0,0 @@
import { Callout } from 'nextra/components';
# Signature Levels
This page outlines our adherence to key regulations across various jurisdictions, including:
- U.S. ESIGN Act
- Uniform Electronic Transactions Act (UETA)
- European Union's eIDAS regulation
- Switzerland's ZertES
Whether you require simple electronic signatures or advanced cryptographic sealing, Documenso guarantees that all documents are securely sealed and compliant with the highest standards. Explore our compliance details below to understand how we maintain the integrity and enforceability of your electronic transactions.
<Callout emoji="🔏">
Documenso seals all signed documents cryptographically, regardless of signature level, to prevent
any alterations after signing.
</Callout>
## 🇺🇸 ESIGN (Electronic Signatures in Global and National Commerce) Act
<Callout type="info" emoji="✅">
Status: Compliant
</Callout>
The Electronic Signatures in Global and National Commerce Act (ESIGN Act) is a U.S. federal law that
ensures the legal validity and enforceability of electronic signatures and records in commerce.
### Main Requirements
- [x] Intent to Sign: "Parties must demonstrate their intent to sign [..]"
- [x] Consent: "The ESIGN Act requires that all parties involved in a transaction consent to the use of electronic signatures and records [..]"
- [x] Consumer Disclosures: Before obtaining their consent, financial institutions must provide the consumer a clear and conspicuous statement informing the consumer [..]
- [x] Record Retention: Electronic Records must be maintained for later access by signers.
- [x] Security: The ESIGN Act does not mandate specific security measures, but it does require that parties take reasonable steps to ensure the security and integrity of electronic signatures and records. This may include implementing encryption, access controls, and authentication measures.
## UETA (Uniform Electronic Transactions Act)
<Callout type="info" emoji="✅">
Status: Compliant
</Callout>
The Uniform Electronic Transactions Act is a law that provides a legal framework for the use of electronic
signatures and records in electronic transactions, ensuring they have the same validity and enforceability
as paper documents and handwritten signatures.
### Main Requirements
_See [ESIGN](/users/compliance/signature-levels#-esign-electronic-signatures-in-global-and-national-commerce-act)_
## 🇪🇺 eIDAS
<Callout type="info" emoji="✅">
Status: Compliant for Level 1 - SES (Simple Electronic Signatures)
</Callout>
eIDAS (Electronic Identification, Authentication and Trust Services) is an EU regulation that standardizes
electronic identification and trust services for secure and seamless electronic transactions across European
member states.
### Level 1 - SES (Simple Electronic Signatures)
eIDAS SES (Simple Electronic Signature) is a basic electronic signature with minimal security features.
### Main Requirements
- [x] Visual Signature
- [x] Clear Intent to Sign
### Level 2 - AES (Advanced Electronic Signatures)
<Callout type="warning" emoji="⏳">
Status: [Planned](https://github.com/documenso/backlog/issues/9) via third party until [Let's
Sign](https://github.com/documenso/backlog/issues/21) is realized.
</Callout>
eIDAS AES (Advanced Electronic Signature) provides a higher level of security with unique identification
of the signer and data integrity.
### Main Requirements
- [x] Cryptographic Signature Sealing the Document against tampering
- [x] Signing Using Dedicated Hardware (Hardware Security Module)
- [ ] Embedding Signer Identity in the Cryptographic Signature
- [ ] Being a Government Audited Trusted Qualified Services Provider
### Level 3 - QES (Qualified Electronic Signatures)
<Callout type="warning" emoji="⏳">
Status: [Planned](https://github.com/documenso/backlog/issues/32) via third party until [Let's
Sign](https://github.com/documenso/backlog/issues/21) is realized.
</Callout>
eIDAS QES (Qualified Electronic Signature) is the highest security level, legally equivalent to a handwritten
signature within the EU.
### Main Requirements
- [x] Cryptographic Signature Sealing the Document against tampering
- [x] Signing using dedicated hardware (Hardware Security Module)
- [ ] Embedding Signer Identity in the Cryptographic Signature
- [ ] Being a government-trusted qualified services provider
- [ ] eIDAS-compliant identification before signing using local passports or similar
## 🇨🇭 ZertES
<Callout type="warning" emoji="⏳">
Status: [Planned](https://github.com/documenso/backlog/issues/34)
</Callout>
ZertES is a Swiss Federal law that regulates electronic signature compliance.

View File

@ -1,47 +0,0 @@
import { Callout } from 'nextra/components';
## 21 CFR Part 11
<Callout type="info" emoji="✅">
Status: Compliant (Enterprise License)
</Callout>
21 CFR Part 11 is a regulation by the FDA that establishes the criteria for electronic records and electronic
signatures to ensure their authenticity, integrity, and confidentiality in the pharmaceutical, medical
device, and other FDA-regulated industries.
> Read more about 21 CFR Part 11 with Documenso here: https://documen.so/21-CFR-Part-11
### Main Requirements
- [x] Strong Identity Checks for each Signature
- [x] Signature and Audit Trails
- [x] User Access Management
- [x] Quality Assurance Documentation
## SOC/ SOC II
<Callout type="warning" emoji="⏳">
Status: [Planned](https://github.com/documenso/backlog/issues/24)
</Callout>
SOC II is a framework for managing and auditing the security, availability, processing integrity, confidentiality,
and data privacy in cloud and IT service organizations, established by the American Institute of Certified
Public Accountants (AICPA).
## ISO 27001
<Callout type="warning" emoji="⏳">
Status: [Planned](https://github.com/documenso/backlog/issues/26)
</Callout>
ISO 27001 is an international standard for managing information security, specifying requirements for
establishing, implementing, maintaining, and continually improving an information security management
system (ISMS).
### HIPAA
<Callout type="warning" emoji="⏳">
Status: [Planned](https://github.com/documenso/backlog/issues/25)
</Callout>
The HIPAA (Health Insurance Portability and Accountability Act) is a U.S. law designed to protect patient health information's privacy and security and improve the healthcare system's efficiency and effectiveness.

View File

@ -1,48 +0,0 @@
---
title: Direct Link Signing
description: Create a shareable link for document signing.
---
import { Callout, Steps } from 'nextra/components';
# Direct Link Signing
Direct Link Signing allows you to create a shareable link for document signing, where recipients can fill in their information and sign directly. Once the recipients sign the document, they will get it in their email. Also, if they have an account, the document gets saved in their account.
<Steps>
### Select a Document
Identify the template you want to share and make signable with a direct link. Then click on the 3 dots on the right side of the template and select "Direct link".
![Template page in the Documenso dashboard](/direct-links/document-direct-link-documenso.webp)
### Enable Direct Links
Once you click on "Direct link", you will be greeted with a modal where you can learn how direct links work. After reading the information, click "Enable direct link" to proceed.
![Enable the document direct link in the Documenso dashboard](/direct-links/enable-document-direct-link-modal.webp)
### Select the Recipient
The next step is to select the recipient for the direct link. You can select an existing recipient or click the "Create one automatically" button to create a new direct link recipient.
![Choose the Direct Link recipient](/direct-links/choose-direct-link-recipient-documenso.webp)
### Send the Link
After selecting the recipient, you will get a direct link to share with the recipient. The format of the link is as follows:
```bash
https://app.documenso.com/d/<random-generated-string>
```
### Optional: Add Templates to Your Profile
You can add templates with direct links to your public [Documenso profile](/users/profile) to make them signable anytime.
![Choose the Direct Link recipient](/direct-links/documenso-profile.webp)
The image above shows a template with a direct link added to the user's profile.
</Steps>

View File

@ -1,18 +0,0 @@
---
title: Document Visibility
description: Learn how to control the visibility of your team documents.
---
# Team's Document Visibility
By default, all documents created in a team are visible to all team members. However, you can control the visibility of your documents by changing the document's visibility settings.
To set the visibility of a document, click on the **Document visibility** dropdown in the document's settings panel.
![A screenshot of the Documenso's document editor page where you can update the document visibility](/document-visibility-settings.webp)
The document visibility can be set to one of the following options:
- **Everyone** - The document is visible to all team members.
- **Managers and above** - The document is visible to people with the role of Manager or above.
- **Admin only** - The document is only visible to the team's admins.

View File

@ -1,34 +0,0 @@
---
title: Fair Use Policy
description: Learn about our fair use policy, which enables us to have unlimited plans.
---
import { Callout } from 'nextra/components';
# Fair Use Policy
### Why
We offer our plans without any limits on volume because we want our users and customers to make the most of their accounts. Estimating volume is incredibly hard, especially for shorter intervals like a quarter. We are not interested in selling volume packages our customers end up not using. This is why the individual plan and the team plan do not include a limit on signing or API volume. If you are a customer of these [plans](https://documen.so/pricing), we ask you to abide by this fair use policy:
### Spirit of the Plan
> Use the limitless accounts as much as you like (they are meant to offer a lot) while respecting the spirit and intended scope of the account.
<Callout type="info">
What happens if I violate this policy? We will ask you to upgrade to a fitting plan or custom
pricing. We wont block your account without reaching out. [Message
us](mailto:support@documenso.com) for questions. It's probably fine, though.
</Callout>
### DO
- Sign as many documents with the individual plan for your single business or organization you are part of
- Use the API and Zapier to automate all your signing to sign as much as possible
- Experiment with the plans and integrations, testing what you want to build: When in doubt, do it. Especially if you are just starting.
### DON'T
- Use the individual account's API to power a platform
- Run a huge company, signing thousands of documents per day on a two-user team plan using the API
- Let this policy make you overthink. If you are a paying customer, we want you to win, and it's probably fine

View File

@ -1,33 +0,0 @@
---
title: Create Your Account
description: Learn how to create an account on Documenso.
---
import { Callout, Steps } from 'nextra/components';
# Create Your Account
<Steps>
### Pick a Plan
The first step to start using Documenso is to pick a plan and create an account. At the moment of writing this guide, we have 3 plans available: Free, Individual, and Teams.
Explore each plan's features and choose the one that best suits your needs. The [pricing page](https://documen.so/pricing) has more information about the plans.
<Callout>All plans are subject to our [Fair Use Policy](/users/fair-use).</Callout>
### Create an account
If you are unsure which plan to choose, you can start with the free plan and upgrade later.
To create a free account, navigate to the [registration page](https://documen.so/free) and fill in the required information.
### Optional: Claim a Premium Username
You can claim a premium username by upgrading to a paid plan. After upgrading to a paid plan, you can update your [public profile](https://app.documenso.com/settings/public-profile).
### Optional: Create a Team
If you are working with others, you can create a team and invite your team members to collaborate on your documents. More information about teams is available in the [Teams section](/users/get-started/teams).
</Steps>

View File

@ -1,91 +0,0 @@
---
title: Secure Your Account
description: Learn how to secure your Documenso account with Two-Factor Authentication (2FA) and Passkeys.
---
import { Callout, Steps } from 'nextra/components';
# Account Security
Documenso offers several security features to help you protect your account and documents. This guide will walk you through the steps to set up Two-Factor Authentication (2FA) and Passkeys for your account.
Two-factor authentication (2FA) and Passkeys are used for high-security and high-compliance signatures.
## Enable Two-Factor Authentication (2FA)
<Steps>
### Navigate to Security Settings
Navigate to your account's [security settings](https://app.documenso.com/settings/security). Here, you can manage your password and other security settings.
![A screenshot of the Documenso's security page in the user settings](/get-started-images/documenso-account-security-page.webp)
### Enable 2FA
Click the "Enable 2FA" button to start setting up Two-Factor Authentication. You will be presented with a QR code that you can scan with your 2FA app or a code that you can manually enter.
![A screenshot of the Documenso's security page in the user settings](/get-started-images/documenso-enable-2-factor-authentication.webp)
### Scan the QR Code
Use your 2FA app (e.g. Google Authenticator, Microsoft Authenticator) to scan the QR code. This will link your account to the 2FA app and generate a code that you can use to log in.
### Enter the 2FA Generated Code
After scanning the QR code, you will be prompted to enter the code generated by your 2FA app. After entering the code, click the "Enable 2FA" button to complete the process.
### 2FA Enabled
You have successfully enabled Two-Factor Authentication (2FA) for your account. To log in, you must enter the code generated by your 2FA app.
<Callout>
Logging in with Google will not require a 2FA code. As an authentication provider, your Google
account is considered secure. e.g. configuring 2FA for your Google account.
</Callout>
<Callout>
Logging in using a passkey will also not require a 2FA code since passkeys are considered 2FA by
design. The passkey itself is the first factor, and access to the device that holds it is
considered the second factor.
</Callout>
### Extra: Save the Backup Codes
Be sure to download and safely store the 2FA backup codes in case you lose access to your 2FA app. You can use these codes to log in to your account.
</Steps>
## Add Passkeys
A passkey is like a secret password stored locally on your device. You can log in from the device it was created on but not from another device.
<Steps>
### Navigate to Security Settings
Navigate to the [security settings](https://app.documenso.com/settings/security) in your account.
### Manage Passkeys
Click the "Manage passkeys" button to start setting up a passkey. You will be taken to a new page where you can manage your passkeys or add a new one.
![A screenshot of the Documenso's passkeys page](/get-started-images/documenso-passkeys-page.webp)
### Add a New Passkey
To add a new passkey, click the "Add passkey" button. This opens a modal window where you can choose a passkey name.
![A screenshot of the "Add passkey" modal](/get-started-images/documenso-add-passkey-box.webp)
After entering the passkey name, click the "Continue" button to proceed.
What happens next depends on the passkey provider you have configured. If you have a passkey provider installed in your browser, you will be prompted to add the passkey there. If not, you will be prompted to add the passkey to your browser's passkey manager.
Whatever option you choose, follow the on-screen instructions to add the passkey. Once the passkey is added, you can use it to log in to your account.
### Manage Passkeys
You can manage your passkeys from the passkeys page. You can see the list of passkeys you have added and remove them if needed.
</Steps>

View File

@ -1,99 +0,0 @@
---
title: Teams
description: Learn how to create and manage teams in Documenso.
---
import Image from 'next/image';
import { Callout, Steps } from 'nextra/components';
# Teams
Documenso allows you to create teams to collaborate with others on creating and signing documents.
<Steps>
### Create a New Team
Anyone can create a team from their account by clicking on the "+" (plus) button in the "Teams" section from the account dropdown.
![Documenso account dropdown menu](/get-started-images/add-team.webp)
Each team is a separate entity with its members, documents, and templates. You can create as many teams as you like but remember that each team is billed separately.
<Callout type="info">You can transfer the ownership of the team at any time.</Callout>
### Name and URL
Clicking the "+" button will open a modal where you must pick your team's name and URL. The URL is the team's identifier and will link to the team's page and settings. An example URL would be:
```bash
https://app.documenso.com/t/<your-team-name>
```
![Documenso create team modal](/get-started-images/add-team-2.webp)
You can select a different name and URL for your team, but we recommend using the same or similar name.
### Invite Team Members
After creating the team, you can invite team members by navigating to the "Members" tab in the team settings and clicking the "Invite member" button.
To access the team settings, click on the team's name in the account dropdown and select the appropriate team. Lastly, click again on the avatar and then "Team Settings".
Or you can copy this URL:
```bash
https://app.documenso.com/t/<your-team-name>/settings/members
```
Once you click on the "Invite member" button, you will be prompted to enter the email address of the person you want to invite. You can also select the role of the person you are inviting.
![Invite team members in Documenso dashboard](/get-started-images/add-team-members-documenso.webp)
You can also bulk-invite members by uploading a CSV file with the email addresses and roles of the people you want to invite.
The table below shows how the CSV file should be structured:
| Email address | Role |
| -------------------------- | ------- |
| team-admin@documenso.com | Admin |
| team-manager@documenso.com | Manager |
| team-member@documenso.com | Member |
<Callout type="info">
The basic team plan includes 5 members. You can invite as many members as you like by upgrading
your team's seats on the team's billing page.
</Callout>
#### Roles
You can assign different permissions to team members based on their roles. The roles available are:
| Role | Create, Edit, Send Documents | Manage Users | Manage Admins | Settings | Billing | Delete/ Transfer |
| :-----: | :--------------------------: | :----------: | :-----------: | :------: | :-----: | :--------------: |
| Member | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ |
| Manager | ✅ | ✅ | ❌ | ✅ | ✅ | ❌ |
| Admin | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ |
| Owner | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
### Set a Team Email
You can add a team email to make signing and sending documents easier. Adding a team email allows you to:
- See a signing request sent to this email (Team Inbox)
- See all documents sent on behalf of the team
### (Optional) Transfer Team Ownership
You can transfer the team's ownership at any time. To do this, navigate to the "General" tab in the team settings and click the "Transfer team" button.
Use this URL to get to the team settings:
```bash
https://app.documenso.com/t/<your-team-name>/settings
```
### [Send your First Document](https://app.documenso.com/)
</Steps>

View File

@ -1,8 +0,0 @@
---
title: Get Started
description: Get started with Documenso by creating an account, configuring your account security, collaborating with others via Teams, and using the basic features of Documenso.
---
# First Steps
This is a step-by-step guide to getting started with Documenso. You'll learn how to create a new account, configure your account security, collaborate with others via Teams, and use the features of Documenso.

View File

@ -1,5 +0,0 @@
{
"index": "Overview",
"community-edition": "Community Edition",
"enterprise-edition": "Enterprise Edition"
}

View File

@ -1,44 +0,0 @@
import { Callout } from 'nextra/components';
# Community Edition
The purpose of the Community Edition is to allow anyone to run their signing infrastructure. You can take Documenso as is and run it yourself with barely any restrictions. We aim to keep self-hosting a realistic option and not force the product to become cloud-only.
## License
Documenso and the Community Edition are licensed under [AGPL3](https://github.com/documenso/documenso/blob/main/LICENSE). Below, you can find an overview of the significant licensing terms. The most important thing that you must remember is that if you use the community edition, you must keep it open source:
> Permissions of this most robust copyleft license are conditioned on making available the complete source code of licensed works and modifications, which include larger works using a licensed work under the same license. Copyright and license notices must be preserved. Contributors provide an express grant of patent rights. When a modified version is used to provide a service over a network, the complete source code of the modified version must be made available.
### Permissions
- Modification - You can fork and modify the community edition.
- Distribution - You are free to redistribute the community edition.
- Patent use - See license for details.
- Private use - You can use the Community Edition privately.
<Callout type="info">
You can use Documenso commercially by hosting the community edition or otherwise (as long as you
keep the code open-source).
</Callout>
### Limitations
- **Liability & Warranty** - While we aim to build a best-in-class product, the community edition comes without an official warranty or liability.
- **EE Folder** - Features in the EE folder are not licensed under AGPL3 and cannot be used without an enterprise license. You can find a list of enterprise-licensed features [here](https://github.com/documenso/documenso/blob/main/packages/ee/FEATURES).
- **Official Support** - The Community Edition is not eligible for official customer support. While you can request community support through our Discord Community, it's not guaranteed that you will receive help. The Documenso team might also be happy to help, but be advised that this is strictly voluntary.
### Conditions
License and copyright notice
State changes
Disclose source
Network use is distribution
<Callout type="warning">
It's important to remember that you must keep the AGPL3 license for your modified or non-modified
version of Documenso. If you need clarification on whether this represents a problem or not for
you, reach out to us on [Discord](documen.so/discord).
</Callout>

View File

@ -1,21 +0,0 @@
import { Callout } from 'nextra/components';
# Enterprise Edition
The Documenso Enterprise Edition is our license for self-hosters that need the full range of support and compliance. Everything in the EE folder and all features listed [here](https://github.com/documenso/documenso/blob/main/packages/ee/FEATURES) can be used after acquiring a paid license.
## Includes
- Self-Host Documenso in any context.
- Premium Support via Slack, Discord and Email.
- Flexible Licensing (e.g. MIT) for deeper custom integration (if needed).
- Access to all Enterprise-grade compliance and administration features.
## Limitations
The Enterprise Edition currently has no limitations except custom contract terms.
<Callout type="info">
The Enterprise Edition requires a paid subscription. [Contact us for a
quote](https://documen.so/enterprise).
</Callout>

View File

@ -1,16 +0,0 @@
# Self-Hosting Licenses
Documenso comes in two versions for self-hosting:
### [Community Edition (Free)](licenses/community-edition)
- Free
- No official support
### [Enterprise Edition (Paid)](licenses/enterprise-edition)
- Paid
- Official support
- Enterprise Features
The choice between the two editions is entirely yours, depending on your specific needs. If you require official support and enterprise-level compliance, the Enterprise Edition is likely the best fit. However, if you find that the Community Edition, with its almost unrestricted features and use cases (including commercial use), meets all your requirements, we encourage you to start with it. Remember, you can always upgrade later.

View File

@ -1,68 +0,0 @@
---
title: User Profile
description: Learn how to set up your public profile on Documenso.
---
import { Callout, Steps } from 'nextra/components';
# User Profile
Documenso allows you to create a public profile to share your templates for anyone to sign. This is useful for distributing and collecting signatures for commonly used documents, making it more efficient for both the document creator and the signers.
<Callout type="info">A free Documenso account gives you 5 free signatures per month.</Callout>
<Steps>
### Navigate to Your Profile Settings
Click on your profile picture in the top right corner and select "User settings". Then, navigate to the "Public Profile" tab to configure your profile.
![The profile settings page](/public-profile/documenso-public-profile-settings.webp)
### (Mandatory) Set Your Profile URL
This is the URL that people will use to access your profile. We recommend choosing something easy to remember and share.
The structure of the URL is as follows:
```bash
https://app.documenso.com/p/<username>
```
Setting the public profile URL is mandatory to publish your profile.
### (Optional) Add a Bio Description
If you want to add a description to your profile, you can do so here. This is a good place to introduce yourself and explain what kind of documents you have available for signing.
### (Optional) Add a Profile Picture
Uploading a profile picture is optional, but we recommend it to make your profile more recognizable.
### Private/Public Profile
You can choose to make your profile public or private. Only you can access it if you make it private. If you make it public, anyone with the link can access it.
To make your profile public, toggle the switch to the right ("Show") at the top right-hand side of the page.
### (Optional) Link Templates
Linking templates to your profile is optional, but it's what makes your profile helpful. Linking templates allow people to sign documents directly from your profile. As a result, we recommend linking at least one template you want to share with others.
Learn more about [templates](/users/templates).
### Publish your Profile
After configuring your profile, click the "Update" button at the bottom of the page to publish it. Once you have published your profile, you can share the link with others if you made it public.
![An example of a public profile on Documenso](/direct-links/documenso-profile.webp)
The image above shows an example of a public profile on Documenso.
### Share the Link
Add the link to your other social profiles and share it on social media so people know they can quickly sign your documents from there.
<Callout>Tag @documenso on X to get a retweet and an endorsement from us.</Callout>
</Steps>

View File

@ -1,4 +0,0 @@
{
"index": "Send Documents",
"fields": "Document Fields"
}

View File

@ -1,446 +0,0 @@
---
title: Document Fields
description: Learn about the different fields you can add to your documents in Documenso.
---
# Document Fields
Learn about the different fields you can add to your documents in Documenso and how to make the most of them.
## Signature Field
The signature field collects the signer's signature. It's required for each recipient with the "Signer" role.
### Document Editor View
The field doesn't have any additional settings. You just need to place it on the document where you want the signer to sign.
![The signature field in the Documenso document editor](/document-signing/signature-field-document-editor-view.webp)
### Document Signing View
The recipient will see the signature field when they open the document to sign.
The recipient must click on the signature field to open the signing view, where they can sign using their mouse, touchpad, or touchscreen.
![The signature field in the Documenso document signing view](/document-signing/signature-field-document-signing-view.webp)
The image below shows the signature field signed by the recipient.
![The signature field signed by the user in the Documenso document signing view](/document-signing/signed-signature-field.webp)
After signing, the recipient can click the "Complete" button to complete the signing process.
## Email Field
The email field is used to collect the signer's email address.
### Document Editor View
The field doesn't have any additional settings. You just need to place it on the document where you want the signer to sign.
![The email field in the Documenso document editor](/document-signing/email-field-document-editor-view.webp)
### Document Signing View
When the recipient opens the document to sign, they will see the email field.
The recipient must click on the email field to automatically sign the field with the email associated with their account.
![The email field in the Documenso document signing view](/document-signing/email-field-document-signing-view.webp)
The image below shows the email field signed by the recipient.
![The email field signed by the user in the Documenso document signing view](/document-signing/signed-email-field.webp)
After entering their email address, the recipient can click the "Complete" button to complete the signing process.
## Name Field
The name field is used to collect the signer's name.
### Document Editor View
The field doesn't have any additional settings. You just need to place it on the document where you want the signer to sign.
![The name field in the Documenso document editor](/document-signing/name-field-document-editor-view.webp)
### Document Signing View
When the recipient opens the document to sign, they will see the name field.
The recipient must click on the name field, which will automatically sign the field with the name associated with their account.
![The name field in the Documenso document signing view](/document-signing/name-field-document-signing-view.webp)
The image below shows the name field signed by the recipient.
![The name field signed by the user in the Documenso document signing view](/document-signing/name-field-signed.webp)
After entering their name, the recipient can click the "Complete" button to complete the signing process.
## Date Field
The date field is used to collect the date of the signature.
### Document Editor View
The field doesn't have any additional settings. You just need to place it on the document where you want the signer to sign.
![The date field in the Documenso document editor](/document-signing/date-field-document-editor-view.webp)
### Document Signing View
When the recipient opens the document to sign, they will see the date field.
The recipient must click on the date field to automatically sign the field with the current date and time.
![The date field in the Documenso document signing view](/document-signing/date-field-document-signing-view.webp)
The image below shows the date field signed by the recipient.
![The date field signed by the user in the Documenso document signing view](/document-signing/date-field-signed.webp)
After entering the date, the recipient can click the "Complete" button to complete the signing process.
## Text Field
The text field is used to collect text input from the signer.
### Document Editor View
Place the text field on the document where you want the signer to enter text. The text field comes with additional settings that can be configured.
![The text field in the Documenso document editor](/document-signing/text-field-document-editor-view.webp)
To open the settings, click on the text field and then on the "Sliders" icon. That opens the settings panel on the right side of the screen.
![The text field settings in the Documenso document editor](/document-signing/text-field-advanced-settings-document-editor-view.webp)
The text field settings include:
- **Label** - The label displayed in the field.
- **Placeholder** - The placeholder text displayed in the field.
- **Text** - The default text displayed in the field.
- **Character limit** - The maximum number of characters allowed in the field.
- **Required** - Whether the field is required or not.
- **Read only** - Whether the field is read-only or not.
It also comes with a couple of rules:
- The field can't be required and read-only at the same time.
- A read-only field can't have an empty text field. It must have a default text value.
- The signer must fill out a required field.
- The text field characters count can't exceed the character limit.
- The signer can't modify a read-only field.
- The field auto-signs if there is a default text value.
Let's look at the following example.
![A text field with the settings configured by the user in the Documenso document editor](/document-signing/text-field-with-filled-advanced-settings.webp)
The field is configured as follows:
- Label: "Address"
- Placeholder: "Your office address"
- Default Text: "Signing Street 1, 241245"
- Character Limit: 35
- Required: False
- Read Only: False
Since the field has a label set, the label is displayed instead of the default text field value - "Add text".
### Document Signing View
What the recipient sees when they open the document to sign depends on the settings configured by the sender.
In this case, the recipient sees the text field signed with the default value.
![Text field with the default value signed by the user in the Documenso document signing view](/document-signing/text-field-autosigned.webp)
The recipient can modify the text field value since the field is not read-only. To change the value, the recipient must click the field to un-sign it.
Once it's unsigned, the field uses the label set by the sender.
![Unsigned text field in the Documenso document signing view](/document-signing/text-field-unsigned.webp)
To sign the field with a different value, the recipient needs to click on the field and enter the new value.
![Text field with the text input in the Documenso document signing view](/document-signing/text-field-input-modal.webp)
Since the text field has a character limit, the recipient must enter a value that doesn't exceed the limit. Otherwise, an error message will appear, and the field will not be signed.
The image below illustrates the text field signed with a new value.
![Text field signed with a new value](/document-signing/text-field-new-value-signed.webp)
After signing the field, the recipient can click the "Complete" button to complete the signing process.
## Number Field
The number field is used for collecting a number input from the signer.
### Document Editor View
Place the number field on the document where you want the signer to enter a number. The number field comes with additional settings that can be configured.
![The number field in the Documenso document editor](/document-signing/number-field-document-editor.webp)
To open the settings, click on the number field and then on the "Sliders" icon. That opens the settings panel on the right side of the screen.
![The number field in the Documenso document editor](/document-signing/number-field-document-editor-view.webp)
The number field settings include:
- **Label** - The label displayed is the field.
- **Placeholder** - The placeholder text displayed in the field.
- **Value** - The default number displayed in the field.
- **Number format** - The format of the number.
- **Required** - Whether the field is required or not.
- **Read only** - Whether the field is read-only or not.
- **Validation** - The validation rules for the field.
It also comes with a couple of rules:
- The value must be a number.
- The field can't be required and read-only at the same time.
- A read-only field can't have an empty number field. It must have a default number value.
- The signer must fill out a required field.
- If the default number and a max value are set, the default number must be less than the max value.
- If the default number and a min value are set, the default number must be greater than the min value.
- The value must match the number format if a number format is set.
In this example, the number field is configured as follows:
- Label: "Quantity"
- Placeholder: "Enter the preferred quantity"
- Default Value: 12
- Number Format: "123,456,789.00"
- Required: False
- Read Only: False
- Validation:
- Min value: 5, Max value: 50
![A number field with the label configured by the user in the Documenso document editor](/document-signing/number-field-label.webp)
Since the field has a label set, the label is displayed instead of the default number field value - "Add number".
### Document Signing View
What the recipient sees when they open the document to sign depends on the settings configured by the sender.
The recipient sees the number field signed with the default value in this case.
![Number field with the default value signed by the user in the Documenso document signing view](/document-signing/number-field-autosigned.webp)
Since the number field is not read-only, the recipient can modify its value. To change the value, the recipient must click the field to un-sign it.
Once it's unsigned, the field uses the label set by the sender.
![Unsigned number field in the Documenso document signing view](/document-signing/number-field-unsigned.webp)
To sign the field with a different value, the recipient needs to click on the field and enter the new value.
![Number field with the number input in the Documenso document signing view](/document-signing/number-field-input-modal.webp)
Since the number field has a validation rule set, the recipient must enter a value that meets the rules. In this example, the value needs to be between 5 and 50. Otherwise, an error message will appear, and the field will not be signed.
The image below illustrates the text field signed with a new value.
![Number field signed with a new value](/document-signing/number-field-signed-with-another-value.webp)
After signing the field, the recipient can click the "Complete" button to complete the signing process.
## Radio Field
The radio field is used to collect a single choice from the signer.
### Document Editor View
Place the radio field on the document where you want the signer to select a choice. The radio field comes with additional settings that can be configured.
![The radio field in the Documenso document editor](/document-signing/radio-field-document-editor-view.webp)
To open the settings, click on the radio field and then on the "Sliders" icon. That opens the settings panel on the right side of the screen.
![The radio field advanced settings in the Documenso document editor](/document-signing/radio-field-advanced-settings-document-editor-view.webp)
The radio field settings include:
- **Required** - Whether the field is required or not.
- **Read only** - Whether the field is read-only or not.
- **Values** - The list of choices for the field.
It also comes with a couple of rules:
- The field can't be required and read-only at the same time.
- A read-only field can't have an empty radio field. It must have at least one option.
- The signer must fill out a required field.
- The field auto-signs if there is a default value.
- The signer can't sign with a value not in the options list.
- The signer can't modify the field if it's read-only.
- It should contain at least one option.
- The field can't have more than one option selected.
In this example, the radio field is configured as follows:
- Required: False
- Read Only: False
- Options:
- Option 1
- Option 2
- Empty value
- Empty value
- Option 3
![The radio field with the settings configured by the user in the Documenso document editor](/document-signing/radio-field-options-document-editor-view.webp)
Since the field contains radio options, it displays them instead of the default radio field value, "Radio".
### Document Signing View
What the recipient sees when they open the document to sign depends on the settings configured by the sender.
In this case, the recipient sees the radio field unsigned because the sender didn't select a value.
![Radio field with no value selected in the Documenso document signing view](/document-signing/radio-field-unsigned.webp)
The recipient can select one of the options by clicking on the radio button next to the option.
![Radio field with the value selected by the user in the Documenso document signing view](/document-signing/radio-field-signed.webp)
After signing the field, the recipient can click the "Complete" button to complete the signing process.
## Checkbox Field
The checkbox field is used to collect multiple choices from the signer.
### Document Editor View
Place the checkbox field on the document where you want the signer to select choices. The checkbox field comes with additional settings that can be configured.
![The checkbox field in the Documenso document editor](/document-signing/checkbox-document-editor-view.webp)
To open the settings, click on the checkbox field and then on the "Sliders" icon. That opens the settings panel on the right side of the screen.
![The checkbox field settings in the Documenso document editor](/document-signing/checkbox-advanced-settings.webp)
The checkbox field settings include the following:
- **Validation** - The validation rules for the field.
- **Rule** - The rule specifies "At least", "At most", and "Exactly".
- **Number** - The number of choices that must be selected.
- **Required** - Whether the field is required or not.
- **Read only** - Whether the field is read-only or not.
- **Options** - The list of choices for the field.
It also comes with a couple of rules:
- The field can't be required and read-only at the same time.
- A read-only field can't have an empty checkbox field. It must have at least one checked option.
- The signer must fill out a required field.
- The field auto-signs if there is a default value.
- The signer can't sign with a value not in the options list.
- The signer can't modify the field if it's read-only.
- It should contain at least one option.
In this example, the checkbox field is configured as follows:
- No validation rules
- Required: True
- Read Only: False
- Options:
- Option 1
- Empty value (checked)
- Option 2
- Option 3 (checked)
- Empty value
![The checkbox field with the settings configured by the user in the Documenso document editor](/document-signing/checkbox-advanced-settings-document-editor-view.webp)
Since the field contains checkbox options, it displays them instead of the default checkbox field value, "Checkbox".
### Document Signing View
What the recipient sees when they open the document to sign depends on the settings configured by the sender.
In this case, the recipient sees the checkbox field signed with the values selected by the sender.
![Checkbox field with the values selected by the user in the Documenso document signing view](/document-signing/checkbox-field-document-signing-view.webp)
Since the field is required, the recipient can either sign with the values selected by the sender or modify the values.
The values can be modified in 2 ways:
- Click on the options you want to select or deselect.
- Hover over the field and click the "X" button to clear all the selected values.
The image below illustrates the checkbox field with the values cleared by the recipient. Since the field is required, it has a red border instead of the yellow one (non-required fields).
![Checkbox field the values cleared by the user in the Documenso document signing view](/document-signing/checkbox-field-unsigned.webp)
Then, the recipient can select values other than the ones chosen by the sender.
![Checkbox field with the values selected by the user in the Documenso document signing view](/document-signing/checkbox-field-custom-sign.webp)
After signing the field, the recipient can click the "Complete" button to complete the signing process.
## Dropdown/Select Field
The dropdown/select field collects a single choice from a list of options.
### Document Editor View
Place the dropdown/select field on the document where you want the signer to select a choice. The dropdown/select field comes with additional settings that can be configured.
![The dropdown/select field in the Documenso document editor](/document-signing/select-field-sliders.webp)
To open the settings, click on the dropdown/select field and then on the "Sliders" icon. That opens the settings panel on the right side of the screen.
![The dropdown/select field settings in the Documenso document editor](/document-signing/select-field-advanced-settings-panel.webp)
The dropdown/select field settings include:
- **Required** - Whether the field is required or not.
- **Read only** - Whether the field is read-only or not.
- **Options** - The list of choices for the field.
- **Default** value - The default value selected in the field.
It also comes with a couple of rules:
- The field can't be required and read-only at the same time.
- A read-only field can't have an empty select field. It must have a default value.
- The signer must fill out a required field.
- The default value must be one of the options.
- The field auto-signs if there is a default value.
- The field can't be signed with a value not in the options list.
- The signer can't modify the field if it's read-only.
- It should contain at least one option.
In this example, the dropdown/select field is configured as follows:
- Required: False
- Read Only: False
- Default Value: None
- Options:
- Document
- Template
- Other
### Document Signing View
What the recipient sees when they open the document to sign depends on the settings configured by the sender.
In this case, the recipient sees the dropdown/select field with the default label, "-- Select ---" since the sender has not set a default value.
![Dropdown/select field in the Documenso document signing view](/document-signing/select-field-unsigned.webp)
The recipient can modify the dropdown/select field value since the field is not read-only. To change the value, the recipient must click on the field for the dropdown list to appear.
![Dropdown/select field with the dropdown list in the Documenso document signing view](/document-signing/select-field-unsigned-dropdown.webp)
The recipient can select one of the options from the list. The image below illustrates the dropdown/select field signed with a new value.
![Dropdown/select field signed with a value](/document-signing/select-field-signed.webp)
After signing the field, the recipient can click the "Complete" button to complete the signing process.

View File

@ -1,152 +0,0 @@
---
title: Send a document for signing
description: The guide gives a detailed description of all options available when sending out a document for signing.
---
import { Callout, Steps } from 'nextra/components';
# Send Documents for Signing
This guide will walk you through the process of sending a document out for signing. You will learn how to upload a document, add recipients, place signature fields, and send the document for signing.
<Steps>
### Login Into Your Account
The guide assumes you have a Documenso account. If you don't, you can create a free account [here](https://documen.so/free-docs).
### Upload Document
Navigate to the [Documenso dashboard](https://app.documenso.com/documents) and click on the "Add a document" button. Select the document you want to upload and wait for the upload to complete.
![Documenso dashboard](/document-signing/documenso-documents-dashboard.webp)
After the upload is complete, you will be redirected to the document's page. You can configure the document's settings and add recipients and fields here.
![Documenso document overview](/document-signing/documenso-uploaded-document.webp)
### (Optional) Advanced Options
Click on the "Advanced options" button to access additional settings for the document. You can set an external ID, date format, time zone, and the redirect URL.
![Advanced settings for a document uploaded in the Documenso dashboard](/document-signing/documenso-uploaded-document-advanced-options.webp)
The external ID allows you to set a custom ID for the document that can be used to identify the document in your external system(s).
The date format and time zone settings allow you to customize how the date and time are displayed in the document.
The redirect URL allows you to specify a URL where the signer will be redirected after signing the document.
### (Optional) Document Access
Documenso enables you to set up access control for your documents. You can require authentication for viewing the document.
The available options are:
- **Require account** - The recipient must be signed in to view the document.
- **None** - The document can be accessed directly by the URL sent to the recipient.
![Document access settings in the Documenso dashboard](/document-signing/documenso-enterprise-document-access.webp)
<Callout type="info">
The "Document Access" feature is only available for Enterprise accounts.
</Callout>
### (Optional) Recipient Authentication
The "Recipient Authentication" feature allows you to specify the authentication method required for recipients to sign the signature field.
The available options are:
- **Require passkey** - The recipient must have an account and passkey configured via their settings.
- **Require 2FA** - The recipient must have an account and 2FA enabled via their settings.
- **None** - No authentication required.
![Document recipient action authentication in the Documenso dashboard](/document-signing/document-enterprise-recipient-action-authentication.webp)
This can be overridden by setting the authentication requirements directly for each recipient in the next step.
<Callout type="info">
The "Recipient Authentication" feature is only available for Enterprise accounts.
</Callout>
### Recipients
Click the "+ Add Signer" button to add a new recipient. You can configure the recipient's email address, name, role, and authentication method on this page.
You can choose any option from the ["Recipient Authentication"](#optional-recipient-authentication) section, or you can set it to "Inherit authentication method" to use the global action signing authentication method configured in the "General Settings" step.
![The required authentication method for a recipient](/document-signing/documenso-document-recipient-authentication-method.webp)
You can also set the recipient's role, which determines their actions and permissions in the document.
![The recipient role](/document-signing/documenso-document-recipient-role.webp)
#### Roles
Documenso has 4 roles for recipients with different permissions and actions.
| Role | Function | Action required | Signature |
| :------: | :-----------------------------------------------------------------------------: | :-------------: | :-------: |
| Signer | Needs to sign signatures fields assigned to them. | Yes | Yes |
| Approver | Needs to approve the document as a whole. Signature optional. | Yes | Optional |
| Viewer | Needs to confirm they viewed the document. | Yes | No |
| BCC | Receives a copy of the signed document after completion. No action is required. | No | No |
### Fields
Documenso supports 9 different field types that can be added to the document. Each field type collects various information from the recipients when they sign the document.
![The available field types in the Documenso dashboard](/document-signing/documenso-document-fields.webp)
The available field types are:
- **Signature** - Collects the signer's signature
- **Email** - Collects the signer's email address
- **Name** - Collects the signer's name
- **Date** - Collects the date of the signature
- **Text** - Collects text input from the signer
- **Number** - Collects a number input from the signer
- **Radio** - Collects a single choice from the signer
- **Checkbox** - Collects multiple choices from the signer
- **Dropdown/Select** - Collects a single choice from a list of choices
All fields can be placed anywhere on the document and resized as needed.
<Callout type="info">
Learn more about the available field types and how to use them on the [Fields
page](signing-documents/fields).
</Callout>
#### Signature Required
Signer Roles require at least 1 signature field. You will get an error message if you try to send a document without a signature field.
![Error message when trying to send a document without a signature field](/document-signing/documenso-no-signature-field-found.webp)
### Email Settings
Before sending the document, you can configure the email settings and customize the subject line, message, and sender name.
![Email settings in the Documenso dashboard](/document-signing/documenso-document-email-settings.webp)
If you leave the email subject and message empty, Documenso will use the default email template.
### Sending the Document
After configuring the document, click the "Send" button to send the document to the recipients. The recipients will receive an email with a link to sign the document.
![The email sent to the recipients with the signing link](/document-signing/documenso-sign-email.webp)
#### Signing Link
If you need to copy the signing link for each recipient, you can do so by clicking on the recipient whose link you want to copy. The signing link is copied automatically to your clipboard.
![How to copy the signing link for each recipient from the Documenso dashboard](/document-signing/documenso-signing-links.webp)
The signing link has the following format:
```bash
https://app.documenso.com/sign/12ACP777zxQLO52hjj_vCB
```
</Steps>

View File

@ -1,38 +0,0 @@
---
title: Support
description: Learn what types of support we offer.
---
# Support
## Community Support
If you are a developer or free user, you can reach out to the community or raise an issue:
### [Create Github Issues](https://github.com/documenso/documenso/issues)
The community and the core team address GitHub issues. Be sure to check if a similar issue already exists. Please note that while we want to address everything immediately, we must prioritize.
### [Join our Discord](https://documen.so/discord)
You can ask for help in the [community help channel](https://discord.com/channels/1132216843537485854/1133419426524430376).
## Paid Account Support
### Email: support@documenso.com
If you are paying customers facing issues, email our customer support, especially in urgent cases.
### Private Discord channel
If you prefer Discord, we can invite you to a private channel. Message support to make this happen.
## Enterprise Support
### Email: support@documenso.com
If you are paying customers facing issues, email our customer support, especially in urgent cases.
### Slack
If your team is on Slack, we can create a private workspace to support you more closely.

View File

@ -1,100 +0,0 @@
import { Callout, Steps } from 'nextra/components';
# Document Templates
Documenso allows you to create templates, which are reusable documents. Templates are helpful if you often send the same type of document, such as contracts, agreements, or invoices, as they help you save time.
<Steps>
### Create New Template
To create a new template, navigate to the ["Templates" page](https://app.documenso.com/templates) and click on the "New Template" button.
![Documenso template page](/templates/documenso-template-page.webp)
Clicking on the "New Template" button opens a new modal to upload the document you want to use as a template. Select the document and wait for Documenso to upload it to your account.
![Upload a new template document in the Documenso dashboard](/templates/documenso-template-page-upload-document.webp)
Once the upload is complete, Documenso opens the template configuration page.
![A successfuly uploaded document in the Documenso dashboard](/templates/documenso-template-page-uploaded-document.webp)
You can then configure the template by adding recipients, fields, and other options.
### (Optional) Email options
When you send a document for signing, Documenso emails the recipients with a link to the document. The email contains a subject, message, and the document.
Documenso uses a generic subject and message but also allows you to customize them for each document and template.
![Configuring the email options for the Documenso template](/templates/documenso-template-page-uploaded-document-email-options.webp)
To configure the email options, click the "Email Options" tab and fill in the subject and message fields. Every time you use this template for signing, Documenso will use the custom subject and message you provided. They can also be overridden before sending the document.
### (Optional) Advanced Options
The template also has advanced options that you can configure. These options include settings such as the external ID, date format, time zone and the redirect URL.
![Configuring the advanced options for the Documenso template](/templates/documenso-template-page-uploaded-document-advanced-options.webp)
The external ID allows you to set a custom ID for the document that can be used to identify the document in your external system(s).
The date format and time zone settings allow you to customize how the date and time are displayed in the document.
The redirect URL allows you to specify a URL where the signer will be redirected after signing the document.
### Add Placeholders or Recipients
You can add placeholders for the template recipients. Placeholders specify where the recipient's name, email, and other information should be in the document.
You can also add recipients directly to the template. Recipients are the people who will receive the document for signing.
![Adding placeholder recipients for the Documenso template](/templates/documenso-template-recipients.webp)
If you add placeholders to the template, you must replace them with actual recipients when creating a document from it. See the modal from the ["Use a Template"](#use-a-template) section.
### Add Fields
The last step involves adding fields to the document. These fields collect information from the recipients when they sign the document.
Documenso provides the following field types:
- **Signature** - Collects the signer's signature
- **Email** - Collects the signer's email address
- **Name** - Collects the signer's name
- **Date** - Collects the date of the signature
- **Text** - Collects text input from the signer
- **Number** - Collects a number input from the signer
- **Radio** - Collects a single choice from the signer
- **Checkbox** - Collects multiple choices from the signer
- **Dropdown/Select** - Collects a single choice from a list of choices
![Adding fields for the Documenso template](/templates/documenso-template-page-fields.webp)
After adding the fields, press the "Save Template" button to save the template.
<Callout type="info">
Learn more about the available field types and how to use them on the [Fields
page](signing-documents/fields).
</Callout>
### Use a Template
Click on the "Use Template" button to create a new document from the template. Before creating the document, you are asked to fill in the recipients for the placeholders you added to the template.
After filling in the recipients, click the "Create Document" button to create the document in your account.
![Use an available Documenso template](/templates/documenso-use-template.webp)
You can also send the document straight to the recipients for signing by checking the "Send document" checkbox.
### (Optional) Create A Direct Signing Link
A direct signing link allows you to create a shareable link for document signing, where recipients can fill in their information and sign the document. See the "Create Direct Link" button in the image from [step 4](#add-placeholders-or-recipients).
<Callout type="info">
Check out the [Direct Signing Links](/users/direct-links) section for more information.
</Callout>
</Steps>

View File

@ -1,6 +0,0 @@
module.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
};

View File

@ -1,13 +0,0 @@
'use client';
import React from 'react';
import NextPlausibleProvider from 'next-plausible';
export type PlausibleProviderProps = {
children: React.ReactNode;
};
export const PlausibleProvider = ({ children }: PlausibleProviderProps) => {
return <NextPlausibleProvider domain="documenso.com">{children}</NextPlausibleProvider>;
};

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 91 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 189 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 69 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 74 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 72 KiB

Some files were not shown because too many files have changed in this diff Show More