Compare commits

..

13 Commits

1209 changed files with 14994 additions and 206323 deletions

View File

@ -1,38 +0,0 @@
{
"name": "Documenso",
"image": "mcr.microsoft.com/devcontainers/base:bullseye",
"features": {
"ghcr.io/devcontainers/features/docker-in-docker:2": {
"version": "latest",
"enableNonRootDocker": "true",
"moby": "true"
},
"ghcr.io/devcontainers/features/node:1": {}
},
"onCreateCommand": "./.devcontainer/on-create.sh",
"forwardPorts": [
3000,
54320,
9000,
2500,
1100
],
"customizations": {
"vscode": {
"extensions": [
"aaron-bond.better-comments",
"bradlc.vscode-tailwindcss",
"dbaeumer.vscode-eslint",
"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

@ -1,10 +0,0 @@
#!/usr/bin/env bash
# Install dependencies
npm install
# Copy the env file
cp .env.example .env
# Run the dev setup
npm run dx

View File

@ -1,3 +0,0 @@
#!/usr/bin/env bash
npm run dev

View File

@ -1,118 +1,19 @@
# [[AUTH]]
NEXTAUTH_URL="http://localhost:3000"
NEXTAUTH_SECRET="secret"
# [[CRYPTO]]
# Application Key for symmetric encryption and decryption
# REQUIRED: This should be a random string of at least 32 characters
NEXT_PRIVATE_ENCRYPTION_KEY="CAFEBABE"
# REQUIRED: This should be a random string of at least 32 characters
NEXT_PRIVATE_ENCRYPTION_SECONDARY_KEY="DEADBEEF"
NEXT_PUBLIC_SITE_URL="http://localhost:3000"
NEXT_PUBLIC_APP_URL="http://localhost:3000"
# [[AUTH OPTIONAL]]
NEXT_PRIVATE_GOOGLE_CLIENT_ID=""
NEXT_PRIVATE_GOOGLE_CLIENT_SECRET=""
# [[URLS]]
NEXT_PUBLIC_WEBAPP_URL="http://localhost:3000"
NEXT_PUBLIC_MARKETING_URL="http://localhost:3001"
# [[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=
NEXT_PUBLIC_STRIPE_COMMUNITY_PLAN_MONTHLY_PRICE_ID=
NEXT_PUBLIC_STRIPE_COMMUNITY_PLAN_YEARLY_PRICE_ID=
# [[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.
NEXT_PRIVATE_UPLOAD_BUCKET="documenso"
# OPTIONAL: Defines the access key ID to use for the S3 storage transport.
NEXT_PRIVATE_UPLOAD_ACCESS_KEY_ID="documenso"
# OPTIONAL: Defines the secret access key to use for the S3 storage transport.
NEXT_PRIVATE_UPLOAD_SECRET_ACCESS_KEY="password"
# [[SMTP]]
# OPTIONAL: Defines the transport to use for sending emails. Available options: smtp-auth (default) | smtp-api | mailchannels
NEXT_PRIVATE_SMTP_TRANSPORT="smtp-auth"
# OPTIONAL: Defines the host to use for sending emails.
NEXT_PRIVATE_SMTP_HOST="127.0.0.1"
# OPTIONAL: Defines the port to use for sending emails.
NEXT_PRIVATE_SMTP_PORT=2500
# OPTIONAL: Defines the username to use with the SMTP server.
NEXT_PRIVATE_SMTP_USERNAME="documenso"
# OPTIONAL: Defines the password to use with the SMTP server.
NEXT_PRIVATE_SMTP_PASSWORD="password"
# OPTIONAL: Defines the API key user to use with the SMTP server.
NEXT_PRIVATE_SMTP_APIKEY_USER=
# OPTIONAL: Defines the API key to use with the SMTP server.
NEXT_PRIVATE_SMTP_APIKEY=
# OPTIONAL: Defines whether to force the use of TLS.
NEXT_PRIVATE_SMTP_SECURE=
# REQUIRED: Defines the sender name to use for the from address.
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
NEXT_PRIVATE_RESEND_API_KEY=
# OPTIONAL: The API key to use for MailChannels.
NEXT_PRIVATE_MAILCHANNELS_API_KEY=
# OPTIONAL: The endpoint to use for the MailChannels API if using a proxy.
NEXT_PRIVATE_MAILCHANNELS_ENDPOINT=
# OPTIONAL: The domain to use for DKIM signing.
NEXT_PRIVATE_MAILCHANNELS_DKIM_DOMAIN=
# OPTIONAL: The selector to use for DKIM signing.
NEXT_PRIVATE_MAILCHANNELS_DKIM_SELECTOR=
# OPTIONAL: The private key to use for DKIM signing.
NEXT_PRIVATE_MAILCHANNELS_DKIM_PRIVATE_KEY=
# OPTIONAL: Displays the maximum document upload limit to the user in MBs
NEXT_PUBLIC_DOCUMENT_SIZE_UPLOAD_LIMIT=5
# [[STRIPE]]
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=
# [[FEATURES]]
# OPTIONAL: Leave blank to disable PostHog and feature flags.
NEXT_PUBLIC_POSTHOG_KEY=""
# OPTIONAL: Leave blank to disable billing.
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"
NEXT_PUBLIC_SUBSCRIPTIONS_ENABLED=false
# This is only required for the marketing site
# [[REDIS]]
NEXT_PRIVATE_REDIS_URL=
NEXT_PRIVATE_REDIS_TOKEN=

View File

@ -1,8 +0,0 @@
# Config files
*.config.js
*.config.cjs
# Statically hosted javascript files
apps/*/public/*.js
apps/*/public/*.cjs
scripts/

View File

@ -1,47 +0,0 @@
name: 'Bug Report'
labels: ['bug']
description: Create a bug report to help us improve
body:
- type: markdown
attributes:
value: Thank you for reporting an issue.
Please fill in as much of the form below as you're able to.
- type: textarea
attributes:
label: Issue Description
description: Please provide a clear and concise description of the problem.
- type: textarea
attributes:
label: Steps to Reproduce
description: Please provide step-by-step instructions to reproduce the issue. Include code snippets, error messages, and any other relevant information.
- type: textarea
attributes:
label: Expected Behavior
description: Describe what you expected to happen.
- type: textarea
attributes:
label: Current Behavior
description: Describe what is currently happening.
- type: textarea
attributes:
label: Screenshots (optional)
description: If applicable, add screenshots to help explain the issue.
- type: input
attributes:
label: Operating System [e.g., Windows 10]
- type: input
attributes:
label: Browser [e.g., Chrome, Firefox]
- type: input
attributes:
label: Version [e.g., 2.0.1]
- type: checkboxes
attributes:
label: Please check the boxes that apply to this issue report.
options:
- label: I have searched the existing issues to make sure this is not a duplicate.
- label: I have provided steps to reproduce the issue.
- label: I have included relevant environment information.
- label: I have included any relevant screenshots.
- label: I understand that this is a voluntary contribution and that there is no guarantee of resolution.
- label: I want to work on creating a PR for this issue if approved

View File

@ -1,36 +0,0 @@
name: 'Feature Request'
description: Suggest a new idea or enhancement for this project
body:
- type: markdown
attributes:
value: Please provide a clear and concise title for your feature request
- type: textarea
attributes:
label: Feature Description
description: Describe the feature you are requesting in detail. Explain what problem it solves or what value it adds to the project.
- type: textarea
attributes:
label: Use Case
description: Provide a scenario or use case where this feature would be beneficial. Explain how users would interact with this feature and why it's important.
- type: textarea
attributes:
label: Proposed Solution
description: If you have an idea of how this feature could be implemented, describe it here. Include any technical details, UI/UX considerations, or design suggestions.
- type: textarea
attributes:
label: Alternatives (optional)
description: Are there any alternative ways to achieve the same goal? Describe other approaches that could be considered if this feature is not implemented.
- type: textarea
attributes:
label: Additional Context
description: Add any additional context or information that might be relevant to the feature request.
- type: checkboxes
attributes:
label: Please check the boxes that apply to this feature request.
options:
- label: I have searched the existing feature requests to make sure this is not a duplicate.
- label: I have provided a detailed description of the requested feature.
- label: I have explained the use case or scenario for this feature.
- label: I have included any relevant technical details or design suggestions.
- label: I understand that this is a suggestion and that there is no guarantee of implementation.
- label: I want to work on creating a PR for this issue if approved

View File

@ -1,39 +0,0 @@
name: 'General Improvement Request'
description: 'Suggest a minor enhancement or improvement for this project'
title: '[Title for your improvement suggestion]'
body:
- type: textarea
attributes:
label: 'Describe the improvement you are suggesting in detail'
description: 'Explain why this improvement would be beneficial. Share any context, pain points, or reasons for suggesting this change.'
validations:
required: true
- type: textarea
id: description
attributes:
label: 'Additional Information & Alternatives (optional)'
description: 'Are there any additional context or information that might be relevant to the improvement suggestion.'
validations:
required: false
- type: dropdown
id: assignee
attributes:
label: 'Do you want to work on this improvement?'
multiple: false
options:
- 'No'
- 'Yes'
default: 0
validations:
required: true
- type: checkboxes
attributes:
label: 'Please check the boxes that apply to this improvement suggestion.'
options:
- label: 'I have searched the existing issues and improvement suggestions to avoid duplication.'
- label: 'I have provided a clear description of the improvement being suggested.'
- label: 'I have explained the rationale behind this improvement.'
- label: 'I have included any relevant technical details or design suggestions.'
- label: 'I understand that this is a suggestion and that there is no guarantee of implementation.'
validations:
required: true

View File

@ -1,49 +0,0 @@
---
name: Pull Request
about: Submit changes to the project for review and inclusion
---
## Description
<!--- Describe the changes introduced by this pull request. -->
<!--- Explain what problem it solves or what feature/fix it adds. -->
## Related Issue
<!--- If this pull request is related to a specific issue, reference it here using #issue_number. -->
<!--- For example, "Fixes #123" or "Addresses #456". -->
## Changes Made
<!--- Provide a summary of the changes made in this pull request. -->
<!--- Include any relevant technical details or architecture changes. -->
- Change 1
- Change 2
- ...
## Testing Performed
<!--- Describe the testing that you have performed to validate these changes. -->
<!--- Include information about test cases, testing environments, and results. -->
- Tested feature X in scenario Y.
- Ran unit tests for component Z.
- Tested on browsers A, B, and C.
- ...
## Checklist
<!--- Please check the boxes that apply to this pull request. -->
<!--- You can add or remove items as needed. -->
- [ ] I have tested these changes locally and they work as expected.
- [ ] I have added/updated tests that prove the effectiveness of these changes.
- [ ] I have updated the documentation to reflect these changes, if applicable.
- [ ] I have followed the project's coding style guidelines.
- [ ] I have addressed the code review feedback from the previous submission, if applicable.
## Additional Notes
<!--- Provide any additional context or notes for the reviewers. -->
<!--- This might include details about design decisions, potential concerns, or anything else relevant. -->

View File

@ -1,40 +0,0 @@
---
name: Test Addition
about: Submit a new test, either unit or end-to-end (E2E), for review and inclusion
---
## Description
<!--- Provide a clear and concise description of the new test you are adding. -->
<!--- Explain the purpose of the test and what it aims to validate. -->
## Related Issue
<!--- If this test addition is related to a specific issue, reference it here using #issue_number. -->
<!--- For example, "Fixes #123" or "Addresses #456". -->
## Test Details
<!--- Describe the details of the test you're adding. -->
<!--- Include information about inputs, expected outputs, and any specific scenarios. -->
- Test Name: Name of the test
- Type: [Unit / E2E]
- Description: Brief description of what the test checks
- Inputs: What inputs the test uses (if applicable)
- Expected Output: What output or behavior the test expects
## Checklist
<!--- Please check the boxes that apply to this pull request. -->
<!--- You can add or remove items as needed. -->
- [ ] I have written the new test and ensured it works as intended.
- [ ] I have added necessary documentation to explain the purpose of the test.
- [ ] I have followed the project's testing guidelines and coding style.
- [ ] I have addressed any review feedback from previous submissions, if applicable.
## Additional Notes
<!--- Provide any additional context or notes for the reviewers. -->
<!--- This might include explanations about the testing approach or any potential concerns. -->

View File

@ -1,24 +0,0 @@
name: Cache production build binaries
description: 'Cache or restore if necessary'
inputs:
node_version:
required: false
default: v18.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 }}
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: v18.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,32 +0,0 @@
version: 2
updates:
- package-ecosystem: 'github-actions'
directory: '/'
schedule:
interval: 'weekly'
target-branch: 'main'
labels:
- 'ci dependencies'
- 'ci'
open-pull-requests-limit: 0
- package-ecosystem: 'npm'
directory: '/apps/marketing'
schedule:
interval: 'weekly'
target-branch: 'main'
labels:
- 'npm dependencies'
- 'frontend'
open-pull-requests-limit: 0
- package-ecosystem: 'npm'
directory: '/apps/web'
schedule:
interval: 'weekly'
target-branch: 'main'
labels:
- 'npm dependencies'
- 'frontend'
open-pull-requests-limit: 0

21
.github/labeler.yml vendored
View File

@ -1,21 +0,0 @@
'apps: marketing':
- apps/marketing/**
'apps: web':
- apps/web/**
'version bump 👀':
- '**/package.json'
- '**/package-lock.json'
'🚨 migrations 🚨':
- packages/prisma/migrations/**/migration.sql
'🚨 e2e changes 🚨':
- packages/app-tests/e2e/**
'🚨 .env changes 🚨':
- .env.example
'pkg: ee changes':
- packages/ee/**

View File

@ -1,67 +0,0 @@
name: 'Continuous Integration'
on:
workflow_call:
push:
branches: ['main']
pull_request:
branches: ['main']
concurrency:
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
jobs:
build_app:
name: Build App
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 2
- uses: ./.github/actions/node-install
- name: Copy env
run: cp .env.example .env
- uses: ./.github/actions/cache-build
build_docker:
name: Build Docker Image
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 2
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Cache Docker layers
uses: actions/cache@v3
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

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

@ -1,41 +0,0 @@
name: 'CodeQL'
on:
workflow_dispatch:
push:
branches: ['main']
pull_request:
branches: ['main']
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write
strategy:
fail-fast: true
matrix:
language: ['javascript']
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Copy env
run: cp .env.example .env
- uses: ./.github/actions/node-install
- uses: ./.github/actions/cache-build
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
with:
languages: ${{ matrix.language }}
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2

View File

@ -1,24 +0,0 @@
name: Deploy to Production
on:
push:
tags:
- '*'
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
ref: main
fetch-depth: 0
token: ${{ secrets.GH_TOKEN }}
- name: Push to release branch
run: |
git checkout release || git checkout -b release
git merge --ff-only main
git push origin release

View File

@ -1,44 +0,0 @@
name: Playwright Tests
on:
push:
branches: ['main']
pull_request:
branches: ['main']
jobs:
e2e_tests:
name: 'E2E Tests'
timeout-minutes: 60
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- 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: Create the database
run: npm run prisma:migrate-dev
- name: Seed the database
run: npm run prisma:seed
- uses: ./.github/actions/cache-build
- name: Run Playwright tests
run: npm run ci
- uses: actions/upload-artifact@v3
if: always()
with:
name: test-results
path: 'packages/app-tests/**/test-results/*'
retention-days: 30
env:
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
TURBO_TEAM: ${{ vars.TURBO_TEAM }}

View File

@ -1,29 +0,0 @@
name: 'Welcome New Contributors'
on:
pull_request:
types: ['opened']
issues:
types: ['opened']
permissions:
pull-requests: write
issues: write
jobs:
welcome-message:
name: Welcome Contributors
if: github.event.action == 'opened'
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/first-interaction@v1
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
pr-message: |
Thank you for creating your first Pull Request and for being a part of the open signing revolution! 💚🚀
<br /> Feel free to hop into our community in [Discord](https://documen.so/discord)
issue-message: |
Thank you for opening your first issue and for being a part of the open signing revolution!
<br /> One of our team members will review it and get back to you as soon as it possible 💚
<br /> Meanwhile, please feel free to hop into our community in [Discord](https://documen.so/discord)

View File

@ -1,63 +0,0 @@
name: 'Issue Assignee Check'
on:
issues:
types: ['assigned']
permissions:
issues: write
jobs:
countIssues:
if: ${{ github.event.issue.assignee }} && github.event.action == 'assigned' && github.event.sender.type == 'User'
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 2
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: '18'
cache: npm
- name: Install Octokit
run: npm install @octokit/rest@18
- name: Check Assigned User's Issue Count
id: parse-comment
uses: actions/github-script@v5
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const { Octokit } = require("@octokit/rest");
const octokit = new Octokit({ auth: process.env.GITHUB_TOKEN });
const username = context.payload.issue.assignee.login;
console.log(`Username Extracted: ${username}`);
const { data: issues } = await octokit.issues.listForRepo({
owner: context.repo.owner,
repo: context.repo.repo,
assignee: username,
state: 'open'
});
const issueCount = issues.length;
console.log(`Issue Count For ${username}: ${issueCount}`);
if (issueCount > 3) {
let issueCountMessage = `### 🚨 Documenso Police 🚨`;
issueCountMessage += `\n@${username} has ${issueCount} open issues assigned already. Consider whether this issue should be assigned to them or left open for another contributor.`;
await octokit.request('POST /repos/{owner}/{repo}/issues/{issue_number}/comments', {
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
body: issueCountMessage,
headers: {
'Authorization': `token ${{ secrets.GITHUB_TOKEN }}`,
}
});
}

View File

@ -1,21 +0,0 @@
name: 'Label Issues'
on:
issues:
types: ['opened', 'reopened']
jobs:
label_issues:
runs-on: ubuntu-latest
permissions:
issues: write
steps:
- uses: actions/github-script@v6
with:
script: |
github.rest.issues.addLabels({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
labels: ["needs triage"]
})

View File

@ -1,20 +0,0 @@
name: 'PR Labeler'
on:
- pull_request_target
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
jobs:
labeler:
permissions:
contents: read
pull-requests: write
runs-on: ubuntu-latest
steps:
- uses: actions/labeler@v4
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
sync-labels: ''

View File

@ -1,64 +0,0 @@
name: 'PR Review Reminder'
on:
pull_request:
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' || 'reopened' || 'ready_for_review' || 'review_requested')
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 2
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: '18'
cache: npm
- name: Install Octokit
run: npm install @octokit/rest@18
- name: Check user's PRs awaiting review
id: parse-prs
uses: actions/github-script@v5
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const { Octokit } = require("@octokit/rest");
const octokit = new Octokit({ auth: process.env.GITHUB_TOKEN });
const username = context.payload.pull_request.user.login;
console.log(`Username Extracted: ${username}`);
const { data: pullRequests } = await octokit.pulls.list({
owner: context.repo.owner,
repo: context.repo.repo,
state: 'open',
sort: 'created',
direction: 'asc',
});
const userPullRequests = pullRequests.filter(pr => pr.user.login === username && (pr.state === 'open' || pr.state === 'ready_for_review'));
const prCount = userPullRequests.length;
console.log(`PR Count for ${username}: ${prCount}`);
if (prCount > 3) {
let prReminderMessage = `🚨 @${username} has ${prCount} pull requests awaiting review. Please consider reviewing them when possible. 🚨`;
await octokit.request('POST /repos/{owner}/{repo}/issues/{issue_number}/comments', {
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.payload.pull_request.number,
body: prReminderMessage,
headers: {
'Authorization': `token ${{ secrets.GITHUB_TOKEN }}`,
}
});
}

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

@ -1,62 +0,0 @@
name: 'Validate PR Name'
on:
pull_request_target:
types:
- opened
- reopened
- edited
- synchronize
permissions:
pull-requests: write
jobs:
validate-pr:
name: Validate PR title
runs-on: ubuntu-latest
steps:
- name: Check PR creator's previous activity
id: check_activity
run: |
CREATOR=$(curl -s "https://api.github.com/repos/${{ github.repository }}/pulls/${{ github.event.pull_request.number }}" | jq -r '.user.login')
ACTIVITY=$(curl -s "https://api.github.com/search/commits?q=author:${CREATOR}+repo:${{ github.repository }}" | jq -r '.total_count')
if [ "$ACTIVITY" -eq 0 ]; then
echo "::set-output name=is_new::true"
else
echo "::set-output name=is_new::false"
fi
- name: Count PRs created by user
id: count_prs
run: |
CREATOR=$(curl -s "https://api.github.com/repos/${{ github.repository }}/pulls/${{ github.event.pull_request.number }}" | jq -r '.user.login')
PR_COUNT=$(curl -s "https://api.github.com/search/issues?q=type:pr+is:open+author:${CREATOR}+repo:${{ github.repository }}" | jq -r '.total_count')
echo "::set-output name=pr_count::$PR_COUNT"
- uses: amannn/action-semantic-pull-request@v5
id: lint_pr_title
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- uses: marocchino/sticky-pull-request-comment@v2
if: always() && (steps.lint_pr_title.outputs.error_message != null)
with:
header: pr-title-lint-error
message: |
Hey There! and thank you for opening this pull request! 📝👋🏼
We require pull request titles to follow the [Conventional Commits Spec](https://www.conventionalcommits.org/en/v1.0.0/) and it looks like your proposed title needs to be adjusted.
Details:
```
${{ steps.lint_pr_title.outputs.error_message }}
```
- if: ${{ steps.lint_pr_title.outputs.error_message == null && steps.check_activity.outputs.is_new == 'false' && steps.count_prs.outputs.pr_count < 2}}
uses: marocchino/sticky-pull-request-comment@v2
with:
header: pr-title-lint-error
message: |
Thank you for following the naming conventions for pull request titles! 💚🚀

View File

@ -1,24 +0,0 @@
name: 'Mark Stale Issues and PRs'
on:
schedule:
- cron: '0 */8 * * *'
jobs:
stale:
runs-on: ubuntu-latest
permissions:
issues: write
pull-requests: write
steps:
- uses: actions/stale@v4
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
days-before-pr-stale: 90
days-before-issue-stale: 90
days-before-issue-close: 180
stale-pr-message: 'This PR has not seen activitiy for a while. It will be closed in 30 days unless further activity is detected.'
close-pr-message: 'This PR has been closed because of inactivity.'
exempt-pr-labels: 'WIP,on-hold,needs review'
exempt-issue-labels: 'WIP,on-hold,needs review,roadmap,assigned,needs triage'

14
.gitignore vendored
View File

@ -31,20 +31,6 @@ yarn-error.log*
# turbo
.turbo
.turbo-cookie
# vercel
.vercel
# contentlayer
.contentlayer
# intellij
.idea
# vscode
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json

View File

@ -1,55 +0,0 @@
tasks:
- init: |
npm i &&
npm run dx:up &&
cp .env.example .env &&
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)"
command: npm run d
ports:
- port: 3000
visibility: public
onOpen: open-preview
- port: 3001
visibility: public
onOpen: open-preview
- port: 9000
visibility: public
onOpen: ignore
- port: 1100
visibility: private
onOpen: ignore
- port: 2500
visibility: private
onOpen: ignore
- 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
- bradlc.vscode-tailwindcss
- dbaeumer.vscode-eslint
- 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

@ -1,4 +0,0 @@
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"
npm run commitlint -- $1

View File

@ -1,16 +0,0 @@
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"
SCRIPT_DIR="$(readlink -f "$(dirname "$0")")"
MONOREPO_ROOT="$(readlink -f "$SCRIPT_DIR/../")"
echo "Copying pdf.js"
npm run copy:pdfjs --workspace apps/**
echo "Copying .well-known/ contents"
node "$MONOREPO_ROOT/scripts/copy-wellknown.cjs"
git add "$MONOREPO_ROOT/apps/web/public/"
git add "$MONOREPO_ROOT/apps/marketing/public/"
npx lint-staged

View File

@ -1,16 +0,0 @@
node_modules
.next
public
**/**/node_modules
**/**/.next
**/**/public
*.lock
*.log
*.test.ts
.gitignore
.npmignore
.prettierignore
.DS_Store
.eslintignore

View File

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

View File

@ -1,7 +0,0 @@
# General Issues
Contact: https://github.com/documenso/documenso/issues/new?assignees=&labels=bug&projects=&template=bug-report.yml
# Report critical issues privately to let us take appropriate action before publishing.
Contact: mailto:security@documenso.com
Preferred-Languages: en
Canonical: https://documenso.com/.well-known/security.txt

45
CLA.md
View File

@ -1,45 +0,0 @@
# Documenso Contributors License Agreement
This Contributors License Agreement ("CLA") is entered into between the Contributor, and Documenso Inc. ("Documenso"), collectively referred to as the "Parties."
## Background:
Documenso is an open-source project aimed at providing an open-source document signing platform for all parties. This CLA governs the rights and contributions made by the Contributor to the Documenso project.
## Agreement:
**Contributor Grant of License:**
By submitting code, documentation, or any other materials (collectively, "Contributions") to the Documenso project, the Contributor grants Documenso a perpetual, worldwide, non-exclusive, royalty-free, sublicensable license to use, modify, distribute, and otherwise exploit the Contributions, including any intellectual property rights therein, for the purposes of the Documenso project.
**Representation of Ownership and Right to Contribute:**
The Contributor represents that they have the legal right to grant the license stated in Section 1, and that the Contributions do not infringe upon the intellectual property rights of any third party. The Contributor also represents that they have the authority to submit the Contributions on their own behalf or, if applicable, on behalf of their employer or any other entity.
**Patent Grant:**
If the Contributions include any method, process, or apparatus that is covered by a patent, the Contributor agrees to grant Documenso a non-exclusive, worldwide, royalty-free license under any patent claims necessary to use, modify, distribute, and otherwise exploit the Contributions for the purposes of the Documenso project.
**No Implied Warranties or Support:**
The Contributor acknowledges that the Contributions are provided "as is," without any warranties or support of any kind. Documenso shall have no obligation to provide maintenance, updates, bug fixes, or support for the Contributions.
**Retention of Contributor Rights:**
The Contributor retains all right, title, and interest in and to their Contributions. This CLA does not restrict the Contributor from using their own Contributions for any other purpose.
**Governing Law:**
This CLA shall be governed by and construed in accordance with the laws of California (CA), without regard to its conflict of laws principles.
**Entire Agreement:**
This CLA constitutes the entire agreement between the Parties with respect to the subject matter hereof and supersedes all prior and contemporaneous understandings, agreements, representations, and warranties.
**Acceptance:**
By submitting Contributions to the Documenso project, the Contributor acknowledges and agrees to the terms and conditions of this CLA. If the Contributor is agreeing to this CLA on behalf of an entity, they represent that they have the necessary authority to bind that entity to these terms.
**Effective Date:**
This CLA is effective as of the date of the first Contribution made by the Contributor to the Documenso project.

View File

@ -1,126 +0,0 @@
# Contributor Covenant Code of Conduct
## Our Pledge
We as members, contributors, and leaders pledge to make participation in our
community a harassment-free experience for everyone, regardless of age, body
size, visible or invisible disability, ethnicity, sex characteristics, gender
identity and expression, level of experience, education, socio-economic status,
nationality, personal appearance, race, caste, color, religion, or sexual
identity and orientation.
We pledge to act and interact in ways that contribute to an open, welcoming,
diverse, inclusive, and healthy community.
## Our Standards
Examples of behavior that contributes to a positive environment for our
community include:
- Demonstrating empathy and kindness toward other people
- Being respectful of differing opinions, viewpoints, and experiences
- Giving and gracefully accepting constructive feedback
- Accepting responsibility and apologizing to those affected by our mistakes,
and learning from the experience
- Focusing on what is best not just for us as individuals, but for the overall
community
Examples of unacceptable behavior include:
- The use of sexualized language or imagery, and sexual attention or advances of
any kind
- Trolling, insulting or derogatory comments, and personal or political attacks
- Public or private harassment
- Publishing others' private information, such as a physical or email address,
without their explicit permission
- Other conduct which could reasonably be considered inappropriate in a
professional setting
## Enforcement Responsibilities
Community leaders are responsible for clarifying and enforcing our standards of
acceptable behavior and will take appropriate and fair corrective action in
response to any behavior that they deem inappropriate, threatening, offensive,
or harmful.
Community leaders have the right and responsibility to remove, edit, or reject
comments, commits, code, wiki edits, issues, and other contributions that are
not aligned to this Code of Conduct, and will communicate reasons for moderation
decisions when appropriate.
## Scope
This Code of Conduct applies within all community spaces, and also applies when
an individual is officially representing the community in public spaces.
Examples of representing our community include using an official e-mail address,
posting via an official social media account, or acting as an appointed
representative at an online or offline event.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders responsible for enforcement at
support@documenso.com.
All complaints will be reviewed and investigated promptly and fairly.
All community leaders are obligated to respect the privacy and security of the
reporter of any incident.
## Enforcement Guidelines
Community leaders will follow these Community Impact Guidelines in determining
the consequences for any action they deem in violation of this Code of Conduct:
### 1. Correction
**Community Impact**: Use of inappropriate language or other behavior deemed
unprofessional or unwelcome in the community.
**Consequence**: A private, written warning from community leaders, providing
clarity around the nature of the violation and an explanation of why the
behavior was inappropriate. A public apology may be requested.
### 2. Warning
**Community Impact**: A violation through a single incident or series of
actions.
**Consequence**: A warning with consequences for continued behavior. No
interaction with the people involved, including unsolicited interaction with
those enforcing the Code of Conduct, for a specified period of time. This
includes avoiding interactions in community spaces as well as external channels
like social media. Violating these terms may lead to a temporary or permanent
ban.
### 3. Temporary Ban
**Community Impact**: A serious violation of community standards, including
sustained inappropriate behavior.
**Consequence**: A temporary ban from any sort of interaction or public
communication with the community for a specified period of time. No public or
private interaction with the people involved, including unsolicited interaction
with those enforcing the Code of Conduct, is allowed during this period.
Violating these terms may lead to a permanent ban.
### 4. Permanent Ban
**Community Impact**: Demonstrating a pattern of violation of community
standards, including sustained inappropriate behavior, harassment of an
individual, or aggression toward or disparagement of classes of individuals.
**Consequence**: A permanent ban from any sort of public interaction within the
community.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
version 2.1, available at
[https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1].
Community Impact Guidelines were inspired by
[Mozilla's code of conduct enforcement ladder][Mozilla CoC].
For answers to common questions about this code of conduct, see the FAQ at
[https://www.contributor-covenant.org/faq][FAQ]. Translations are available at
[https://www.contributor-covenant.org/translations][translations].

View File

@ -5,39 +5,22 @@ If you plan to contribute to Documenso, please take a moment to feel awesome ✨
## Before getting started
- Before jumping into a PR be sure to search [existing PRs](https://github.com/documenso/documenso/pulls) or [issues](https://github.com/documenso/documenso/issues) for an open or closed item that relates to your submission.
- Select an issue from [here](https://github.com/documenso/documenso/issues) or create a new one
- Consider the results from the discussion on the issue
- Accept the [Contributor License Agreement](https://documen.so/cla) to ensure we can accept your contributions.
## 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 intention to work on it
You can then:
1. Comment on the issue with your intention to work on it
2. Begin work on the issue
Always feel free to ask questions or seek clarification on the issue.
- Select and issue from [here](https://github.com/documenso/documenso/issues) or create a new one
- Consider the results from the discussion in the issue
## Developing
The development branch is <code>main</code>. All pull requests should be made against this branch. If you need help getting started, [join us on Discord](https://documen.so/discord).
The development branch is <code>main</code>. All pull request should be made against this branch. If you need help getting started, [join us on Slack](https://join.slack.com/t/documenso/shared_invite/zt-1qwxxsvli-nDyojjt~wakhgBGl9JRl2w).
1. [Fork](https://help.github.com/articles/fork-a-repo/) this repository to your
own GitHub account and then
[clone](https://help.github.com/articles/cloning-a-repository/) it to your local device.
2. Create a new branch:
- Create a new branch (include the issue id and something readable):
- Create a new branch (include the issue id and somthing readable):
```sh
git checkout -b feat/doc-999-somefeature-that-rocks
git checkout -b doc-999-my-feature-or-fix
```
3. See the [Developer Setup](https://github.com/documenso/documenso/blob/main/README.md#developer-setup) for more setup details.
@ -45,7 +28,7 @@ The development branch is <code>main</code>. All pull requests should be made ag
## Building
> **Note**
> Please ensure you can make a full production build before pushing code or creating PRs.
> Please be sure that you can make a full production build before pushing code or creating PRs.
You can build the project with:

View File

@ -1,6 +0,0 @@
# The Documenso Manifest
Signing documents is a fundamental building block of private, economic, and government interactions. Access to easy and secure signing to participate in society should therefore be a fundamental right for everyone. The technology to enable this should be accessible and widespread.
We know that open source is the key to solving this need once and for all to benefit all humankind. Using open source kickstarts innovation by putting the open sharing of ideas and solutions first. With Documenso, we will create an open and globally accessible signing platform to empower users, customers, and developers to fulfill their needs. Documenso is built by and for the global community, listening and implementing what is needed. Being transparent with the code and the processes that use it brings trust and security to the platform.
We build Documenso for longevity and scale by embracing the capital efficiency and inclusiveness of the Commercial Open Source (COSS) movement. We are building a global commodity for the world.

385
README.md
View File

@ -1,310 +1,207 @@
<img src="https://github.com/documenso/documenso/assets/13398220/a643571f-0239-46a6-a73e-6bef38d1228b" alt="Documenso Logo">
<p align="center" style="margin-top: 120px">
<a href="https://github.com/documenso/documenso.com">
<img width="250px" src="https://github.com/documenso/documenso/assets/1309312/cd7823ec-4baa-40b9-be78-4acb3b1c73cb" alt="Documenso Logo">
</a>
<h3 align="center">Open Source Signing Infrastructure</h3>
<p align="center" style="margin-top: 20px">
<p align="center">
The Open Source DocuSign Alternative.
<br>
The DocuSign Open Source Alternative.
<br />
<a href="https://documenso.com"><strong>Learn more »</strong></a>
<br />
<br />
<a href="https://documen.so/discord">Discord</a>
<a href="https://documen.so/slack">Slack</a>
·
<a href="https://documenso.com">Website</a>
·
<a href="https://github.com/documenso/documenso/issues">Issues</a>
·
<a href="https://documen.so/live">Upcoming Releases</a>
·
<a href="https://documen.so/roadmap">Roadmap</a>
<a href="https://github.com/documenso/documenso/milestones">Roadmap</a>
</p>
</p>
<p align="center">
<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://documen.so/slack"><img src="https://img.shields.io/badge/Slack-documenso.slack.com-%234A154B" alt="Join Documenso on Slack"></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="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%;" />
# Documenso 0.9 - Developer Preview
<div>
<img style="display: block; height: 120px; width: 24%"
src="https://user-images.githubusercontent.com/1309312/224570645-167128ee-3e39-4578-85d2-5394d9a0379c.png">
<img style="display: block; height: 120px; width: 24%"
src="https://user-images.githubusercontent.com/1309312/224570651-0afd12f8-cfe3-49d1-805e-e495af963d91.png">
<img style="display: block; height: 120px; width: 24%"
src="https://user-images.githubusercontent.com/1309312/224570655-328d2279-058d-4a3e-b5c3-5cbd8a1f4e05.png">
<img style="display: block; height: 120px; width: 24%"
src="https://user-images.githubusercontent.com/1309312/224571617-1f3c2811-c1ac-4d7d-b9b0-4ab183731405.png">
<img style="display: block; height: 120px; width: 24%"
src="https://user-images.githubusercontent.com/1309312/224570322-b2c76ea8-7482-4043-ad97-f1221220c591.png">
<img style="display: block; height: 120px; width: 24%"
src="https://user-images.githubusercontent.com/1309312/224570325-a8055f24-9826-4a23-b116-4fbb0577581a.png">
<img style="display: block; height: 120px; width: 24%"
src="https://user-images.githubusercontent.com/1309312/224570318-f724bbd9-c394-4bdc-bace-2d78af92de44.png">
<img style="display: block; height: 120px; width: 24%"
src="https://user-images.githubusercontent.com/1309312/224571539-f019b860-f613-4b20-86e8-4437c5784265.png">
</div>
> **Note**
> This project is currently under community review and will publish it's first production release soon™.
## 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.
Join us in creating the next generation of open trust infrastructure.
Signing documents digitally is fast, easy and should be 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.
## Recognition
<p align="center">
<a href="https://www.producthunt.com/posts/documenso?utm_source=badge-top-post-badge&utm_medium=badge&utm_souce=badge-documenso" target="_blank"><img src="https://api.producthunt.com/widgets/embed-image/v1/top-post-badge.svg?post_id=395047&theme=light&period=daily" alt="Documenso - The&#0032;open&#0032;source&#0032;DocuSign&#0032;alternative | Product Hunt" style="width: 250px; height: 54px;" width="250" height="54" /></a>
<a href="https://www.producthunt.com/posts/documenso?utm_source=badge-featured&utm_medium=badge&utm_souce=badge-documenso" target="_blank"><img src="https://api.producthunt.com/widgets/embed-image/v1/featured.svg?post_id=395047&theme=light" alt="Documenso - The&#0032;Open&#0032;Source&#0032;DocuSign&#0032;Alternative&#0046; | Product Hunt" style="width: 250px; height: 54px;" width="250" height="54" /></a>
</p>
<a href="https://www.producthunt.com/posts/documenso?utm_source=badge-top-post-badge&utm_medium=badge&utm_souce=badge-documenso" target="_blank"><img src="https://api.producthunt.com/widgets/embed-image/v1/top-post-badge.svg?post_id=395047&theme=light&period=daily" alt="Documenso - The&#0032;open&#0032;source&#0032;DocuSign&#0032;alternative | Product Hunt" style="width: 250px; height: 54px;" width="250" height="54" /></a>
<a href="https://www.producthunt.com/posts/documenso?utm_source=badge-featured&utm_medium=badge&utm_souce=badge-documenso" target="_blank"><img src="https://api.producthunt.com/widgets/embed-image/v1/featured.svg?post_id=395047&theme=light" alt="Documenso - The&#0032;Open&#0032;Source&#0032;DocuSign&#0032;Alternative&#0046; | Product Hunt" style="width: 250px; height: 54px;" width="250" height="54" /></a>
## Community and Next Steps 🎯
We're currently working on a redesign of the application, including a revamp of the codebase, so Documenso can be more intuitive to use and robust to develop upon.
The current project goal is to <b>[release a production ready version](https://github.com/documenso/documenso/milestone/1)</b> for self-hosting as soon as possible. If you want to help making that happen you can:
- Check out the first source code release in this repository and test it.
- Tell us what you think in the [Discussions](https://github.com/documenso/documenso/discussions).
- Join the [Discord server](https://documen.so/discord) for any questions and getting to know to other community members.
- ⭐ the repository to help us raise awareness.
- Spread the word on Twitter that Documenso is working towards a more open signing tool.
- Fix or create [issues](https://github.com/documenso/documenso/issues), that are needed for the first production release.
- Check out the first source code release in this repository and test it
- Tell us what you think in the current [Discussions](https://github.com/documenso/documenso/discussions)
- Join the [Slack Channel](https://documen.so/slack) for any questions and getting to know to other community members
- ⭐ the repository to help us raise awareness
- Spread the word on Twitter, that Documenso is working towards a more open signing tool
- Fix or create [issues](https://github.com/documenso/documenso/issues), that are needed for the first production release
## Contributing
- To contribute, please see our [contribution guide](https://github.com/documenso/documenso/blob/main/CONTRIBUTING.md).
- To contribute please see our [contribution guide](https://github.com/documenso/documenso/blob/main/CONTRIBUTING.md).
## Contact us
# Tech
Contact us if you are interested in our Enterprise plan for large organizations that need extra flexibility and control.
Documenso is built using awesome open source tech including:
<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>
- [Typescript](https://www.typescriptlang.org/)
- [Javascript (when necessary)](https://developer.mozilla.org/en-US/docs/Web/JavaScript)
- [NextJS (JS Fullstack Framework)](https://nextjs.org/)
- [Postgres SQL (Database)](https://www.postgresql.org/)
- [Prisma (ORM - Object-relational mapping)](https://www.prisma.io/)
- [Tailwind CSS (Styling)](https://tailwindcss.com/)
- [Node SignPDF (Digital Signature)](https://github.com/vbuch/node-signpdf)
- [React-PDF for viewing PDFs](https://github.com/wojtekmaj/react-pdf)
- [PDF-Lib for PDF manipulation](https://github.com/Hopding/pdf-lib)
- Check out `/package.json` and `/apps/web/package.json` for more
- Support for [opensignpdf (requires Java on server)](https://github.com/open-pdf-sign) is currently planned.
## Tech Stack
# Getting Started
- [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
## Requirements
<!-- - Support for [opensignpdf (requires Java on server)](https://github.com/open-pdf-sign) is currently planned. -->
To run Documenso locally you need
## Local Development
- [Node.js (Version: >=18.x)](https://nodejs.org/en/download/)
- Node Package Manager NPM - included in Node.js
- [PostgreSQL (local or remote)](https://www.postgresql.org/download/)
### Requirements
To run Documenso locally, you will need
- Node.js (v18 or above)
- Postgres SQL Database
- Docker (optional)
### Developer Quickstart
## Developer Quickstart
> **Note**: This is a quickstart for developers. It assumes that you have both [docker](https://docs.docker.com/get-docker/) and [docker-compose](https://docs.docker.com/compose/) installed on your machine.
Want to get up and running quickly? Follow these steps:
1. [Fork this repository](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/about-forks) to your GitHub account.
- [Clone the repository](https://help.github.com/articles/cloning-a-repository/) it to your local device.
After forking the repository, clone it to your local device by using the following command:
```sh
git clone https://github.com/documenso/documenso
```
```sh
git clone https://github.com/<your-username>/documenso
```
- Set up your `.env` file using the recommendations in the `.env.example` file.
- Run `npm run dx` in the root directory
- This will spin up a postgres database and inbucket mail server in docker containers.
- Run `npm run dev` in the root directory
- Want it even faster? Just use
```sh
npm run d
```
2. Set up your `.env` file using the recommendations in the `.env.example` file. Alternatively, just run `cp .env.example .env` to get started with our handpicked defaults.
That's it! You should now be able to access the app at http://localhost:3000
3. Run `npm run dx` in the root directory
Incoming mail will be available at http://localhost:9000
- This will spin up a postgres database and inbucket mailserver in a docker container.
4. Run `npm run dev` in the root directory
5. Want it even faster? Just use
```sh
npm run d
```
#### Access Points for Your Application
1. **App** - http://localhost:3000
2. **Incoming Mail Access** - http://localhost:9000
3. **Database Connection Details**
- **Port**: 54320
- **Connection**: Use your favorite database client to connect using the provided port.
4. **S3 Storage Dashboard** - http://localhost:9001
Your database will also be available on port `54320`. You can connect to it using your favorite database client.
## Developer Setup
### Manual Setup
Follow these steps to setup documenso on you local machine:
Follow these steps to setup Documenso on your local machine:
1. [Fork this repository](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/about-forks) to your GitHub account.
After forking the repository, clone it to your local device by using the following command:
```sh
git clone https://github.com/<your-username>/documenso
```
2. Run `npm i` in the root directory
3. Create your `.env` from the `.env.example`. You can use `cp .env.example .env` to get started with our handpicked defaults.
4. Set the following environment variables:
- 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
5. Create the database schema by running `npm run prisma:migrate-dev`
6. Run `npm run dev` in the root directory to start
7. Register a new user at http://localhost:3000/signup
- [Clone the repository](https://help.github.com/articles/cloning-a-repository/) it to your local device.
```sh
git clone https://github.com/documenso/documenso
```
- Run <code>npm i</code> in root directory
- Rename <code>.env.example</code> to <code>.env</code>
- Set DATABASE_URL value in .env file
- You can use the provided test database url (may be wiped at any point)
- Or setup a local postgres sql instance (recommended)
- Create the database scheme by running <code>db-migrate:dev</code>
- Setup your mail provider
- Set <code>SENDGRID_API_KEY</code> value in .env file
- You need a SendGrid account, which you can create [here](https://signup.sendgrid.com/).
- Documenso uses [Nodemailer](https://nodemailer.com/about/) so you can easily use your own SMTP server by setting the <code>SMTP\_\* variables</code> in your .env
- Run <code>npm run dev</code> root directory to start
- Register a new user at http://localhost:3000/signup
---
- Optional: Seed the database using `npm run prisma:seed -w @documenso/prisma` to create a test user and document.
- Optional: Create your own signing certificate.
- To generate your own using these steps and a Linux Terminal or Windows Subsystem for Linux (WSL), see **[Create your own signing certificate](./SIGNING.md)**.
- Optional: Seed the database using <code>npm run db-seed</code> to create a test user and document
- Optional: Upload and sign <code>apps/web/resources/example.pdf</code> manually to test your setup
### Run in Gitpod
- Optional: Create your own signing certificate
- A demo certificate is provided in `/app/web/resources/certificate.p12`
- To generate your own using these steps and a Linux Terminal or Windows Subsystem for Linux (WSL) see **[Create your own signing certificate](#creating-your-own-signing-certificate)**.
- Click below to launch a ready-to-use Gitpod workspace in your browser.
## Updating
[![Open in Gitpod](https://gitpod.io/button/open-in-gitpod.svg)](https://gitpod.io/#https://github.com/documenso/documenso)
- If you pull the newest version from main, using <code>git pull</code>, it may be necessary to regenerate your database client
- You can do this by running the generate command in `/packages/prisma`:
```sh
npx prisma generate
```
- This is not necessary on first clone.
### Run in DevContainer
# Creating your own signing certificate
We support DevContainers for VSCode. [Click here to get started.](https://vscode.dev/redirect?url=vscode://ms-vscode-remote.remote-containers/cloneInVolume?url=https://github.com/documenso/documenso)
For the digital signature of your documents you need a signing certificate in .p12 format (public and private key). You can buy one (not recommended for dev) or use the steps to create a self-signed one:
### Video walkthrough
1. Generate a private key using the OpenSSL command. You can run the following command to generate a 2048-bit RSA key:\
<code>openssl genrsa -out private.key 2048</code>
If you're a visual learner and prefer to watch a video walkthrough of setting up Documenso locally, check out this video:
2. Generate a self-signed certificate using the private key. You can run the following command to generate a self-signed certificate:\
<code>openssl req -new -x509 -key private.key -out certificate.crt -days 365</code> \
This will prompt you to enter some information, such as the Common Name (CN) for the certificate. Make sure you enter the correct information. The -days parameter sets the number of days for which the certificate is valid.
3. Combine the private key and the self-signed certificate to create the p12 certificate. You can run the following command to do this: \
<code>openssl pkcs12 -export -out certificate.p12 -inkey private.key -in certificate.crt</code>
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 <code>/apps/web/resources/certificate.p12</code>
[![Watch the video](https://img.youtube.com/vi/Y0ppIQrEnZs/hqdefault.jpg)](https://youtu.be/Y0ppIQrEnZs)
# Docker
## Docker
> We are still working on the publishing of docker images, in the meantime you can follow the steps below to create a production ready docker image.
We provide a Docker container for Documenso, which is published on both DockerHub and GitHub Container Registry.
Want to create a production ready docker image? Follow these steps:
- 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)
- Run `./docker/build.sh` in the root directory.
- Publish the image to your docker registry of choice.
You can pull the Docker image from either of these registries and run it with your preferred container hosting provider.
# Deploying - Coming Soon™
Please note that you will need to provide environment variables for connecting to the database, mailserver, and so forth.
- Docker support
- One-Click-Deploy on Render.com Deploy
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.
# Troubleshooting
## Self Hosting
## Support IPv6
We support a variety of deployment methods, and are actively working on adding more. Stay tuned for updates!
> Please note that the below deployment methods are for v0.9, we will update these to v1.0 once it has been released.
### Fetch, configure, and build
First, clone the code from Github:
```
git clone https://github.com/documenso/documenso.git
```
Then, inside the `documenso` folder, copy the example env file:
```
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`
> 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!
Now you can install the dependencies and build it:
```
npm i
npm run build:web
npm run prisma:migrate-deploy
```
Finally, you can start it with:
```
npm run start
```
This will start the server on `localhost:3000`. For now, any reverse proxy can then do the frontend and SSL termination.
> 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.
### Run as a service
You can use a systemd service file to run the app. 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
```
### 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)
## Troubleshooting
### I'm not receiving any emails when using the developer quickstart.
When using the developer quickstart, an [Inbucket](https://inbucket.org/) server will be spun up in a docker container that will store all outgoing emails locally for you to view.
The Web UI can be found at http://localhost:9000, while the SMTP port will be on localhost:2500.
### Support IPv6
If you are deploying to a cluster that uses only IPv6, You can use a custom command to pass a parameter to the Next.js start command
In case you are deploying to a cluster that uses only IPv6. You can use a custom command to pass a parameter to the NextJS start command
For local docker run
@ -326,25 +223,5 @@ containers:
- start
- --
- -H
- '::'
- "::"
```
### I can't see environment variables in my package scripts.
Wrap your package script with the `with:env` script like such:
```
npm run with:env -- npm run myscript
```
The same can be done when using `npx` for one of the bin scripts:
```
npm run with:env -- npx myscript
```
This will load environment variables from your `.env` and `.env.local` files.
## Repo Activity
![Repository Activity](https://repobeats.axiom.co/api/embed/622a2e9aa709696f7226304b5b7178a5741b3868.svg)

View File

@ -1,56 +0,0 @@
# Creating your own signing certificate
For the digital signature of your documents you need a signing certificate in .p12 format (public and private key). You can buy one (not recommended for dev) or use the steps to create a self-signed one:
1. Generate a private key using the OpenSSL command. You can run the following command to generate a 2048-bit RSA key:
`openssl genrsa -out private.key 2048`
2. Generate a self-signed certificate using the private key. You can run the following command to generate a self-signed certificate:
`openssl req -new -x509 -key private.key -out certificate.crt -days 365`
This will prompt you to enter some information, such as the Common Name (CN) for the certificate. Make sure you enter the correct information. The -days parameter sets the number of days for which the certificate is valid.
3. Combine the private key and the self-signed certificate to create the p12 certificate. You can run the following command to do this:
`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)
## Docker
> We are still working on the publishing of docker images, in the meantime you can follow the steps below to create a production ready docker image.
Want to create a production ready docker image? Follow these steps:
- cd into `docker` directory
- Make `build.sh` executable by running `chmod +x build.sh`
- Run `./build.sh` to start building the docker image.
- Publish the image to your docker registry of choice (or) If you prefer running the image from local, run the below command
```
docker run -d --restart=unless-stopped -p 3000:3000 -v documenso:/app/data --name documenso documenso:latest
```
Command Breakdown:
- `-d` - Let's you run the container in background
- `-p` - Passes down which ports to use. First half is the host port, Second half is the app port. You can change the first half anything you want and reverse proxy to that port.
- `-v` - Volume let's you persist the data
- `--name` - Name of the container
- `documenso:latest` - Image you have built
## Deployment
We support a variety of deployment methods, and are actively working on adding more. Stay tuned for updates!
## Railway
[![Deploy on Railway](https://railway.app/button.svg)](https://railway.app/template/DjrRRX)
## Render
[![Deploy to Render](https://render.com/images/deploy-to-render-button.svg)](https://render.com/deploy?repo=https://github.com/documenso/documenso)

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:3000](http://localhost:3000) 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.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

View File

@ -1,33 +0,0 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
:root {
--foreground-rgb: 0, 0, 0;
--background-start-rgb: 214, 219, 220;
--background-end-rgb: 255, 255, 255;
}
@media (prefers-color-scheme: dark) {
:root {
--foreground-rgb: 255, 255, 255;
--background-start-rgb: 0, 0, 0;
--background-end-rgb: 0, 0, 0;
}
}
body {
color: rgb(var(--foreground-rgb));
background: linear-gradient(
to bottom,
transparent,
rgb(var(--background-end-rgb))
)
rgb(var(--background-start-rgb));
}
@layer utilities {
.text-balance {
text-wrap: balance;
}
}

View File

@ -1,22 +0,0 @@
import type { Metadata } from "next";
import { Inter } from "next/font/google";
import "./globals.css";
const inter = Inter({ subsets: ["latin"] });
export const metadata: Metadata = {
title: "Create Next App",
description: "Generated by create next app",
};
export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
return (
<html lang="en">
<body className={inter.className}>{children}</body>
</html>
);
}

View File

@ -1,9 +0,0 @@
/** @type {import('next').NextConfig} */
const nextConfig = {};
const withNextra = require('nextra')({
theme: 'nextra-theme-docs',
themeConfig: './theme.config.tsx',
});
module.exports = withNextra(nextConfig);

View File

@ -1,29 +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": {
"next": "14.0.3",
"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,7 +0,0 @@
import '../styles.css'
export default function App({ Component, pageProps }) {
return <Component {...pageProps} />
}

View File

@ -1,44 +0,0 @@
{
"index": {
"title": "Home",
"type": "page",
"theme": {
"layout": "full",
"sidebar": false
},
"display": "hidden"
},
"app": {
"title": "Getting Started",
"type": "page"
},
"faq": {
"title": "FAQ",
"type": "page"
},
"local-development": {
"title": "Local Development",
"type": "page"
},
"public-api": {
"title": "Public API",
"type": "page",
"href": "/fcc/"
},
"webhooks": {
"title": "Webhooks",
"type": "page"
},
"contributing": {
"title": "Contributing Guide",
"type": "page"
},
"---": {
"type": "separator"
},
"GitHub": {
"title": "View on GitHub",
"href": "https://documen.so/github",
"newWindow": true
}
}

View File

@ -1 +0,0 @@
# Getting Started

View File

@ -1,8 +0,0 @@
{
"index": {
"title": "Get started",
"theme": {
"sidebar": false
}
}
}

View File

@ -1,115 +0,0 @@
---
title: Contributing Guide
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
Check out the [local development](/local-development) guide to set up your local environment.
### Pick a Task
Find an issue to work on or create a new one.
- Before starting to work on an issue, ensure that no one else is working on it. If no one is assigned to the issue, feel free to pick it up by leaving a comment on the issue and asking to get it assigned 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 +0,0 @@
# FAQ

View File

@ -1,78 +0,0 @@
export const Wrapper = ({ children }) => {
return <div className="p-24">{children}</div>;
};
<Wrapper>
# Documentation
Welcome to the official Documenso documentation! This documentation is designed to help you get started with Documenso.
For users, we'll guide you through setting up your Documenso account, creating and organizing your documents, collaborating with team members, and leveraging our advanced features. You'll learn how to get the most out of Documenso.
If you're a developer, you'll find detailed information on how to set up your local development environment, work with our API, and utilize webhooks for seamless integration. We'll provide code examples, best practices, and troubleshooting tips to help you effectively incorporate Documenso's features into your applications.
We aim to make our documentation clear, concise, and easy to navigate. If you have any questions, feedback, or suggestions for improving our documentation, please don't hesitate to reach out to us. We want to make your experience with Documenso as smooth and enjoyable as possible.
Let's get started!
## About Documenso
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.
## Our 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>
</Wrapper>

View File

@ -1,7 +0,0 @@
{
"index": "Home",
"quickstart": "Developer Quickstart",
"manual": "Manual Setup",
"docker": "Docker",
"gitpod": "Gitpod"
}

View File

@ -1,177 +0,0 @@
---
title: Docker Development
description: Set up Documenso using Docker for local development.
---
import { Callout, Steps } from 'nextra/components';
# 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, 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, mail server, and other services.
## Prerequisites
Before you begin, ensure that you have the following installed:
- Docker
- Docker Compose (if using the Docker Compose setup)
## 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, you can use the pre-built Docker image from DockerHub or GitHub's Package Registry. Note that 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
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. |

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,15 +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 4 ways of running Documenso locally:
- [Using the developer quickstart](/local-development/quickstart)
- [Manually setting up the development environment](/local-development/manual)
- [Using the Docker image](/local-development/docker)
- [Using Gitpod](/local-development/gitpod)
Pick the one that fits your needs the best.

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](./SIGNING.md)**.
</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,6 +0,0 @@
{
"intro": "Intro",
"authentication": "Authentication",
"versioning": "Versioning",
"api-reference": "API Reference"
}

View File

@ -1,6 +0,0 @@
---
title: 'API Reference'
description: 'Reference documentation for the Documenso public API.'
---
# API Reference

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 to never 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
To authenticate your API requests, you must include the API key in the `Authorization` request header. 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 that 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 that enables 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
There is also the [Swagger documentation](https://app.documenso.com/api/v1/openapi) available, which 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,8 +0,0 @@
{
"intro": {
"title": "Get started",
"theme": {
"sidebar": false
}
}
}

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 that are 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 can 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-Signature` 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,6 +0,0 @@
module.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
};

File diff suppressed because one or more lines are too long

Binary file not shown.

Before

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 137 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 61 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 61 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 49 KiB

View File

@ -1,3 +0,0 @@
@tailwind base;
@tailwind components;
@tailwind utilities;

View File

@ -1,20 +0,0 @@
import type { Config } from "tailwindcss";
const config: Config = {
content: [
"./pages/**/*.{js,ts,jsx,tsx,mdx}",
"./components/**/*.{js,ts,jsx,tsx,mdx}",
"./app/**/*.{js,ts,jsx,tsx,mdx}",
],
theme: {
extend: {
backgroundImage: {
"gradient-radial": "radial-gradient(var(--tw-gradient-stops))",
"gradient-conic":
"conic-gradient(from 180deg at 50% 50%, var(--tw-gradient-stops))",
},
},
},
plugins: [],
};
export default config;

View File

@ -1,49 +0,0 @@
import { useConfig } from 'nextra-theme-docs';
import type { DocsThemeConfig } from 'nextra-theme-docs';
const themeConfig: DocsThemeConfig = {
logo: <span>Documenso Docs</span>,
head: function useHead() {
const config = useConfig<{ title?: string; description?: string }>();
const title = `${config.frontMatter.title} | Documenso Docs` || 'Documenso Docs';
const description = config.frontMatter.description || 'The official Documenso documentation';
return (
<>
<meta httpEquiv="Content-Language" content="en" />
<meta name="title" content={title} />
<meta name="og:title" content={title} />
<meta name="description" content={description} />
<meta name="og:description" content={description} />
</>
);
},
project: {
link: 'https://documen.so/github',
},
chat: {
link: 'https://documen.so/discord',
},
docsRepositoryBase: 'https://github.com/documenso/documenso/tree/main/apps/documentation',
footer: {
text: (
<span>
{new Date().getFullYear()} ©{' '}
<a href="https://documen.so" target="_blank">
Documenso
</a>
.
</span>
),
},
primaryHue: 100,
primarySaturation: 48.47,
useNextSeoProps() {
return {
titleTemplate: '%s | Documenso Docs',
};
},
};
export default themeConfig;

View File

@ -1,27 +0,0 @@
{
"compilerOptions": {
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"strict": true,
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve",
"incremental": true,
"plugins": [
{
"name": "next"
}
],
"paths": {
"@/*": ["./*"]
},
"forceConsistentCasingInFileNames": true
},
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
"exclude": ["node_modules"]
}

View File

@ -1 +0,0 @@
declare module '@documenso/tailwind-config';

View File

@ -1,51 +0,0 @@
---
title: Announcing Documenso
description: Launching an open-source document signing tool because trusted-based products should be built on openness. The first release will be in 2023. Sign up at documenso.com to be on board.
authorName: 'Timur Ercan'
authorImage: '/blog/blog-author-timur.jpeg'
authorRole: 'Co-Founder'
date: 2022-12-29
tags:
- Announcement
---
<figure>
<MdxNextImage
src="/blog/blog-banner-announcing-documenso.webp"
width="1400"
height="884"
alt="Documenso announcement blog banner"
/>
<figcaption className="text-center">Documenso — The Open Source DocuSign Alternative.</figcaption>
</figure>
## TL; DR;
I'm launching an open source document signing tool because trust-based products should be built on openness. The first release will be in 2023. Sign up at <a href="https://documenso.com" target="_blank">documenso.com</a> and get on board.
## Lets build the worlds most trusted document-signing tool.
Today I'm excited to announce my new project Documenso. Documenso is an open source document signing tool you can host yourself and freely build upon because it's, you know, open source. Before I get more into the details of what and when will be launched I want to take a moment and talk about why.
## Digital signing is great
Signing Documents digitally has countless benefits: Less struggle with printing, less wasting paper, faster request delivery, easier changes, easier coordination of people far away, verifiable document integrity, and verifiable signer identity (this is a vast topic, will write more on soon), easier storage and search of signed documents, the list goes on. Digital Signatures take something very old and very trusted like personally signing documents into the digital space, adding the benefits listed above. It also introduces a new party to every signing transaction, the signing tool providers. What was peer to peer transaction before, now goes through an intermediary. While this isn't a problem in itself, it should make us think about how we want these providers of trust to work.
## How do we build trusted systems?
While doing research for Documenso I came upon a quote that expresses the current state of document signing pretty well:
> Document signing is NOT a technical problem. [Editors Note: Because it was solved technically a long time ago] Its a legal acceptance problem — and everyone KNOWS DocuSign and friends and understands how theyre admissible. Anything else would have to compete with that and people would be suspicious of it for a long time.
While this may sound like a hurdle at first, it immediately gave me a sense of validation for a more open approach to signing. People will and should be suspicious of their tools and demand a high bar when it comes to trust. And the way to earn this trust is by being open. Trusted tools should be the result of thoughtful discussion and reviews. They should be the result of the needs and will of its community. They should be transparent, adaptable, and empowering while using. Open Source embodies these values very well for software, which makes it a perfect fit for this space and creating a high-trust tool.
## Next Steps
So, what can you expect from here on out? I've started to build Documenso 0.1 which is scheduled to release in “early” 2023. If you're interested in helping make this happen, let me know via [hi@documenso.com](mailto:hi@documenso.com). Getting working code into the hands of the perspective Documenso community is currently the #1 goal. Other than that I'll be releasing several articles about document signing and what something like Documenso should look like, in my humble opinion. So stay tuned!
If you think Documenso is worthy of support, please share <a href="https://documenso.com" target="_blank">documenso.com</a> with anyone interested, and sign up to be among the first to try out version 0.1 as soon as it launches.
Cheers from Hamburg
Timur

View File

@ -1,98 +0,0 @@
---
title: 'Building Documenso — Part 1: Certificates'
description: Let's take a look why you need a signing certificate and how Documenso does it.
authorName: 'Timur Ercan'
authorImage: '/blog/blog-author-timur.jpeg'
authorRole: 'Co-Founder'
date: 2023-06-23
tags:
- Open Source
- Document Signature
- Certificates
- Signing
---
<figure>
<MdxNextImage
src="/blog/blog-banner-building-documenso.webp"
width="1200"
height="675"
alt="Building Documenso blog banner"
/>
<figcaption className="text-center">
What actually is a signature?
</figcaption>
</figure>
> Disclaimer: Im not a lawyer and this isnt legal advice. We plan to publish a much more specific framework on the topic of signature validity.
This is the first installment of the new Building Documenso series, where I describe the challenges and design choices that we make while building the worlds most open signing platform.
As you may have heard, we launched the community-reviewed <a href="https://github.com/documenso/documenso" target="_blank">version 0.9 of Documenso on GitHub</a> recently and its now available through the early adopters plan. One of the most fundamental choices we had to make on this first release, was the choice of certificate. While its interesting to know what we opted for, this shall also serve as a guide for everyone facing the same choice for self-hosting Documenso.
> Question: Why do I need a document signing certificate to self-host?
>
> Short Answer: Inserting the images of a signature into the document is only part of the signing process.
To have an actual digitally signed document you need a document signing certificate that is used to create the digital signature that is inserted into the document, alongside the visible one¹.
When hosting a signature service yourself, as we do, there are four main choices for handling the certificate: Not using a certificate, creating your own, buying a trusted certificate, and becoming and trusted service provider to issue your own trusted certificate.
## 1\. No Certificate
A lot of signing services actually dont employ actual digital signatures besides the inserted image. The only insert and image of the signatures into the document you sign. This can be done and is legally acceptable in many cases. This option isnt directly supported by Documenso without changing the code.
## 2\. Create your own
Since the cryptography behind certificates is freely available as open source you could generate your own using OpenSSL for example. Since its hardly more work than option 1 (using Documenso at least), this would be my minimum effort recommendation. Having a self-created (“self-signed”) certificate doesnt add much in terms of regulation but it guarantees the documents integrity, meaning no changes have been made after signing². What this doesnt give you, is the famous green checkmark in Adobe Acrobat. Why? Because you arent on the list of providers Adobe “trusts”.³
## 3\. Buy a “trusted” certificate.
There are Certificate Authorities (CAs) that can sell you a certificate⁴. The service they provide is, that they validate your name (personal certificates) or your organizations name (corporate certificate) before creating your certificate for you, just like you did in option 2. The difference is, that they are listed on the previously mentioned trust lists (e.g. Adobes) and thus the resulting signatures get a nice, green checkmark in Adobe Reader⁵
## 4\. Becoming a Trusted Certificate Authority (CA) yourself and create your own certificate
This option is an incredibly complex endeavour, requiring a lot of effort and skill. It can be done, as there are multiple CAs around the world. Is it worth the effort? That depends a lot on what youre trying to accomplish.
<center>.&nbsp;&nbsp;.&nbsp;&nbsp;.</center>
## What we did
Having briefly introduced the options, here is what we did: Since we aim to raise the bar on digital signature proliferation and trust, we opted to buy an “Advanced Personal Certificates for Companies/Organisations” from WiseKey. Thus, documents signed with Documensos hosted version look like this:
<figure>
<MdxNextImage
src="/blog/blog-fig-building-documenso.webp"
width="1262"
height="481"
alt="Figure 1"
/>
<figcaption className="text-center">The famous green checkmark: Signed by hosted Documenso</figcaption>
</figure>
There werent any deeper reasons we choose WiseKey, other than they offered what we needed and there wasnt any reason to look much further. While I didnt map the entire certificate market offering (yet), Im pretty sure something similar could be found elsewhere. While we opted for option 3, choosing option 2 might be perfectly reasonable considering your use case.⁶
> While this is our setup, for now, we have a bigger plan for this topic. While globally trusted SSL Certificates have been available for free, courtesy of Lets Encrypt, for a while now, there is no such thing as document signing. And there should be. Not having free and trusted infrastructure for signing is blocking a completely new generation of signing products from being created. This is why well start working on option 4 when the time is right.
Do you have questions or thoughts about this? As always, let me know in the comments, on <a href="http://twitter.com/eltimuro" target="_blank">twitter.com/eltimuro</a>
or directly: <a href="https://documen.so/timur" target="_blank">documen.so/timur</a>
Join the self-hoster community here: <a href="https://documen.so/discord" target="_blank">https://documen.so/discord</a>
Best from Hamburg
Timur
\[1\] There are different approaches to signing a document. For the sake of simplicity, here we talk about a document with X inserted signature images, that is afterward signed once the by signing service, i.e. Documenso. If each visual signature should have its own digital one (e.g. QES — eIDAS Level 3), the case is a bit more complex.
\[2\] Of course, the signing service provider technically can change and resign the document, especially in the case mentioned in \[1\]. This can be countered by requiring actual digital signatures from each signer, that are bound to their identity/ account. Creating a completely trustless system in the context however is extremely hard to do and not the most pressing business need for the industry at this point, in my opinion. Though, this would be nice.
\[3\] Adobe, like the EU, has a list of organizations they trust. The Adobe green checkmark is powered by the Adobe trust list, if you want to be trusted by EU standards here: <a href="https://ec.europa.eu/digital-building-blocks/DSS/webapp-demo/validation" target="_blank">https://ec.europa.eu/digital-building-blocks/DSS/webapp-demo/validation</a>, you need to be on the EU trust list. Getting on each list is possible, though the latter is much more work.
\[4\] Technically, they sign your certificate creation request (created by you), containing your info with their certificate (which is trusted), making your certificate trusted. This way, everything you sign with your certificate is seen as trusted. They created their certificate just like you, the difference is they are on the lists, mentioned in \[3\]
\[5\] Why does Adobe get to say, what is trusted? They simply happen to have the most used pdf viewer. And since everyone checks there, whom they consider trusted carries weight. If it should be like this, is a different matter.
\[6\] Self-Signed signatures, even purely visual signatures, are fully legally binding. Why you use changes mainly your confidence in the signature and the burden of proof. Also, some industries require a certain level of signatures e.g. retail loans (QES/ eIDAS Level 3 in the EU).

View File

@ -1,117 +0,0 @@
---
title: 'Building Documenso — Part 2: Signature Validity'
description: Is a signature valid? And what does that mean? It's a surprisingly complex question; let's take a look.
authorName: 'Timur Ercan'
authorImage: '/blog/blog-author-timur.jpeg'
authorRole: 'Co-Founder'
date: 2024-04-05
tags:
- Document Signature
- Certificates
- Signing
---
<figure>
<MdxNextImage
src="/blog/eu-validate-1.png"
width= "650"
height= "650"
alt= "A report card for signature validity."
/>
<figcaption className="text-center">
If a tree does not comply with the EU trust list, does it make a sound when validating?r
</figcaption>
</figure>
> TLDR; Signatures can be valid and compliant for different signature levels, even if some validators show higher-level errors. Not all helpful security measures are mandated by law.
# A valid question
A few days ago, an early adopter brought up this question in our [Discord](https://documen.so/discord):
<figure>
<MdxNextImage
src="/blog/eu-validate-2.png"
width= "650"
height= "650"
alt= "A report card for signature validity."
/>
<figcaption className="text-center">
You can check out the validator here: [https://documen.so/eu-validator](https://documen.so/eu-validator)
</figcaption>
</figure>
For those unfamiliar with the tool, he used the validator tool of the EU's Digital Signature Service (DSS) Framework to check the signature of a document signed with Documenso. The EU provides this tool to help users and providers check the validity level of their signatures.
A short refresher from [Building Documenso — Part 1: Certificates](https://documen.so/certs):
> Documenso inserts all visual signatures into the document and then seals it using the "Documenso Inc." corporate certificate. This makes the resulting PDF document tamper-proof and guarantees it hasn't changed since signing.
Before we answer if the document was signed correctly, we need to understand what the goal was.
There are three signature levels in the European eIDAS regulation:
1. **Simple Electronic Signatures (Level 1/ SES):** This is just a visual signature or even a checkbox on a document.
2. **Advanded Electronic Signatures (Level 2/ AES)**: An actual crypographic signature (not just a seal on the whole document, but a specific signature), using a certificate linked to the identification data of the signer.
3. **Qualified Electronic Signatures (Level 3/ QES):** Same as 2. but done by a government-certified entity on certified hardware and after identifying the signer with an official ID document (e.g., passport)
> 💡 Side Note: Number 2 (AES) is how most people imagine digital signatures. But most of the market uses 1. plus a seal on the whole document under the name of the signing provider (e.g., Documenso). The signer's data is only inserted visually, not in the actual signature. Why? One of the reasons is that it's much easier, and without a readily available open source framework to draw from, it is quite tricky to build. This is something we aim to build (which many have done) and open source (which no one has done).
From the perspective of eIDAS, Documenso offers Level 1/ SES signatures since it does not adhere to all of the requirements of Level 2/ AES. This means that, technically, there is no legal need to seal the document to achieve this level of validity (at least within eIDAS). We do it anyway since it improves the level of confidence users can have in the signed document. Sealing the document, even though not legally required, is a great example of Documenso's approach to signatures. First, we aim to provide all legal requirements for a given use case. Then, we add any protection that can be added without unwarranted friction to the creation of the signature.
## Not if valid, but how valid
**Q: So, is the signature in the image valid?**
A: Yes, as an eidas Level 1 SES.
**Q: Then why does it say "Unable to build a certificate chain up to a trusted list"**
A: The certificate we use to seal the document after inserting the signatures is not on the EU Trust list.
**Q: Does that mean it is less secure?**
A: No, it means the provider (Wisekey) is not on a list maintained by the EU. The cryptographic signature is just as strong as any other
For someone who does not deal with this stuff daily, this can be hard to comprehend. Whether you use a certificate you generated yourself, one generated by a certificate authority (CA) like Wisekey, or one by another on the EU trust list (e.g., Bundesdruckerei), the cryptographic security guaranteeing that the document has not been tampered with is always the same. Many providers like Documenso, DocuSign, PandaDoc, and Digisigner all use this method for their regular plans. That means if you were to run a document signed by them through the validator above, the result would be the same[1]. The interesting question is why? Why do it like this?
## Certificate Infrastructure is broken
While there are some actual expenses involved in providing AES and QES, the blunt reality is that it's just good business to charge for them per signature, making it unsuitable for the "standard offerings"; almost no one has the resources to set this up themselves. While this initial process of becoming a QES-certified entity is really expensive, selling the certificates afterward is very lucrative. This leads to less innovation in the space and only big players providing these high-compliance services. Even certificates only used to seal documents without being QES certified are sold for a large range of prices, and they cost almost nothing to produce.
## Why Though?
**Q: Why do people buy a certificate for money and not just generate one themselves? Isn't the cryptographic security the same?**
A: Self-generated certificates are not recognized for higher-level compliance signatures like QES
**Q: So if you don't need higher-level signatures, you could just generate one yourself?**
A: Yes, you could. Since eIDAS Level 1 does not require a cert, you could use your own.
**Q: Why don't more people?**
A: One reason is that apart from the EU trust list, there are others, like the Adobe trust list. While not legally required, being on that one (like Wisekey) gives you a green checkmark in Adobe PDF, which is how most people check signature validity.
**Q: Not a question, but all of this sounds weird**
A: It is. This is one of the reasons why Documenso exists. We plan to make this easier.
**Q: How?**
A: By explaining and providing easy-to-use tools and eventually free, highly compliant signature certificates for everyone.
Eventually, we plan to start a free certificate authority called Let's Sign, named after another instituion that broke the paid certificate paradigm to the benefit of the internet: [Let's Encrypt](https://letsencrypt.org/).
As always, feel free to connect on [Twitter / X](https://twitter.com/eltimuro) (DM open) or [Discord](https://documen.so/discord) if you have any questions or comments.
Best from Hamburg\
Timur
\
\
\
[1] The signature format (e.g. PKCS7-B) will vary. It's the format what the signature inserted into the document looks like. eIDAS itself does not specifically require any given format, but the PAdES defined by the EU is mostly used by european providers.

View File

@ -1,87 +0,0 @@
---
title: Commodifying Signing
description: We are creating signing as a public good and are commoditizing it to make it cheaper and better.
authorName: 'Timur Ercan'
authorImage: '/blog/blog-author-timur.jpeg'
authorRole: 'Co-Founder'
date: 2024-01-25
tags:
- Vision
- Mission
- Open Source
---
<figure>
<MdxNextImage
src="/blog/lighthouse.jpeg"
width="650"
height="650"
alt="A lighthouse on a tiny island."
/>
<figcaption className="text-center">
Lighthouses are often used as an example of a public good; As they benefit all maritime users, but no one can be excluded from using them as a navigational aid. Use by one person neither prevents access by other people, nor does it reduce availability to others.
</figcaption>
</figure>
# Commodifying Signing
> TLDR; We are creating signing as a public good and are commoditizing it to make it cheaper and better.
While we are in full-on building mode with Documenso, I think a lot about the big picture of what we are attempting to do. One phrase that keeps popping up is, "We are commodifying signing." Let's dig deeper into what that means.
Let's start with why we are doing this. Documenso's mission is to solve the domain of signing once and for all for everyone. In so many calls, I hear stories about how organizations build their own solution because the existing ones are too expensive or need to be more flexible. That means not hundreds but probably thousands of companies worldwide have done the same. This is simply wasting humanity's time. Since digital signing systems are understood well enough that seemingly "everyone" can build them, given enough pain, It's time to do it once correctly.
## Is signing already a commodity?
> In economics, a **commodity** is an economic good, usually a resource, that has explicitly full or substantial fungibility: that is, the market treats instances of the good as equivalent or nearly so with no regard to who produced them.
That sounds like the signing market today. There is no shortage of signing providers, and you can get similar signing services from many places. So why is this different from what we want, and why does this not satisfy the market?
- Signing is expensive and painful when you are locked into your vendor, and they charge by signing volume.
- Signing is also expensive and painful when you have to build it yourself since no vendor fits your requirements or you are not allowed to
To understand why, we need to look at the landscape as it is today:
- **Commodity**: Signing SaaS
- **Private Goods**: Signing Code Base, Regulatory Know-How
- **Public Goods**: Web Tech, Digital Signature Algorithms and Standards
What the current players have done is to commodify the listed public goods into commercial products:
> […]the action and process of transforming goods, services, ideas, nature, personal information, people, or animals into commodities.
> (Let's ignore the end of that list for now and what it says about humanity, yikes)
While this paradigm brought digital signing to many businesses worldwide, we aim for a different future. To solve signing once and for all, we need to achieve two core points:
- Making it cheaper so it's profitable for everyone to use
- Making it more accessible so everyone can use it (e.g. regulated industries) and flexible enough (extendable, open).
To achieve this, we must transform the landscape to look like this:
- **Commodities**: Enterprise Components, Support, Hosting, Self-Host Licenses
- **Public Goods**: (no longer private): OS (Open Source) Signing Code Base, OS Regulatory Know-How
- **Public Goods**: OS Web Tech, Digital Signature Algorithms and Standards
## Raising the Bar
Before creating a commodity, we are raising the bar of what the underlying public good is. Having an open source singing framework you can extend, self-host, and understand makes the resulting solution much more accessible and extendable for everyone. Now for the final feat of making signing cheaper:
As we have seen, signing has already been commodified. But since it was done by a closed source and, frankly, a very opaque industry, no downward price spiral has ensued. By building Documenso open source with an open culture, we can pierce the veil and trigger what the space has been missing for a long time: Commoditization. If you had to read that again, so did I:
> In business literature, **commoditization** is defined as the process by which goods that have economic value and are distinguishable in terms of attributes (uniqueness or brand) become simple commodities in the eyes of the market or consumers.
By only selling what creates value for the customer (hosting a highly available service, keeping it compliant, supporting with technical issues and challenges, preparing industry-specific components), we are commoditizing signing since everyone can do it now: The resources enabling it are public goods, aka. open source. A leveled playing field, as described above, is the perfect environment for a community-first, technology-first, and value-first company like Documenso to flourish.
## Changing the Game
In this new world, a company needing signing (literally every company) can decide if the ROI (Return on Investment) of building signing themselves is greater than simply paying for the value-added activities they will need anyway. Pricing our offering not on volume but fixed is a nice additional wedge into the market we intend to use here.
The market dynamic now changes to who can offer the greatest value added to the public goods, driving the price down as this can be done much more efficiently than locking customers into closed source SaaS. Documenso, being a lean company, which we intend to stay with for a long time, will help kickstart this effect. Open Source capital efficiency is real. Our planned enterprise components, hosting support, and partner ecosystem will all leverage this effect.
We will grow our community around the public good, the open-source repo, and create an ecosystem around the commodities built on top of it (components, hosting, compliance, support). We will solve signing once and for all, and the world will be better for it. Onwards.
As always, feel free to connect on [Twitter / X](https://twitter.com/eltimuro) (DM open) or [Discord](https://documen.so/discord) if you have any questions or comments.
Best from Hamburg\
Timur

View File

@ -1,198 +0,0 @@
---
title: 'Deploying Documenso with Vercel, Supabase and Resend'
description: This is the first part of the new Building Documenso series, where I describe the challenges and design choices that we make while building the worlds most open signing platform.
authorName: 'Ephraim Atta-Duncan'
authorImage: '/blog/blog-author-duncan.jpeg'
authorRole: 'Software Engineer Intern'
date: 2023-09-08
tags:
- Open Source
- Self Hosting
- Tutorial
---
In this article, we'll walk you through how to deploy and self-host Documenso using Vercel, Supabase, and Resend.
You'll learn:
- How to set up a Postgres database using Supabase,
- How to install SMTP with Resend,
- How to deploy your project with Vercel.
If you don't know what [Documenso](https://documenso.com/) is, it's an open-source alternative to DocuSign, with the mission to create an open signing infrastructure while embracing openness, cooperation, and transparency.
## Prerequisites
Before we start, make sure you have a [GitHub](https://github.com/signup) account. You also need [Node.js](https://nodejs.org/en) and [npm](https://www.npmjs.com/) installed on your local machine (note: you also have the option to host it on a cloud environment using Gitpod for example; that would be another post). If you need accounts on Vercel, Supabase, and Resend, create them by visiting the [Vercel](https://vercel.com/), [Supabase](https://supabase.com/), and [Resend](https://resend.com/) websites.
Checklist:
- [ ] Have a GitHub account
- [ ] Install Node.js
- [ ] Install npm
- [ ] Have a Vercel account
- [ ] Have a Supabase account
- [ ] Have a Resend account
## Step-by-Step guide to deploying Documenso with Vercel, Supabase, and Resend
To deploy Documenso, we'll take the following steps:
1. Fork the Documenso repository
2. Clone the forked repository and install dependencies
3. Create a new project on Supabase
4. Copy the Supabase Postgres database connection URL
5. Create a `.env` file
6. Run the migration on the Supabase Postgres Database
7. Get your SMTP Keys on Resend
8. Create a new project on Vercel
9. Add Environment Variables to your Vercel project
So, you're ready? Lets dive in!
### Step 1: Fork the Documenso repository
Start by creating a fork of Documenso on GitHub. You can do this by visiting the [Documenso repository](https://github.com/documenso/documenso) and clicking on the 'Fork' button. (Also, star the repo!)
![Documenso](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wkcujctpf86p56bju3mq.png)
Choose your GitHub profile as the owner and click on 'Create fork' to create a fork of the repo.
![Fork the Documenso repository on GitHub](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xf49r2byu9nnd1465niy.png)
### Step 2: Clone the forked repository and install dependencies
Clone the forked repository to your local machine in any directory of your choice. Open your terminal and enter the following commands:
```bash
# Clone the repo using Github CLI
gh repo clone [your_github_username]/documenso
# Clone the repo using Git
git clone <https://github.com/[your_github_username]/documenso.git>
```
You can now navigate into the directory and install the projects dependencies:
```bash
cd documenso
npm install
```
### Step 3: Create a new project on Supabase
Now, let's set up the database.
If you haven't already, create a new project on Supabase. This will automatically create a new Postgres database for you.
On your Supabase dashboard, click the '**New project**' button and choose your organization.
On the '**Create a new project**' page, set a database name of **documenso** and a secure password for your database. Choose a region closer to you, a pricing plan, and click on '**Create new project**' to create your project.
![Create a new project on Supabase](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/w5lqz771iupjyi1ekfdz.png)
### Step 4: Copy the Supabase Postgres database connection URL
In your project, click the '**Settings**' icon at the bottom left.
Under the '**Project Settings**' section, click '**Database**' and scroll down to the '**Connection string**' section. Copy the '**URI**' and update it with the password you chose in the previous step.
![Copy the Supabase Postgres database connection URL](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/y1ldu3qrg9moednbzjij.png)
### Step 5: Create a `.env` file
Create a `.env` file in the root of your project by copying the contents of the `.env.example` file.
Add the connection string you copied from your Supabase dashboard to the `DATABASE_URL` variable in the `.env` file.
The `.env` should look like this:
```bash
DATABASE_URL="postgres://postgres:[YOUR-PASSWORD]@db.[YOUR-PROJECT-REF].supabase.co:5432/postgres"
```
### Step 6: Run the migration on the Supabase Postgres Database
Run the migration on the Supabase Postgres Database using the following command:
```bash
npx prisma migrate deploy
```
### Step 7: Get your SMTP Keys on Resend
So, you've just cloned Documenso, installed dependencies on your local machine, and set your database using Supabase. Now, SMTP is missing. Emails won't go out! Let's fix it with Resend.
In the **[Resend](https://resend.com/)** dashboard, click 'Add API Key' to create a key for Resend SMTP.
![Create a key for Resend SMTP](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uh2rztgn09mlvecl34i5.png)
Next, add and verify your domain in the '**Domains**' section on the sidebar. This will allow you to send emails from any address associated with your domain.
![Verify your domain on Resend](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nxgie0esz530vq5a494o.png)
You can update your `.env` file with the following:
```jsx
SMTP_MAIL_HOST = 'smtp.resend.com';
SMTP_MAIL_PORT = '25';
SMTP_MAIL_USER = 'resend';
SMTP_MAIL_PASSWORD = 'YOUR_RESEND_API_KEY';
MAIL_FROM = 'noreply@[YOUR_DOMAIN]';
```
### Step 8: Create a new project on Vercel
You set the database with Supabase and are SMTP-ready with Resend. Almost there! The next step is to deploy the project — we'll use Vercel for that.
On your Vercel dashboard, create a new project using the forked project from your GitHub repositories. Select the project among the options and click '**Import**' to start running Documenso.
![Create a new project on Vercel](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gdy97tltpnu7vf4fc11f.png)
### Step 9: Add Environment Variables to your Vercel project
In the '**Configure Project**' page, adding the required Environmental Variables is essential to ensure the application deploys without any errors.
Specifically, for the `NEXT_PUBLIC_WEBAPP_URL` and `NEXTAUTH_URL` variables, you must add `.vercel.app` to your Project Name. This will form the deployment URL, which will be in the format: `https://[project_name].vercel.app`.
For example, in my case, the deployment URL is `https://documenso-supabase-web.vercel.app`.
![Add Environment Variables to your Vercel project](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/aru33fk1i19h0valffow.png)
This is a sample `.env` to deploy. Copy and paste it to auto-populate the fields and click **Deploy.** Now, you only need to wait for your project to deploy. Youre going live — enjoy!
```bash
DATABASE_URL='postgresql://postgres:typeinastrongpassword@db.njuigobjlbteahssqbtw.supabase.co:5432/postgres'
NEXT_PUBLIC_WEBAPP_URL='https://documenso-supabase-web.vercel.app'
NEXTAUTH_SECRET='something gibrish to encrypt your jwt tokens'
NEXTAUTH_URL='https://documenso-supabase-web.vercel.app'
# Get a Sendgrid Api key here: <https://signup.sendgrid.com>
SENDGRID_API_KEY=''
# Set SMTP credentials to use SMTP instead of the Sendgrid API.
SMTP_MAIL_HOST='smtp.resend.com'
SMTP_MAIL_PORT='25'
SMTP_MAIL_USER='resend'
SMTP_MAIL_PASSWORD='YOUR_RESEND_API_KEY'
MAIL_FROM='noreply@[YOUR_DOMAIN]'
NEXT_PUBLIC_ALLOW_SIGNUP=true
```
## Wrapping up
![Deploying Documenso](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/secg29j9j40o4u2oa8o8.png)
Congratulations! 🎉 You've successfully deployed Documenso using Vercel, Supabase, and Resend. You're now ready to create and sign your own documents with your self-hosted Documenso!
In this step-by-step guide, you learned how to:
- set up a Postgres database using Supabase,
- install SMTP with Resend,
- deploy your project with Vercel.
Over to you! How was the tutorial? If you enjoyed it, [please do share](https://twitter.com/documenso/status/1700141802693480482)! And if you have any questions or comments, please reach out to me on [Twitter / X](https://twitter.com/EphraimDuncan_) (DM open) or [Discord](https://documen.so/discord).
We're building an open-source alternative to DocuSign and welcome every contribution. Head over to the GitHub repository and [leave us a Star](https://github.com/documenso/documenso)!

View File

@ -1,49 +0,0 @@
---
title: Open Sourcing Documenso's Design
description: It's day 1 of our first launch week. We are kicking it off by open sourcing Documenso's design system! Let's go..
authorName: 'Timur Ercan'
authorImage: '/blog/blog-author-timur.jpeg'
authorRole: 'Co-Founder'
date: 2023-09-25
tags:
- Design
- Open Source
- Community
---
<figure>
<MdxNextImage
src="/blog/designsystem.png"
width="1260"
height="630"
alt="Documenso's Design System"
/>
<figcaption className="text-center">
Documenso's Design System ✨
</figcaption>
</figure>
> TLDR; Our design system is OSS under MIT at [design.documenso.com](https://design.documenso.com)
Today, we are open sourcing our design system, lovingly crafted by [Thilo](https://twitter.com/thilokonzok). The system is public on Figma and will be available at [design.documenso.com](https://design.documenso.com) from here on out.
We are publishing it under the MIT License so everyone can share, remix, and use it as it helps them most.
We chose to start our first launch week with a design topic to emphasize the role design will play in Documenso's company and community culture. As it is historically difficult to bring together open-source software with great design, this is our first step towards encouraging a more design-driven COSS (Commercial Open Source) movement.
## Designers Welcome
We added a designer role in our Discord to create a space for designers to explore and discuss design-related topics of Documenso and signing in general. In the future, we want to foster more coding contributions and start a design culture around the product. As it is much more difficult to incorporate design contributions, we have yet to find a clear plan of what that will look like. I would like to see contributions around stuff we are NOT working on. Designs in that area can inspire and start discussions without the complexities of implementing them immediately — a free-thinking space around everything Documenso. Having a free mandate to design without restriction can create many exciting ideas. Some Ideas worth exploring:
## Areas for design contributions
- Explorations of exciting aspects of signing and document handling:
- What does signing look like when we no longer have skeuomorphic signatures?
- What is signing if we move beyond paper-inspired documents?
- What would the government process look like using Documenso?
- Solutions Concepts for features further down the roadmap, e.g., Widgets in websites
These are fascinating ideas for explorative design. They won't be built 1:1 but shape how we think about signing and where it can go, which is even more critical. If you are interested in product design, you are invited to join our [Discord](https://documen.so/discord) and discuss the future of signing design or the future of Documenso's design system. Also let me know what you think on [X (formerly Twitter)](https://x.com/eltimuro).
Best from Hamburg\
Timur

View File

@ -1,67 +0,0 @@
---
title: The Early Adopters Plan
description: Launch Week Day 4 and we are still early! Early enough for you to get a sweet deal for supporting Documenso's Mission. Join the movement and get a shiny early adopter account in the process.
authorName: 'Timur Ercan'
authorImage: '/blog/blog-author-timur.jpeg'
authorRole: 'Co-Founder'
date: 2023-09-28
tags:
- Paid Plan
- Metrics
- Open Startup
---
<figure>
<MdxNextImage
src="/blog/early.png"
width="1260"
height="630"
alt="XKCD: Bug"
/>
<figcaption className="text-center">
"Being early is, uh, good." -Unknown
</figcaption>
</figure>
> 🔔 UPDATE: We launched <a href="https://documen.so/day1" target="_blank">teams</a> and the early adopters plan will be replaced by the new teams pricing as soon as all availible early adopters seats are filled.
## Community-Driven Development
As we ramp up hiring and development speed for Documenso, I want to discuss how we plan to build its core version.
As we want to be a highly community-driven product, we want to capture the thoughts and ideas of said community in two ways:
1. Everything we plan (i.e. documen.so/roadmap) and build (i.e. documen.so/repo) is public and open to comments and suggestions from everyone by design. We plan to have discussions, streams, and articles showcasing what we're up to, encouraging feedback and iterations on our plans.
2. We're looking for 100 die-hard early adopters to get more deep hands-on feedback. If you want to be among the first to use and help shape Documenso, we have a special offer for you:
## The Early Adopter Plan
- All first 100 signups are entitled to the early adopter plan.
- The plan includes everything we build in the next 12 months and unlimited<sup>1</sup> signatures
- This plan is priced at $30/mo.
- No matter what we add, the price is guaranteed for life as a thank you for supporting Documenso's mission<sup>2</sup>. And we plan to add a lot.
- This also includes unlimited users<sup>3</sup> as part of the upcoming support for teams.
- If you already claimed an early adopter account in the past and canceled, we are happy to reactivate your account with the early adopter pricing. Reach out to support@documenso.com
## Being an Early Adopter
Being eligible for the early adopter plan has no formal requirements like giving feedback or being active in the community. In good faith, we assume you sign the Documenso Supporter Pledge to be part of this. And if you want to use the newest version quietly, that's fine, too. Everything the die-hard community brings up will be carefully considered and prioritized <sup>4</sup>. Also, there will obviously be limited edition merch available for the first 100.
Documenso currently runs the community reviewed 0.9.1 version. Getting from here to the globally loved and adopted signing tool we all deserve will take a lot of work, and we want you on board to help us create it. Join us in shaping the future of open signing and having fun doing it. [Malfunction Mania](https://documenso.com/blog/malfunction-mania) and releasing 1.0 will go a long way.
## Extending our open metrics
As part of our ongoing effort to be open and transparent in our doing, we are adding "Early Adopters" to our [/open page](https://documenso.com/open) page. After we exceed the early adopter slots, this metric will transition to "Customers". When no more early adopter seats can be claimed, the early adopter plan will transition to a standard paid plan. It will still be priced at $30/mo., but will no longer include upcoming features or unlimited seats.
If you have any questions or comments, please reach out on [Twitter / X](https://twitter.com/eltimuro) (DM open) or [Discord](https://documen.so/discord).
Best from Hamburg\
Timur
\
[1] Excluding signatures, we have to pay for i.e. third-party QES
[2] The Documenso Manifest
[3] Within reason. If you are unsure what that means, feel free to contact hi@documenso.com. But it should be fine if you don't plan to onboard a huge enterprise.
[4] We won't be able to build everything everyone asks for. But we firmly plan to listen and build in a way everyone's requirements are met as well as possible.

View File

@ -1,28 +0,0 @@
---
title: Jan 10th Email Provider Security Incident
description: On January 10th, 2022, we were notified by our email provider that they had experienced a security incident.
authorName: 'Lucas Smith'
authorImage: '/blog/blog-author-lucas.png'
authorRole: 'Co-Founder'
date: 2024-01-17
tags:
- Security
---
On January 10th, 2024 we were notified by our email provider that a security incident had occurred. This security incident which had started on January 7th led to a bad actor obtaining access to their database which contains ours and other customers data.
We understand that during this security incident the following has been accessed:
- Email addresses.
- Metadata on emails sent excluding the email body.
While the incident is unfortunate we are pleased with the remediation and the processes that our email provider has put in place to help avoid this kind of situation in the future. Since the incident, our provider has rectified the issue and has engaged a security company to conduct an exhaustive investigation and to help improve their security posture moving forward.
We remain steadfast in our commitment to our current email provider, and will not be taking any further action with relation to changing providers.
We are now working with our legal counsel to ensure that we provide the appropriate notice to all our customers in each jurisdiction. If you have any further questions on this incident please feel free to contact our support team at [support@documenso.com](mailto:support@documenso.com).
We appreciate your ongoing support in this matter.
You can read more on the incident on our providers blog post below:
[https://resend.com/blog/incident-report-for-january-10-2024](https://resend.com/blog/incident-report-for-january-10-2024)

View File

@ -1,64 +0,0 @@
---
title: Launch Week II - Day 1 - Teams
description: Teams for Documenso are here. And they come free for early adopters!
authorName: 'Timur Ercan'
authorImage: '/blog/blog-author-timur.jpeg'
authorRole: 'Co-Founder'
date: 2024-02-26
tags:
- Launch Week
- Teams
- Early Adopter Perks
---
<video
id="vid"
width="100%"
src="https://github.com/documenso/design/assets/1309312/12a85ec7-20bb-4813-9714-e4da42c9cfba"
autoPlay
loop
muted
></video>
> TLDR; Docucmenso now supports teams that share documents, templates and a team mail address. Early Adopter get UNLIMITED<sup>1</sup> Users.
## Kicking off Launch Week II - "Connected"
The day has come! Roughly 5 months after kicked off our first launch week with open sourcing our design and Malfunction Mania, Launch Week #2 is here 🎉 This Launch Week's theme is "connected", since this is all about connecting humans, machines and documents.
Working with documents and getting that signature is a team sport. This is why we are kicking it off today with a very long-awaited feature: Documenso now supports teams!
## Introducing Teams for Documenso
You can now create teams next to your personal account: Simply invite your colleagues, and you can include everyone you like in working with your documents. With teams, you can:
- Send unlimited signature requests with unlimited recipients
- Create, view, edit and sign documents owned by the team
- Define a dedicated team email, to receive signing requests into a team inbox for the owner to sign
- Manage team roles: Member (Create+Edit), Managers (+Manage Team Members), Owner (+Transfer Team +Delete Team + Sign Documents sent to team email)
## Pricing
Together with Teams, we are announcing the new teams pricing:
- $10 per seat per month
- 5 seats minimum
- You can add seats dynamically as needed
This pricing will take effect, as soon as the early adopter seats run out. Want to check out teams: [https://documen.so/teams](https://documen.so/teams).
## Early Adopter Perks
There is one more point on pricing I have been looking forward to for a long time:
All early adopter plans now include **UNLIMITED teams and users**<sup>1</sup> . We appreciate your support so far very much, and I'm happy to announce this first of more early adopter perks to come. We have roughly 48 early adopter plans left, so if you plan to onboard your team, now is a great time to [grab your early adopter seat.](https://documen.so/claim-early-adopters-plan)
We are eager to hear from all teams users how you like this addition and what we can add to make it even better. Connect with us on [Twitter / X](https://twitter.com/eltimuro) (DM open) or [Discord](https://documen.so/discord) if you have any questions or comments! We're always here, and we would love to hear from you :)
> 🚨 We need you help to help us to make this the biggest launch week yet: <a href="https://twitter.com/intent/tweet?text=It's @Documenso Launch Week Day 1! Teams just dropped. Check it out https://documen.so/day1 🚀"> Support us on Twitter </a> or anywhere to spread awareness for open signing! The best posts will receive merch codes 👀
Best from Hamburg\
Timur
\
[1] Within reason. If you are unsure what that means, feel free to contact hi@documenso.com and ask for clarification if it's more than 100.

View File

@ -1,76 +0,0 @@
---
title: Launch Week II - Day 2 - Templates
description: Templates help you prepare regular documents faster. And you can share them with your team!
authorName: 'Timur Ercan'
authorImage: '/blog/blog-author-timur.jpeg'
authorRole: 'Co-Founder'
date: 2024-02-27
tags:
- Launch Week
- Templates
---
<video
id="vid"
width="100%"
src="https://github.com/documenso/design/assets/1309312/c9504db1-26b7-4033-88ed-a95cabd02e92"
autoPlay
loop
muted
></video>
> TLDR; You can now reuse documents via templates. More field types coming soon as well.
## Introducing Templates
It's day 2 of Launch Week, everybody 🙌 After introducing [Teams](https://documenso.com/blog/launch-week-2-day-1) yesterday, today we are looking at making Documenso faster for daily use:
We are launching templates for Documenso! Templates are an easy way to reuse documents you send out often with just a few clicks. With templates, you can:
<figure>
<MdxNextImage
src="/blog/quickfill.png"
width="1260"
height="630"
alt="Template recipients quick fill view"
/>
<figcaption className="text-center">
Quickly fill out recipients, when creating from a template
</figcaption>
</figure>
- Save often-uploaded documents for reuse
- Pre-define fields, so you just have to send the document
- Quickly fill out recipients and roles for new documents
- Share templates with your team to make working together even easier
<figure>
<MdxNextImage
src="/blog/template.png"
width="1260"
height="630"
alt="Create from template view"
/>
<figcaption className="text-center">
POV: You are a diligent german and create custom receipts with Documenso
</figcaption>
</figure>
## Pricing
Templates are **included in all Documenso Plans!** That includes our free tier: The limit of 5 documents per month still applies, but you are free to reach it with less friction using templates. Sharing templates with other users is only possible with the teams plan. If you want to share templates with people not in your team, we might have something coming up later this week 👀
## What's Next for Templates
We have a lot of great stuff coming up for templates as well:
- More Field Types are in the pipeline
- Sharing Templates Externally 👀
Check out templates [here](https://documen.so/templates) and let us know what you think and what we can improve. Which field types are you missing? Connect with us on [Twitter / X](https://twitter.com/eltimuro) (DM open) or [Discord](https://documen.so/discord) if you have any questions or comments! We're always here and would love to hear from you :)
> 🚨 We need you help to help us to make this the biggest launch week yet: <a href="https://twitter.com/intent/tweet?text=It's @Documenso Launch Week Day 2! They just launched templates, and I'm pumped 🎉🚀🚀🚀. Check it out https://documen.so/day2"> Support us on Twitter </a> or anywhere to spread awareness for open signing! The best posts will receive merch codes 👀
Best from Hamburg\
Timur

View File

@ -1,53 +0,0 @@
---
title: Launch Week II - Day 3 - API
description: Documenso's mission is to create a plattform developers all around the world can build upon. Today we are releasing the first version of our public API, included in all plans!
authorName: 'Timur Ercan'
authorImage: '/blog/blog-author-timur.jpeg'
authorRole: 'Co-Founder'
date: 2024-02-28
tags:
- Launch Week
- API
---
<video
id="vid"
width="100%"
src="https://github.com/documenso/design/assets/1309312/cb74d6cb-a127-4cac-a166-ad6b56c6140d"
autoPlay
loop
muted
></video>
> TLDR; The public API is now availible for all plans.
## Introducing the public Documenso API
Launch. Week. Day. 3 🎉 Documenso's mission is to create a platform that developers all around the world can build upon. Today we are releasing the first version of our public API, and we are pumped. Since this is the first version, we focused on the basics. With the new API you can:
- Get Documents (Individual or all Accessible)
- Upload Documents
- Delete Documents
- Create Documents from Templates
- Trigger Sending Documents for Singing
You can check out the detailed API documentation here:
> API DOCUMENTATION: [https://app.documenso.com/api/v1/openapi](https://app.documenso.com/api/v1/openapi)
## Pricing
We are building Documenso to be an open and extendable platform; therefore the API is included in all current plans. The API is authenticated via auth tokens, which every user can create at no extra cost, as can teams. Existing limits still apply (i.e., the number of included documents for the free plan). While we don't have all the details yet, we don't intend to price the API usage in itself (rather the accounts using it) since we want you to build on Documenso without being smothered by API costs.
> Try the API here for free: [https://documen.so/api](https://documen.so/api)
## What's next for the API
You tell us. This is by far the most requested feature, so we would like to hear from you. What should we add? How can we integrate even better?
Connect with us on [Twitter / X](https://twitter.com/eltimuro) (DM open) or [Discord](https://documen.so/discord) if you have any questions or comments! We're always here and would love to hear from you :)
> 🚨 We need you help to help us to make this the biggest launch week yet: <a href="https://twitter.com/intent/tweet?text=It's @Documenso Launch Week Day 3! The public API is here 👀 Check it out https://documen.so/day3"> Support us on Twitter </a> or anywhere to spread awareness for open signing! The best posts will receive merch codes 👀
Best from Hamburg\
Timur

View File

@ -1,63 +0,0 @@
---
title: Launch Week II - Day 4 - Webhooks and Zapier
description: If you want to integrate Documenso without fiddling with the API, we got you as well. You can now integrate Documenso via Zapier, included in all plans!
authorName: 'Timur Ercan'
authorImage: '/blog/blog-author-timur.jpeg'
authorRole: 'Co-Founder'
date: 2024-02-29
tags:
- Launch Week
- Zapier
- Webhooks
---
<video
id="vid"
width="100%"
src="https://github.com/documenso/design/assets/1309312/3b60789d-8d27-4c66-ae5c-179e33c2e3e6"
autoPlay
loop
muted
></video>
> TLDR; Zapier Integration is now available for all plans.
## Introducing Zapier for Documenso
Day 4 🥳 Yesterday we introduced our [public API](https://documen.so/day3) for developers to build on Documenso. If you are not a developer or simple want a quicker integration this is for you: Documenso now support Zapier Integrations! Just connect your Documenso account via a simple login flow with Zapier and you will have access to Zapier's universe of integrations 💫 The integration currently supports:
- Document Created ([https://documen.so/zapier-created](https://documen.so/zapier-created))
- Document Sent ([Chttps://documen.so/zapier-sent](https://documen.so/zapier-sent))
- Document Opened ([https://documen.so/zapier-opened](https://documen.so/zapier-opened))
- Document Signed ([https://documen.so/zapier-signed](https://documen.so/zapier-signed))
- Document Completed ([https://documen.so/zapier-completed](https://documen.so/zapier-completed))
> ⚡️ You can create your own Zaps here: https://zapier.com/apps/documenso/integrations
Each event comes with extensive meta-data for you to use in Zapier. Missing something? Reach out on [Twitter / X](https://twitter.com/eltimuro) (DM open) or [Discord](https://documen.so/discord). We're always here and would love to hear from you :)
## Also Introducing for Documenso: Webhooks
To build the Zapier Integration, we needed a good webhooks concept, so we added that as well. Together with your Zaps, you can also now create customer webhooks in Documenso. You can try webhooks here for free: [https://documen.so/webhooks](https://documen.so/webhooks)
<figure>
<MdxNextImage
src="/blog/hooks.png"
width="1260"
height="630"
alt="Webhooks UI"
/>
<figcaption className="text-center">
Create unlimited custom webhooks with each plan.
</figcaption>
</figure>
## Pricing
Just like the API, we consider the Zapier integration and webhooks part of the open Documenso platform. Zapier is **available for all Documenso plans**, including free! [Login now](https://documen.so/login) to check it out.
> 🚨 We need you help to help us to make this the biggest launch week yet: <a href="https://twitter.com/intent/tweet?text=It's @Documenso Launch Week Day 4! Documenso now supports @Zapier 🤯 https://documen.so/day4"> Support us on Twitter </a> or anywhere to spread awareness for open signing! The best posts will receive merch codes 👀
Best from Hamburg\
Timur

View File

@ -1,61 +0,0 @@
---
title: Launch Week II - Day 5 - Documenso Profiles
description: Documenso profiles allow you to send signing links to people so they can sign anytime and see who you are. Documenso Profile Usernames can be claimed starting today. Long ones free, short ones paid. Profiles will launch as soon as they are shiny.
authorName: 'Timur Ercan'
authorImage: '/blog/blog-author-timur.jpeg'
authorRole: 'Co-Founder'
date: 2024-03-01
tags:
- Launch Week
- Profiles
---
<video
id="vid"
width="100%"
src="https://github.com/documenso/design/assets/1309312/89643ae2-2aa9-484c-a522-a0e35097c469"
autoPlay
loop
muted
></video>
> TLDR; Documenso profiles allow you to send signing links to people so they can sign anytime and see who you are. Documenso Profile Usernames can be claimed starting today. Long ones free, short ones paid. Profiles launch as soon as they are shiny.
## Introducing Documenso Profile Links
Day 5 - The Finale 🔥
Signing documents has always been between humans, and signing something together should be as frictionless as possible. It should also be async, so you don't force your counterpart to jog to their device to send something when you are ready. Today we are announcing the new Documenso Profiles:
<figure>
<MdxNextImage
src="/blog/profile.png"
width="1260"
height="813"
alt="Timur's Documenso Profile"
/>
<figcaption className="text-center">
Async > Sync: Add public templates to your Documenso Link and let people sign whenever they are ready.
</figcaption>
</figure>
Documenso profiles work with your existing templates. You can just add them to your public profile to let everyone with your link sign them. With profiles, we want to bring back the human aspect of signing.
By making profiles public, you can always access what your counterparty offers and make them more visible in the process. Long-term, we plan to add more to profiles to help you ensure the person you are dealing with is who they claim to be. Documenso wants to be the trust layer of the internet, and we want to start at the very fundamental level: The individual transaction.
Profiles are our first step towards bringing more trust into everything, simply by making the use of signing more frictionless. As there is more and more content of questionable origin out there, we want to support you in making it clear what you send out and what not.
## Pricing and Claiming
Documenso profile username can be claimed starting today. Documenso profiles will launch as soon as we are happy with the details ✨
- Long usernames (6 characters or more) come free with every account, e.g. **documenso.com/u/timurercan**
- Short usernames (5 characters or fewer) or less require any paid account ([Early Adopter](https://documen.so/claim-early-adopters-plan), [Teams](https://documen.so/teams) or Enterprise): **e.g., documenso.com/u/timur**
You can claim your username here: [https://documen.so/claim](https://documen.so/claim)
> 🚨 We need you help to help us to make this the biggest launch week yet: <a href="https://twitter.com/intent/tweet?text=It's @Documenso Launch Week Day 5! You can now claim your username for the upcoming profile links 😮 https://documen.so/day5"> Support us on Twitter </a> or anywhere to spread awareness for open signing! The best posts will receive merch codes 👀
Best from Hamburg\
Timur

View File

@ -1,115 +0,0 @@
---
title: Moving from Linear to GitHub & LIVE Roadmap 2.0
description: We are leaving linear and are going all in on GitHub. Here is how we do it.
authorName: 'Timur Ercan'
authorImage: '/blog/blog-author-timur.jpeg'
authorRole: 'Co-Founder'
date: 2024-01-10
tags:
- GitHub
- Backlog
- Roadmap
---
# From Linear to GitHub
> TLDR; We are leaving Linear and are using only GitHub going forward. We no longer communicate feature timelines, only what we are working on and what's next.
If you follow us, you know we have been in full-on build mode. We are building, the community is building, it's great. Building is our daily business, so we think a lot about improving our approach to doing it.
Our most recent approach is to reduce the number of tools and platforms we use. Every tool we use
- Reduces the average time you spend on the tool
- Reduces your focus
- Increases mental load to keep all points of interest in mind
We thought about where we spend the most time, and hardly surprising: it's GitHub. Not only do we spend a lot of time there, but we also WANT to spend a lot of time there because:
- It's where the community contributes, and we are all about community
- It's where we show the world what we are working on
# The old structure
So far, we have been using Linear for our Backlog/ Task Management and synced issues we want to showcase or work on with the community via synclinear.com. Not only did we have our development issues there, but since
we have our own resident founding designer, we created a proper design backlog to structure our design workflows.
# The new structure
We moved everything to GitHub once we realized our focus was already there. This has a few key benefits:
- Reducing dilution of attention and time: You can hang out on GitHub without risk of missing much
- Putting different aspects of Documenso close to each other: Development, Design, Community
- Keep long-term, niche, and very abstract issues out of the main repo so we don't get desensitized by large issue numbers
To achieve this, we created a few GitHub repositories to host issues, with the main repository remaining the central point of interest, especially for the community.
## 1. Main Repository - Day to day Issues and the shorter-term roadmap (LIVE Roadmap 2.0)
> [github.com/documenso/documenso](https://github.com/documenso/documenso)
Apart from the source code of the Documenso app and website, the main repo houses issues raised by the community and issues where we invite the community to participate.
With the overhauling of our issue management, we are also updating our progress communication. While the software and product development process is highly complex,
we try to give as much insight into what we do as possible. To that end, we went through 3 phases, three being what we do now.
1. **One extensive roadmap**: Initially we had one roadmap and were (very) slowly checking off boxes there (via a "Roadmap" milestone). While this is easy, it's also pretty imprecise and not practical as the project grows
2. **Estimated releases per quarter**: To give better guidance, we tried communicating our goals for the quarter; a pretty big window we thought we could roughly "hit". While the idea of not being too detailed was good, it is tough to estimate when some significant things are done if you do a lot of minor/ other things in parallel,
like working with the community and tuning things you go. Hitting time targets is tricky because there may be better things to do than sticking to that time target. This is always much easier to grasp for the people closely involved. The fallacy is to assume the thing you plan for exists in a vacuum.
3. Since we do not want to limit ourselves in choosing the most effective course but still give some insight into what's going on and what's coming up, we updated the live roadmap [https://documen.so/live](https://documen.so/live). It now shows what we are currently working on and what we plan on doing next. We do not provide
a specific timeline anymore since we couldn't even if we wanted to. Of course, we set our short-term goals based on what's best for the community. We give updates on the issues being worked on as well as possible.
## 2. Public Backlog - The longer-term roadmap
> [github.com/documenso/backlog](https://github.com/documenso/backlog)
The public backlog houses everything we want to build eventually. We do not provide a specific timeline of when that might happen. If we decide against something, it will be removed from the public backlog, as we consider this our long-term vision for Documenso. If you are interested in something on the roadmap, comment on the issue or post on Discord. This helps us gauge interest in specific features.
**Issues in the public backlog are not** available to be worked on. For issues to work on, please check the main repository issues. The issues found here are scoped broader since they are not meant for immediate execution but rather give a sense of where Documenso is going and what we consider part of our domain.
## 3. Internal Backlog
> github.com/documenso/backlog-internal
<figure>
<MdxNextImage
src="/blog/gh1.png"
width="1260"
height="630"
alt="GitHub: Development Board"
/>
<figcaption className="text-center">
Our internal Kanban for development
</figcaption>
</figure>
This serves as the direct replacement for our Linear backlog. Here, we manage issues that are either too small or short-term for inclusion in the long-term roadmap, yet too specialized or fundamental to be integrated into the main repository. Our development Kanban board is implemented using a GitHub project.
## 4. Internal Design Backlog
> github.com/documenso/design-internal
<figure>
<MdxNextImage
src="/blog/gh2.png"
width="1260"
height="630"
alt="GitHub: Design Board"
/>
<figcaption className="text-center">
Our internal Kanban for design
</figcaption>
</figure>
This is the design equivalent of the internal backlog. The internal design backlog houses our design projects that include the exploration of new features, detailed UI designs, and improving the platform overall.
It's similar to the Kanban board for the development backlog.
## 5. Public Design Repository
> [github.com/documenso/backlog-design](https://github.com/documenso/design)
While the internal design backlog also existed in Linear, the public design repository is new. Since designing in the open is tricky, we opted to publish the detailed design artifacts with the corresponding feature instead.
We already have design.documenso.com housing our general design system. Here, we will publish the specifics of how we applied this to each feature. We will publish the first artifacts here soon, what may be in the cards can be found on the [LIVE Roadmap](https://documen.so/live).
Feel free to connect with us on [Twitter / X](https://twitter.com/eltimuro) (DM open) or [Discord](https://documen.so/discord) if you have any questions or comments! We're always here to help and would love to hear from you :)
Best from Hamburg\
Timur

View File

@ -1,75 +0,0 @@
---
title: The 🔴 LIVE Roadmap
description: It's the Launch Week Day finale, Day 5! We are going out with a bang and introducing the 🔴 LIVE roadmap, featuring our next Product Hunt Launch - Free Singleplayer Documenso - Sign without creating an account!
authorName: 'Timur Ercan'
authorImage: '/blog/blog-author-timur.jpeg'
authorRole: 'Co-Founder'
date: 2023-09-29
tags:
- Free Plan
- Launch
- Roadmap
---
<figure>
<MdxNextImage
src="/blog/roadmap.png"
width="1260"
height="630"
alt="XKCD: Bug"
/>
<figcaption className="text-center">
"Being early is, uh, good." -Unknown
</figcaption>
</figure>
> TLDR; We are launching a [🔴 LIVE roadmap](https://documen.so/launches), that gets updated regularly.\
> First upcoming launch: A free single signer experience.
## The Road Ahead
It's been quite a week, launching our [design system](https://documenso.com/blog/design-system), [kicking of a Malfunction Mania](https://documenso.com/blog/malfunction-mania), a [shiny new contributor perk](https://documenso.com/blog/shop) and our [early adopter deal](https://documenso.com/blog/early-adopters). After discussing Version 1.0 a lot, we want to close the week by looking ahead. As an open company, we want transparency about what we are working on and what to expect next. Especially for our Early Adopters, we want to paint a clear picture of what to expect in the near term.
Communicating software development progress and goals is historically tricky because of it's complex nature. Exact release dates are notoriously unreliable; if they are not, they force a particular style of development, forcing the team to make tradeoffs on scope and quality.
To give an appropriate insight into our work, we are launching our new [🔴 LIVE roadmap](https://documen.so/launches) today:
- A List of quarterly development and feature goals
- That gets updated regularly (bi-weekly)
- Has up-to-date insights from the team on where we stand
**While there are some great features planned, one stands out: Single Player Mode!**
## Announcing Documenso Singleplayer Mode
<a href="https://www.producthunt.com/products/documenso" target="_blank">
<figure>
<MdxNextImage
src="/blog/sp5.png"
width="1260"
height="630"
/>
<figcaption className="text-center font-bold">
🚨 We are going back to Product Hunt! Are you ready, player one?
</figcaption>
</figure>
</a>
Single Player Mode will be a free, loginless signing experience for single signers. If you hate creating an account to sign a single, once-in-a-while-document yourself as much as we do, we've got you. Our new free tier will accompany Singleplayer. While you don't HAVE to create an account to sign sth. quickly, you can. A free tier Documenso Account will give you the following:
- A place to store all your sent and received Documenso-signed documents
- Free forever
- Unlimited recipients
- 5 free signatures per month (for now, excluding third party types like QES)
- The use of templates, as soon as we [release](https://documen.so/launches) them
Singleplayer will launch in the first half of October, shortly after the release of 1.0, **[ON PRODUCT HUNT!](https://www.producthunt.com/products/documenso)** That's right, we are going back to Product Hunt to kick of this new phase of Documenso and you are invited to join us once again :)
**[Subscribe on PH](https://www.producthunt.com/products/documenso)** to be notified when we launch.
If you have any questions or comments, please reach out on [Twitter / X](https://twitter.com/eltimuro) (DM open) or [Discord](https://documen.so/discord).
Best from Hamburg\
Timur

View File

@ -1,57 +0,0 @@
---
title: Announcing Malfunction Mania
description: Launch Week Day 2 Y'all! We're getting ready to release Documenso 1.0! Join in on the fun of making sure the open-source alternative to DocuSign is on point. We're calling a 'MALFUNCTION MANIA.'
authorName: 'Timur Ercan'
authorImage: '/blog/blog-author-timur.jpeg'
authorRole: 'Co-Founder'
date: 2023-09-26
tags:
- Testing
- Rewrite
- Bounties
---
<figure>
<MdxNextImage
src="/blog/mm.png"
width="1260"
height="630"
alt="Malfunctioning Documenso Logo in broken colors"
/>
<figcaption className="text-center">
We're calling a MALFUNCTION MANIA! 🚨
</figcaption>
</figure>
> TLDR; Documenso 1.0 is in the [staging environment](https://documen.so/staging). Go check it out.
It's been a minute since Lucas proclaimed, ["We're doing a rewrite"](https://documenso.com/blog/why-were-doing-a-rewrite), and many of you have been asking when the new version will be available. I'm happy to say that the wait has come to an end. The work on Documenso 1.0 has reached a level we feel comfortable going into the next phase with. We had a lot of community feedback, contributions, and moral support to get us this far, which is why we're excited to announce the most extensive community project yet:
As Documenso 1.0 just hit the staging environment, we're calling a MALFUNCTION MANIA. An enormous, public testing phase, where we invite everyone to try out the new version, hunt down, report, and fix any malfunctions (aka bugs), and give feedback before release. Malfunction Mania will happen alongside our internal testing, and by combining the two, we want to ensure the best possible release we can have for Version 1.0. We know many of you have been eager to contribute; this is your chance (the first of many to come).
## As part of Malfunction Mania, we're offering special bug bounties
- We award $25 - $100 per report/ issue/ fix, depending on the severity and if the problem is already known
- Bounties will be awarded for fixing reported or other critical issues via accepted Pull Requests (PR)
- Just reporting issues in a reproducible way can also be awarded
- Smaller but notable contributions like minor issues and documentation will be awarded with exclusive merch as we see fit.
## What you can do
- Head over to the [staging environment](https://documen.so/staging), check out the new version and give it a spin;
- Check out the [source code](https://github.com/documenso/documenso) on GitHub and look it over;
- Spin up the new version locally and try it out.
## How to get the bounties
- Report bugs by creating an issue here: [documen.so/issues](https://documen.so/issues);
- Fix bugs by creating a Pull Request (PR);
- Look over and add missing documentation/ Quickstarts and other useful resources.
Best from Hamburg
Timur
We don't have a specific end date for Malfunction Mania. We plan to move the staging version into the production environment by the end of the month once we're happy with the results. Bug reports and fixes are, of course, always welcome going forward.
**[Follow Documenso on Twitter / X](https://documen.so/tw) and [join the Discord server](https://documen.so/discord) to get the latest about Malfunction Mania.**

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