## Description
Feature flags are broken on SSR due to this error
```
TypeError: fetch failed
at Object.fetch (node:internal/deps/undici/undici:11731:11)
at process.processTicksAndRejections (node:internal/process/task_queues:95:5) {
cause: RequestContentLengthMismatchError: Request body length does not match content-length header
at write (node:internal/deps/undici/undici:8590:41)
at _resume (node:internal/deps/undici/undici:8563:33)
at resume (node:internal/deps/undici/undici:8459:7)
at [dispatch] (node:internal/deps/undici/undici:7704:11)
at Client.Intercept (node:internal/deps/undici/undici:7377:20)
at Client.dispatch (node:internal/deps/undici/undici:6023:44)
at [dispatch] (node:internal/deps/undici/undici:6254:32)
at Pool.dispatch (node:internal/deps/undici/undici:6023:44)
at [dispatch] (node:internal/deps/undici/undici:9343:27)
at Agent.Intercept (node:internal/deps/undici/undici:7377:20) {
code: 'UND_ERR_REQ_CONTENT_LENGTH_MISMATCH'
}
}
```
I've removed content-length header since it isn't mandatory to my
knowledge for get requests.
## Changes
- Add fallback local flags when individual flag request fails
- Add error logging
- Remove `content-length` from headers being passed to Posthog
## Description
Upgrade playwright once again and use CDP for remote connections to
avoid version lock-in with `playwright.connect`
Resolves the issue where all CI is failing currently due to downgrading
playwright.
## Description
Currently if you create a team webhook, you can see it in your personal
webhooks.
However, interacting with them will throw errors because there is server
side logic preventing any interaction with them since they are outside
of the correct context.
So the solution is to either:
- Allow the user to edit the team webhooks that they created on their
personal webhooks page
- Hide team webhooks for personal webhooks pages
This PR goes with the second option, but is open to suggestions.
## Description
Added the ability for recipients to see fields from other recipients who
have completed the document when they are signing the document
Added the ability for the document owner to see fields from recipients
who have completed the field on the document page view (only visible
when the document is pending)
## 🚨🚨 Migrations🚨🚨
- Drop all `Fields` that do not have a `Recipient` set (not sure how it
was possible in the first place)
- Remove optional `Recipient` field on `Field` which doesn't make sense
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
## Summary by CodeRabbit
- **New Features**
- Enhanced document viewing by adding read-only fields based on document
status.
- Improved signing page by fetching and displaying completed fields for
tokens.
- Updated avatar component to show recipient status with tooltips for
better user interaction.
- **Bug Fixes**
- Made `recipientId` a required field in the database to ensure data
consistency.
- **Refactor**
- Optimized popover functionality in UI components for better
performance and user experience.
- **Documentation**
- Added detailed component and function descriptions for new features in
the system.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
## Description
Disable the document certificate download button when the document is
not complete
## Changes Made
- Disable UI button
- Disable TRPC API endpoint
## Testing Performed
Tested locally for pending, draft and completed documents
**Description:**
This PR adds a check for filename title and if the title ends with
`.pdf` then the extension isnt added or else its added
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
- **Bug Fixes**
- Enhanced email attachment handling to ensure PDF files are correctly
identified with a ".pdf" extension.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
## Description
Allow users to download a completed document via API.
## Testing Performed
Tested the code locally by trying to download both draft and completed
docs. Works as expected.
## Checklist
- [x] 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.
- [x] I have followed the project's coding style guidelines.
- [ ] I have addressed the code review feedback from the previous
submission, if applicable.
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
- **New Features**
- Implemented functionality to download signed documents directly from
the app.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
## Description
Updated the email content based on whether the document owner is a
recipient or not.
If the document owner is a recipient (self-signer):
* the email subject will be `Please view/sign/approve your document`
* the email header will be `Please view/sign/approve your document
"<your-doc-title>"`
* the email content will be `You have initiated the document
"<your-doc-title>" that requires you to view/sign/approve it.`
Otherwise:
* the email subject will be `Please view/sign/approve this document`
* the email header will be `<doc-owner> has invited you to
view/sign/approve "<doc-title>"`
* the email content will be `<doc-owner> has invited you to
view/sign/approve the document "<doc-title>".`
## Related Issue
Related to #1091
## Testing Performed
Tested the feature with a different number of recipients (including and
excluding the document owner - self-signer). Tested both the sending and
resending functionality.
## Checklist
- [x] 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.
- [x] I have followed the project's coding style guidelines.
- [ ] I have addressed the code review feedback from the previous
submission, if applicable.
## UI Screenshots




<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
## Summary by CodeRabbit
- **New Features**
- Enhanced the document invitation components to support scenarios where
the recipient is also the sender, providing customized email content and
subject lines.
- Introduced new properties in email templates to improve clarity and
relevance based on the user's role in the document signing process.
- **Refactor**
- Updated components to use a more flexible `headerContent` property for
displaying invitation headers, replacing previous individual inviter
details.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
## Description
Currently users can sign and complete draft documents, which will result
in a completed document in an invalid state.
## Changes Made
- Prevent recipients from inserting or uninserting fields for draft
documents
- Prevent recipients from completing draft documents
- Remove ability to copy signing tokens unless document is pending
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
- **New Features**
- Enhanced document status visibility and control across various
components in the application. Users can now see and interact with
document statuses more dynamically in views like `DocumentPageView`,
`DocumentEditPageView`, and `DocumentsDataTable`.
- Improved document signing process with updated status checks, ensuring
actions like signing, completing, and removing fields are only available
under appropriate document statuses.
- **Bug Fixes**
- Adjusted document status validation logic in server-side operations to
prevent actions on incorrectly stated documents, enhancing the overall
security and functionality of document processing.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
## Description
Add additional information for each role to help document owners
understand what each role involves.
## Changes Made



## Testing Performed
Tested the changes locally.
## Checklist
<!--- Please check the boxes that apply to this pull request. -->
<!--- You can add or remove items as needed. -->
- [x] 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.
- [x] I have followed the project's coding style guidelines.
- [ ] I have addressed the code review feedback from the previous
submission, if applicable.
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
- **New Features**
- Updated recipient role terminology and added tooltips in the
`AddSignersFormPartial` component:
- "Signer" changed to "Needs to sign" with tooltip
- "Receives copy" changed to "Needs to approve" with tooltip
- "Approver" changed to "Needs to view" with tooltip
- "Viewer" changed to "Receives copy" with tooltip
- Enhanced select dropdown options with icons and tooltips for different
recipient roles in the `AddTemplatePlaceholderRecipients` component.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---------
Co-authored-by: Timur Ercan <timur.ercan31@gmail.com>
## Description
Fix the issue where duplicate templates can be created
## Changes Made
- Prevent duplicate templates by correctly disabling elements
- Clear the PDF when the form is reset
- General UI changes to new template dialog for consistency
- Add description for new template dialog
- Add close button for new template dialog
## Testing Performed
Manual testing
## Checklist
- [X] I have tested these changes locally and they work as expected.
- [X] I have followed the project's coding style guidelines.
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
- **New Features**
- Introduced new components in the template creation dialog for better
usability: `DialogClose`, `DialogDescription`, and `DialogFooter`.
- Enhanced file upload handling and display.
- Added a cancel button and a create template button to the dialog
footer for improved navigation.
- **Refactor**
- Updated the dialog content and form layout for a more intuitive user
experience.
- Refactored form structure and labels for clarity.
- **Removed Features**
- Removed the `Label` component from the dialog.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
## Description
Currently, when the command menu is opened using the Command+K hotkey,
two modals are getting rendered.
This is because the modals are mounted in two components: header and
desktop-nav. Upon triggering the hotkey, both modals are rendered.
## Related Issue
#1032
## Changes Made
The changes I made are in the desktop nav component. If the desktop nav
receives the command menu state value and the state setter function, it
will trigger only that. If not, it will trigger the state setter that is
defined in the desktop nav. This way, we are preventing the modal from
mounting two times.
## Testing Performed
- Tested behaviour of command menu in the portal
- Tested on browsers chrome, arc, safari, chrome, firefox
## Checklist
- [x] 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.
- [x] I have followed the project's coding style guidelines.
- [ ] I have addressed the code review feedback from the previous
submission, if applicable.
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
- **New Features**
- Enhanced the navigation experience by integrating command menu state
management directly within the `DesktopNav` component, allowing for
smoother interactions and control.
- **Refactor**
- Simplified the handling of the command menu by removing the
`CommandMenu` component and managing its functionality within
`DesktopNav`.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---------
Co-authored-by: David Nguyen <davidngu28@gmail.com>
## Description
This PR introduces the ability to add oneself as a signer by simply
clicking a button, rather than filling the details manually.
### "Add Myself" in the document creation flow
https://github.com/documenso/documenso/assets/25515812/0de762e3-563a-491f-a742-9078bf1d627d
### "Add Myself" in the document template creation flow
https://github.com/documenso/documenso/assets/25515812/775bae01-3f5a-4b24-abbf-a47b14ec594a
## Related Issue
Addresses
[#113](https://github.com/documenso/backlog-internal/issues/113)
## Changes Made
Added a new button that grabs the details of the logged-in user and
fills the fields *(email, name, and role)* automatically when clicked.
## Testing Performed
Tested the changes locally through the UI.
## Checklist
- [x] 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.
- [x] I have followed the project's coding style guidelines.
- [ ] I have addressed the code review feedback from the previous
submission, if applicable.
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
- **New Features**
- Introduced the ability for users to add themselves as signers within
documents seamlessly.
- **Enhancements**
- Improved form handling logic to accommodate new self-signer
functionality.
- Enhanced user interface elements to support the addition of self as a
signer, including a new "Add myself" button and disabling input fields
during the process.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
**Description:**
- Updated mobile header with respect to latest designs
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
- **New Features**
- Added a new `showText` property to the `MenuSwitcher` component to
control text visibility.
- Added a `textSectionClassName` property to the `AvatarWithText`
component for conditional text section styling.
- Updated the `CommandDialog` and `DialogContent` components with new
positioning and styling properties.
- **Style Updates**
- Adjusted text size responsiveness in the `Hero` component for various
screen sizes.
- Modified text truncation and input styling in the `Widget` component.
- Changed the width of the `SheetContent` element in `MobileNavigation`
and adjusted footer layout.
- **Documentation**
- Added instructions for certificate placement in `SIGNING.md`.
- **Refactor**
- Standardized type imports across various components and utilities for
improved type checking.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---------
Signed-off-by: Adithya Krishna <adithya@documenso.com>
Signed-off-by: Adithya Krishna <aadithya794@gmail.com>
Co-authored-by: David Nguyen <davidngu28@gmail.com>
The searchDocuments function is used for the shortcuts commands, afaik.
The function returns the documents that match the user query (if any),
alongside all their recipients.
The reason for that is so it can build the path for the document. E.g.
if you're the document owner, the document path will be
`..../documents/{id}`. But if you're a signer for example, the document
path (link) will be `..../sign/{token}`.
So instead of doing that on the frontend, I moved it to the backend.
At least that's what I understood. If I'm wrong, please correct me.
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
- **New Features**
- Enhanced the `CommandMenu` component to simplify search result
generation and improve document link management based on user roles.
- **Refactor**
- Updated document search logic to include recipient token masking and
refined document mapping.
- **Style**
- Minor formatting improvement in document routing code.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
- **Refactor**
- Enhanced the API specification generation process to include operation
IDs, security schemes, and security definitions more efficiently.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---------
Co-authored-by: Lucas Smith <me@lucasjamessmith.me>


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
- **New Features**
- Introduced a "Claim Account" feature allowing new users to sign up by
providing their name, email, and password.
- Enhanced user experience for both logged-in and non-logged-in users
with improved UI/UX and additional functionality.
- **Enhancements**
- Implemented form validation and error handling for a smoother sign-up
process.
- Integrated analytics to track user actions during account claiming.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---------
Co-authored-by: Lucas Smith <me@lucasjamessmith.me>
Co-authored-by: David Nguyen <davidngu28@gmail.com>
---
name: Pull Request
about: Submit changes to the project for review and inclusion
---
## Description
Should fix the rerendering of the status widget
## 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. -->
## Description
When document audit logs were first introduced, we by default set the
`fieldSecurity` to `NONE`
Now that document auth has been added, this is causing issues since we
do not use `NONE` to define field that has no migrations required, but
rather have the `fieldSecurity` field itself be undefined.
To keeps things consistent, this migration replaces `NONE` with
undefined.
There are a few ways to approach this:
- Run a prisma migration on the JSON
- Modify the data before we pass the data to the schema in
`parseDocumentAuditLogData`
- Use `NONE` instead of undefined
If anyone thinks there's a better way to do this, please drop a comment
🙇
## Description
General UI updates
## Changes Made
- Add consistent spacing between document edit/view/log pages
- Add document status to document audit log page
- Update document loading page to reserve space for the document status
below the title
- Update the document audit log page to show full dates in the correct
locale
## Description
Adds the ability to prefill native PDF form fields via the API using
either normal documents or templates.
Since we won't always know when a document is uploaded and has forms we
opt to do this on creation for templates and on sending the document to
recipients in all cases. This means that for a created document it can
look a little funky since the form fields are missing the data until the
document is sent.
This should be improved in a later change but since we've scoped this to
an API only workflow for now we are less concerned with the visual
issues.
## Related Issue
N/A
## Changes Made
- Added the `formValues` field the document model
- Added a new method for finding and filling form fields based on a `key
| value` pair
- Updated the API input shapes to take the new field.
## Testing Performed
- Have created and tested a document using the API both for creation and
usage with a template.
- Have verified that the fields display as expected either during
creation or sending depending on the document type.
## Description
Fetch the updated version of the document after sealing it and return
it. Previously, the `document.documentData.data` wasn't up to date. Now
it is.
## Related Issue
Fixes#1088.
## Testing Performed
* Added console.logs in the code to make sure it returns the proper data
* Set up a webhook and tested that the webhook receives the updated data
## Checklist
<!--- Please check the boxes that apply to this pull request. -->
<!--- You can add or remove items as needed. -->
- [x] 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.
- [x] I have followed the project's coding style guidelines.
- [ ] I have addressed the code review feedback from the previous
submission, if applicable.
## Changes Made
- Refactor/optimise tests
- Reduce flakiness
- Add parallel tests (if there's enough CPU capacity)
- Removed explicit worker count when running parallel tests. Defaults to
50% of CPU capacity.
Might want to consider sharding the test across runners in the future as
our tests grows.
## Description
Fixed issue where accounts that were initially created via
email/password, then linked to an SSO account, can bypass the 2FA during
login if they use their email password.
## Testing Performed
Tested locally, and 2FA is now required for linked SSO accounts
## Description
Add the following document action auth options:
- 2FA
- Passkey
If the user does not have the required auth setup, we onboard them
directly.
## Changes made
Note: Added secondaryId to the VerificationToken schema
## Testing Performed
Tested locally, pending preview tests
## Checklist
- [X] I have tested these changes locally and they work as expected.
- [X] I have added/updated tests that prove the effectiveness of these
changes.
- [X] I have followed the project's coding style guidelines.
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
- **New Features**
- Introduced components for 2FA, account, and passkey authentication
during document signing.
- Added "Require passkey" option to document settings and signer
authentication settings.
- Enhanced form submission and loading states for improved user
experience.
- **Refactor**
- Optimized authentication components to efficiently support multiple
authentication methods.
- **Chores**
- Updated and renamed functions and components for clarity and
consistency across the authentication system.
- Refined sorting options and database schema to support new
authentication features.
- **Bug Fixes**
- Adjusted SignInForm to verify browser support for WebAuthn before
proceeding.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
Added a dialog button at the bottom of the admin/documents/[id] page
with confirmation popup.
Confirmation popup have validation for reason to input.
On confirmation document is deleted, and an email is triggred to the
owner of document with the reason stated.
Let me know if there is any more requirement or correction is needed in
this pr. :) #1020
## Description
Currently opening modals, clicking select boxes or using anything from
radix that overlays the screen in some way will shift the screen.
This can be easily noticeable when changing the document "Period"
selector on the /documents page.
## Changes Made
Undo the gutter change for now. Can find a proper solution another time.
https://github.com/documenso/documenso/assets/20962767/5bcae576-2944-4ae5-a2c3-0589e7f61bdb
This change flattens and normalizes annotation and widget layers within
the PDF document removing items that can be accidentally modified after
signing which would void the signature attached to the document.
Initially this change was just to assign to an ArcoForm object in the
document catalog if it existed but quickly turned into the above.
When annotations aren't flattened Adobe PDF will say that the signature
needs to be validated and upon doing so will become invalid due to the
annotation layers being touched.
To resolve this I set out to flatten and remove the annotations by
pulling out their normal appearances if they are present, converting
them into xobjects and then drawing those using the drawObject operator.
This resolves a critical issue the users experienced during the signing
flow when they had marked up a document using annotations in pdf
editors.
## Description
Currently if you try to load the document edit page when fields need to
be rendered, you will not be able to see the fields until you proceed to
the next step.
This is because the fields require the document PDF to be loaded prior
to rendering them.
This PR resolves that issue by only rendering the fields after the PDF
is loaded.
## Changes Made
- Add a state to track whether the PDF is loaded
- Render the fields only after the PDF is loaded
## Testing Performed
Tested document flow manually and the fields are rendered correctly on
load.
## Checklist
- [X] I have tested these changes locally and they work as expected.
- [X] I have updated the documentation to reflect these changes, if
applicable.
## Description
**Fixes issues with mismatching state between document steps.**
For example, editing a recipient and proceeding to the next step may not
display the updated recipient. And going back will display the old
recipient instead of the updated values.
**This PR also improves mutation and query speeds by adding logic to
bypass query invalidation.**
```ts
export const trpc = createTRPCReact<AppRouter>({
unstable_overrides: {
useMutation: {
async onSuccess(opts) {
await opts.originalFn();
// This forces mutations to wait for all the queries on the page to reload, and in
// this case one of the queries is `searchDocument` for the command overlay, which
// on average takes ~500ms. This means that every single mutation must wait for this.
await opts.queryClient.invalidateQueries();
},
},
},
});
```
I've added workarounds to allow us to bypass things such as batching and
invalidating queries. But I think we should instead remove this and
update all the mutations where a query is required for a more optimised
system.
## Example benchmarks
Using stg-app vs this preview there's an average 50% speed increase
across mutations.
**Set signer step:**
Average old speed: ~1100ms
Average new speed: ~550ms
**Set recipient step:**
Average old speed: ~1200ms
Average new speed: ~600ms
**Set fields step:**
Average old speed: ~1200ms
Average new speed: ~600ms
## Related Issue
This will resolve#470
## Changes Made
- Added ability to skip batch queries
- Added a state to store the required document data.
- Refetch the data between steps if/when required
- Optimise mutations and queries
## Checklist
- [X] I have tested these changes locally and they work as expected.
- [X] I have followed the project's coding style guidelines.
---------
Co-authored-by: Lucas Smith <me@lucasjamessmith.me>
## Description
Add support to login with passkeys.
Passkeys can be added via the user security settings page.
Note: Currently left out adding the type of authentication method for
the 'user security audit logs' because we're using the `signIn`
next-auth event which doesn't appear to provide the context. Will look
into it at another time.
## Changes Made
- Add passkeys to login
- Add passkeys feature flag
- Add page to manage passkeys
- Add audit logs relating to passkeys
- Updated prisma schema to support passkeys & anonymous verification
tokens
## Testing Performed
To be done.
MacOS:
- Safari ✅
- Chrome ✅
- Firefox ✅
Windows:
- Chrome [Untested]
- Firefox [Untested]
Linux:
- Chrome [Untested]
- Firefox [Untested]
iOS:
- Safari ✅
## Checklist
<!--- Please check the boxes that apply to this pull request. -->
<!--- You can add or remove items as needed. -->
- [X] I have tested these changes locally and they work as expected.
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
- **New Features**
- Introduced Passkey authentication, including creation, sign-in, and
management of passkeys.
- Added a Passkeys section in Security Settings for managing user
passkeys.
- Implemented UI updates for Passkey authentication, including a new
dialog for creating passkeys and a data table for managing them.
- Enhanced security settings with server-side feature flags to
conditionally display new security features.
- **Bug Fixes**
- Improved UI consistency in the Settings Security Activity Page.
- Updated button styling in the 2FA Recovery Codes component for better
visibility.
- **Refactor**
- Streamlined authentication options to include WebAuthn credentials
provider.
- **Chores**
- Updated database schema to support passkeys and related functionality.
- Added new audit log types for passkey-related activities.
- Enhanced server-only authentication utilities for passkey registration
and management.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
## Details
Currently there's no way to have a proper PR template selector. Since we
rarely use the E2E template, I've opted to move the generic PR template
to be the default template.
## Description
Update the add signer form to disable the signers when required.
I assume the actual issue is that `{...field}` was spreading a disabled
prop which was overriding our one.
## Changes Made
- Use fieldset to disable inputs
- Manually disable select since fieldset doesn't work for that select
for some reason
Right now, the eslint command runs separately for each staged file. This
PR aims to change that by running just one eslint command for all the
files that have been changed.
## Description
Updates the `on-create.sh` script to use our `dx` command resolving
issues where it couldn't find the docker compose file due to changes
that have happened since publishing the Documenso docker image.
## Related Issue
Resolves#1026
## Test Details
N/A
## Checklist
- [x] I have written the new test and ensured it works as intended.
- [x] I have added necessary documentation to explain the purpose of the
test.
- [x] I have followed the project's testing guidelines and coding style.
- [x] I have addressed any review feedback from previous submissions, if
applicable.
## Additional Notes
N/A
## Description
Updates the docker documentation and compose files to include key file
related configuration for self hosters. This was missed as the key file
environment variables weren't documented in the `.env.example` file
which was used for creating the docker documentation.
## Related Issue
#1012
## Changes Made
- Updated the docker configuration to include key file environment
variables
- Updated the .env.example to include key file env vars
- Updated the compose images to use volumes for key files
## Testing Performed
- I have used the containers with the updated values and confirmed that
they work as expected
## Checklist
- [x] I have tested these changes locally and they work as expected.
- [x] I have added/updated tests that prove the effectiveness of these
changes.
- [x] I have updated the documentation to reflect these changes, if
applicable.
- [x] I have followed the project's coding style guidelines.
- [x] I have addressed the code review feedback from the previous
submission, if applicable.
## Additional Notes
N/A
## Description
This pull request addresses the issue where users on touchscreen devices
couldn't properly see the Recipients list. I have implemented a two-easy
solution to address this problem, offering a seamless user experience
across device types:
1. Popover for Touchscreen: For touchscreen devices, I have added a
popover that displays the Recipients list when users tap on the avatars.
2. Tooltip for Larger Screens: On larger screens (desktops and laptops),
I have added a tooltip that appears when users hover over the avatars.
## Changes
1. Added `Popover` for smaller devices and keep the `Tooltip` for larger
devices.
2. Renamed the component `stack-avatars-wtih-tooltip` to
`stack-avatars-wtih-ui` because now it contains both Tooltip and
Popover.
3. Used the `useWindowSize` hook to conditionally render the `Tooltip`
and `Popover`
4. To avoid repeating the same code, I've created a new component named
`stack-avatars-components.tsx` to show the recipient's details. This
component uses both Popover and Tooltip.
## PR Preview
https://github.com/documenso/documenso/assets/87828904/2dc9b056-b4bd-43dd-b427-a0e803dee55a
## Issue
Closes#756
When prisma:migrate-dev needs to reset the database it will run the seed script to repopulate data. Now that we've added the seed script to our root setup command we will want to avoid this behaviour since we will end up double seeding the database which currently can cause issues.
## Description
Fixes the issue with Vercel preview deployments failing.
It appears that the old `PGHOST` environment variable injected by neon
was:
`ep-snowy-snowflake-a2vc5pa2.eu-central-1.aws.neon.tech`
It is now:
`ep-snowy-snowflake-a2vc5pa2.eu-central-1-pooler.aws.neon.tech`
Notice the `-pooler` being attached automatically to the `PGHOST`.
## References
> The following changes were made to the [Neon Vercel
Integration](https://vercel.com/integrations/neon):
>
>To ensure that users accessing a Neon database from a serverless
environment have enough connections, the DATABASE_URL and PGHOST
environment variables added to a Vercel project by the Neon integration
are now set to a pooled Neon connection string by default. Pooled
connections support up to 10,000 simultaneous connections. Previously,
these variables were set to an unpooled connection string supporting
fewer concurrent connections.
https://neon.tech/docs/changeloghttps://neon.tech/docs/guides/vercel#manage-vercel-environment-variables
Remove `bcrypt` in favor of `@node-rs/bcrypt` which includes precompiled
binaries for many platforms reducing the number of tasks to run post
`npm install`.
Resolves#986
Tidy the docker setup and include a Github Action
for publishing docker containers to DockerHub and
Github Container Registry.
Also add a small README file with docker hosting instructions.
Tidy the docker setup and include a Github Action
for publishing docker containers to DockerHub and
Github Container Registry.
Also add a small README file with docker hosting instructions.
Return the recipient as an array to match the other formats for Zapier.
Otherwise, Zaps with the "DOCUMENT_OPENED" hooks won't work.
All the other webhooks return the "Recipient" field as an array.
---
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. -->
This PR adds the public-facing API.

The public API will allow users to interact with Documenso
programmatically. At the moment, there are 5 available endpoints:
1. `GET /documents`
- get all documents of the user making the API call
- it accepts 2 URL query parameters - `page` and `perPage`, but they are
not mandatory
2. `GET /documents/:id`
- get a specific document of the user making the API call
- it requires 1 URL parameter, which represents the ID of the document
that needs to be retrieved
3. `DELETE /documents/:id`
- delete a specific document of the user making the API call
- it requires 1 URL parameter, which represents the ID of the document
that needs to be deleted
4. `POST /documents`
- making a POST request to this endpoint will return an S3 pre-signed
URL where you can upload the document
- it requires you to pass the file name and the file content type
5. `PATCH /documents/:id/send-for-signing`
- send a document for signing
- it allows you to pass the following:
- signer email *(required)*
- signer name *(optional)*
- field type (signature, email, name, etc.) *(required)*
- page number where to insert the field *(required)*
- page X *(required)*
- page Y *(required)*
- page width *(required)*
- page height *(required)*
- email subject *(optional)*
- email body *(optional)*
The users are authenticated through API tokens. The users can create one
or more tokens in their account settings, and each token will be
available for 1 year _(duration open to suggestions/changes)_.
Each time the user makes a request, the app checks if the token exists
and if it's valid. The app will return `401` *(unauthorized)* and the
appropriate error message if either is false. If both are true AND the
user uses the correct HTTP verb and passes the required URL parameters
and body, the API call will be successful.
Code overview:
- `@documenso/packages/lib/trpc/api-contract` - this folder contains the
`contract` and `schema` files. The `contract.ts` file describes the
structure of the API, the format of the requests and responses, and how
to authenticate your API calls, among others. The `schema.ts` file
contains the Zod schemas used in the API contract.
- `@documenso/packages/trpc/server/api-token-router` - this folder
contains the `router.rs` and `schema.ts` files. Here are the tRPC
procedures used on the frontend. That is, the user's settings page,
where the user can list/create/delete API tokens.
- `@documenso/packages/trpc/tsconfig.json` - I added `"strict": true`
because that's what's suggested in the `ts-rest` documentation.
*([source](https://ts-rest.com/docs/quickstart#create-a-contract))*
- `[...ts-rest].tsx` - This file contains the implementation of the API.
You can see the logic behind each route.
- the rest of the code represents the code for the API tokens page in
the user's settings.
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
- **New Features**
- Added two-factor authentication form handling in profile settings.
- Introduced account deletion functionality, including Stripe customer
data removal.
- Updated UI components and styles for improved user interaction, such
as enhanced visual feedback for destructive actions.
- **Refactor**
- Improved code quality by updating import statements for type-only
imports.
- **Chores**
- Restructured the `forwardPorts` array in dev container configuration
for clarity.
- Removed a trailing comma in the `vscode` extensions list to adhere to
JSON format rules.
- **Documentation**
- Added comments to clarify the handling of undefined values in
two-factor authentication verification.
- **Database**
- Implemented a SQL migration script for creating a default deleted user
in the system.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
## Description
This feature allows us to have a dedicated page to view details for a
document.
The current `/documents/[id]` page has been moved to
`/documents/[id]/edit`.
The new `/documents/[id]` page will now display general information on
the document itself.
This will allow us to provide more details relating to a document in the
future, such as version history.
## Examples
These may be outdated as deployment failed
Login via example@documenso.com
Draft document no recipients:
https://stg-7hpkvyc5i-documenso.vercel.app/documents/446
Draft document with recipients:
https://stg-7hpkvyc5i-documenso.vercel.app/documents/440
Pending document:
https://stg-7hpkvyc5i-documenso.vercel.app/documents/447
Completed document:
https://stg-7hpkvyc5i-documenso.vercel.app/documents/448
Pending teams document:
https://stg-7hpkvyc5i-documenso.vercel.app/t/hello/documents/449/
## 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.
- [X] I have followed the project's coding style guidelines.
## Additional Notes
When a user "sends" a document (DRAFT -> PENDING), should we redirect
them to the document/id page, or keep it how it currently is and have it
redirect to `/documents` page?
Disables the generation of the blog and content pages using
generateStaticPaths to deal with a regression with routing
introduced with next-runtime-env.
## Description
Add support for enterprise billing plans.
Enterprise billing plans by default get access to everything early
adopters do:
- Unlimited teams
- Unlimited documents
They will also get additional features in the future.
## Notes
Pending webhook updates to support enterprise onboarding.
Rolled back env changes `NEXT_PUBLIC_PROJECT` since it doesn't seem to
work.
improved document-dropzone ui for small vertical screens (screens less
than 800px vertically)
Although it can still become congested on really small vertical screens,
but possibility is really low.
fixes: #840
Adding a security.txt file enables security researchers to quickly and
easily see where they can submit security issues and know that they are
being taken serious. From the proposal website:
> "When security risks in web services are discovered by independent
security researchers who understand the severity of the risk, they often
lack the channels to disclose them properly. As a result, security
issues may be left unreported. security.txt defines a standard to help
organizations define the process for security researchers to disclose
security vulnerabilities securely.”
See also https://securitytxt.org
## Description
Currently we're not restricting team transfer and email verification
tokens from flowing into the frontend.
This changes restricts it to only return the required information
instead of the whole data object.
## Description
Currently the document redirect URL feature is preventing documents from
being created unless a redirect URL is provided.
During the document edit flow, the redirect URL is hidden in an advanced
tab with the value of an empty string, which will always fail the
current Zod validation since `optional` requires undefined to pass.
There are multiple ways to fix this, but I think this is the easiest
method where we can assume an empty string is valid.
## Description
Fixed issue where setting a recipient role as CC will prevent any
further changes as it is considered as "sent" and "signed".
## Other changes
- Prevent editing document after completed
- Removed CC and Viewers from the field recipient list since they will
never be filled
- Minor UI issues
## Checklist
- [X] I have tested these changes locally and they work as expected.
- [X] I have added/updated tests that prove the effectiveness of these
changes.
- [X] I have followed the project's coding style guidelines.
## Description
Add the ability to feature flag the teams feature via UI.
Also added minor UI changes
## Checklist
- [X] I have tested these changes locally and they work as expected.
- [X] I have added/updated tests that prove the effectiveness of these
changes.
- [X] I have followed the project's coding style guidelines.
## Description
Fixed issue where you are prevented from removing fields for a recipient
that has multiple fields.
Example:
Recipient has 3 fields, you remove 1 and proceed to next step. In the
next step the field reappears as it was not deleted.
## Checklist
- [X] I have tested these changes locally and they work as expected.
- [X] I have added/updated tests that prove the effectiveness of these
changes.
- [X] I have followed the project's coding style guidelines.
## Description
Add support for teams which will allow users to collaborate on
documents.
Teams features allows users to:
- Create, manage and transfer teams
- Manage team members
- Manage team emails
- Manage a shared team inbox and documents
These changes do NOT include the following, which are planned for a
future release:
- Team templates
- Team API
- Search menu integration
## Testing Performed
- Added E2E tests for general team management
- Added E2E tests to validate document counts
## Checklist
- [X] I have tested these changes locally and they work as expected.
- [X] I have added/updated tests that prove the effectiveness of these
changes.
- [ ] I have updated the documentation to reflect these changes, if
applicable.
- [X] I have followed the project's coding style guidelines.
## Description
**Fixed document limitation bypassing issues through templates.**
Previously, users could bypass document restrictions by utilizing
templates even after reaching their limitations. This fix ensures that
templates will no longer function as a workaround when users reach their
document limits.
## Changes
1. imported `useLimits` hook on `data-table-templates.tsx`
2. Disabled the 'Use Template' button when the user reaches their limit.
3. Added an Alert Component on top of the templates page to notify users
that they can't use templates anymore because they have reached their
limit.
4. Used `getServerLimits` hook on `template-router` to a condition on
the server.
## Example

## Issue
Closes#883
## Description
Adds the ability to see the events relating to the account.
Event data includes:
- Device
- IP Address
- Time
- Action
Actions are:
- Profile update
- Account linked to SSO (Example user signs in with Google after
creating a email/password account)
- Enable 2FA
- Disable 2FA
- Reset password
- Update password
- Sign out
- Sign in
- Sign in fail
- Sign in 2FA fail
## Changes
- Added audit logs
- Updated 2FA dialogs to have consistent footers
- Update `/settings/security/page` layout
## Testing Performed
Tested events:

More tested events:

## Checklist
- [X] I have tested these changes locally and they work as expected.
- [X] I have followed the project's coding style guidelines.
## Additional Notes
- Not sure if we really want to record the sign out event or not
- Might want to design breadcrumbs for nested setting pages
## Description
Currently the count for the documents table tabs do not display the
correct values when the period filter is applied.
## Changes Made
- Updated `getStats` to support filtering on period
## Testing Performed
- Tested to see if the documents tab count were being filtered based on
the period
## Checklist
- [X] I have tested these changes locally and they work as expected.
- [X] I have followed the project's coding style guidelines.
## Description
This pull request solves the problem where the avatar component within
the document list has the same z-index value as the header component,
causing the avatar to be above the header. When two elements have the
same z-index value, the last one takes priority!
## Related Issue
Fixes#870
## Changes Made
1. Increases the value of the header's `z-index` by `10` (the current
value is `50`
## Description
Currently we are required to ensure PII data is not passed around in
search parameters and in the open for GDPR reasons.
Allowing us to encrypt and decrypt values with expiry dates will allow
us to ensure this doesn't happen.
## Changes Made
- Added TPRC router for encryption method
## Testing Performed
- Tested encrypting and decrypting data with and without `expiredAt`
- Tested via directly accessing API and also via trpc in react
components
- Tested parsing en email search param in a page and decrypting it
successfully
## Checklist
- [X] I have tested these changes locally and they work as expected.
- [X] I have followed the project's coding style guidelines.
When you're in the `/documents` page in the dashboard, if you hover over
a draft and a completed document, you'll see different URLs.
At the moment, the shortcut tries to go to the following URL for a
completed document `/documents/{doc-id}`.
However, that's the wrong URL, since the URL for a completed doc is
`/sign/{token}` when the user is the recipient, not the one that sent
the document for signing.
If it's the document owner & the document is completed, the URL is fine
as `/documents/{doc-id}`.
---------
Co-authored-by: Lucas Smith <me@lucasjamessmith.me>
Fixed the deleting signature block issue on touchscreens, for some
reason the `onClick` event isn't working on the touchscreens that's why
I've added `onTouchEnd` event to delete the signature block when the
user clicks on it.
Extracts the API implementation to a package so we can
potentially reuse it across different applications in the
event that we move off using a Next.js API route.
Additionally tidies up the tokens page and form to be more simplified.
## Description
Currently there are various z-index values that are causing:
- Toasts to be placed behind dialog blur background
- Menu being cropped off by header
## Changes Made
- Revert `z-[1000]` back to `z-50` for the header (not exactly sure why
it was bumped)
- Refactor z-indexes over 9000 to start from 1000
- Ensure z-index of toast is higher than dialog
This PR makes a small but useful tweak to the `DeleteDocumentDialog`.
Now, the input field gets cleared whenever the dialog is opened. Here’s
what’s changed:
1. **Clear Field After Deleting**: After you delete something and open
the dialog again, it won’t show the old, deleted text anymore. It’s
clean and ready for the next delete.
2. **Type Again to Confirm**: If you type something but close the dialog
without deleting, you’ll have to type it again next time. This way, it
makes sure the user really mean to delete something and didn't do it by
mistake.
Demo Link:
See the old vs. new in action here:
https://www.loom.com/share/80eca0d3b1994f7cbcab6f222db2dbfe?sid=ebc6135c-345e-4640-b395-daff190a96e7
It’s a small change, but it makes the delete process safer and smoother.
## Description
Previously we assumed that there can only be 1 subscription per user.
However, that will soon no longer the case with the introduction of the
Teams subscription.
This PR will apply the required migrations to support multiple
subscriptions.
## Changes Made
- Updated the Prisma schema to allow for multiple `Subscriptions` per
`User`
- Added a Stripe `customerId` field to the `User` model
- Updated relevant billing sections to support multiple subscriptions
## Testing Performed
- Tested running the Prisma migration on a demo database created on the
main branch
Will require a lot of additional testing.
## Checklist
- [ ] I have tested these changes locally and they work as expected.
- [ ] I have added/updated tests that prove the effectiveness of these
changes.
- [X] I have followed the project's coding style guidelines.
## Additional Notes
Added the following custom SQL statement to the migration:
> DELETE FROM "Subscription" WHERE "planId" IS NULL OR "priceId" IS
NULL;
Prior to deployment this will require changes to Stripe products:
- Adding `type` meta attribute
---------
Co-authored-by: Lucas Smith <me@lucasjamessmith.me>
Currently customers with inactive/expired plans will be shown the
BillingPlans component but upon hitting the subscribe button they will
be redirected to their portal where they are unable to complete a
checkout.
To resolve this we check for expiration of their subscription and use a
normal stripe checkout instead.
* feat: add link to homepage on the complete sign page for logged in users
* feat: added ChevronLeft icon to the link
* feat: remove icon from the link
Change "Open" links to "Open Startup" to reduce confusion about how to open the web app.
Additionally add the OSS Friends link to the footer since it was dropped during some changes.
Implementation of a universal upload allowing for multiple storage backends
starting with `database` and `s3`.
Allows clients to put and retrieve files from either client or server using
a blend of client and server actions.
* feat: update document table layout
- Removed dashboard page
- Removed redundant ID column
- Moved date to first column
- Added estimated locales for SSR dates
- Fixed z-index when dragging pre-existing fields
- Refactored document flow
- Added button spinner
- Added animation for document flow slider
- Updated drag and drop fields
- Updated document flow so it adjusts to the height of the PDF
- Updated claim plan dialog
This change actually makes the authoring flow work for
the most part by tying in emailing and more.
We have also done a number of quality of life updates to
simplify the codebase overall making it easier to continue
work on the refresh.
Package managers such as NPM behave strangely when adding
packages such as swc and turborepo which contain platform
variants.
During a first time install they will include only the current
devices platform while a clean node_modules and package-lock
will result in all platforms being included.
This change adds those missed platforms by performing the above step and porting it back to our existing package-lock.
Improve the stripe webhook endpoint by checking for
subscriptions prior to performing an update to handle
cases where accounts have no created subscription.
This can happen in sitations such as when a checkout_session has been created but the payment fails.
Improve the general styling of the app by removing floats and replacing it `flex`. Additionally, improve the constrast of certain parts of the app and add some transitions to hover changes.
Updates the signing endpoint to only apply changes to the Date field for the current signer. This is made possible through the addition of the `signedAt` column within the database.
Resolves the issue with one signer filling the date for all recipients and also ensures that the date of signing on a document won't always be todays date after each recipient has signed.
Debounces the display of the signing canvas to avoid situtations where the canvas renders to 2px due to rendering while a transition is being performed.
Currently the signing email displays poorly on small devices with the line wrapping
causing the button to look broken.
Resolve this by using whitespace no-wrap.
Add support for production container builds using the provided `Dockerfile` and `build.sh` script. This can later be used with actions to automatically publish to the provided docker registry.
Additionally, support an accelerated developer quickstart using `docker-compose`. Developers can now run the `dx` npm command to quickly spin up a database and mail server.
Previous inserted text would appear a little off center from where the user had selected which could cause some frustration.
We improve upon this by updating the code responsible for centering the text to behave in a more accurate manner. From what I can tell it looks to be quite solid but could do with more rigorous testing with shorter and longer inputs.
You can see the improved accuracy in action here:
https://www.loom.com/share/1095fee7605c4790b8b30f573a04f0f0
# You use the provided remote test database, courtesy of the documenso team: postgres://documenso_test_user:GnmLG14u12sd9zHsd4vVWwP40WneFJMo@dpg-cf2hljh4reb5o45oqpq0-a.oregon-postgres.render.com/documenso_test_e2i3
# It is however recommend, that you set up a local Postgres SQL instance
# ⚠ WARNING: The test database can be resetted or taken offline at any point
# ⚠ WARNING: Please be aware that nothing written to the test databae is private.
DATABASE_URL=''
# [[AUTH]]
NEXTAUTH_URL="http://localhost:3000"
NEXTAUTH_SECRET="secret"
# URL
NEXT_PUBLIC_WEBAPP_URL='http://localhost:3000'
# [[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"
# AUTH
# For more see here: https://next-auth.js.org
NEXTAUTH_SECRET='lorem ipsum sit dolor random string for encryption this could literally be anything'
NEXTAUTH_URL='http://localhost:3000'
# [[AUTH OPTIONAL]]
NEXT_PRIVATE_GOOGLE_CLIENT_ID=""
NEXT_PRIVATE_GOOGLE_CLIENT_SECRET=""
# MAIL
# Get a Sendgrid Api key here: https://signup.sendgrid.com
# You can also configure you own SMTP server using Nodemailer in sendMailts. (currently not possible via config)
SENDGRID_API_KEY=''
# Sender for signing requests and completion mails.
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
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
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.`;
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.
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.
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.
## 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 and issue from [here](https://github.com/documenso/documenso/issues) or create a new one
- Consider the results from the discussion in the issue
- 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.
## Developing
The development branch is <code>development</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).
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).
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 somthing readable):
```sh
git checkout -b doc-999-my-feature-or-fix
```
- Create a new branch (include the issue id and something readable):
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.
<ahref="https://join.slack.com/t/documenso/shared_invite/zt-1qwxxsvli-nDyojjt~wakhgBGl9JRl2w"><imgsrc="https://img.shields.io/badge/Slack-documenso.slack.com-%234A154B"alt="Join Documenso on Slack"></a>
<ahref="https://documen.so/discord"><imgsrc="https://img.shields.io/badge/Discord-documen.so/discord-%235865F2"alt="Join Documenso on Discord"></a>
> This project is currently under community review and will publish it's first production release soon™.
## About this project
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.
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.
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 current [Discussions](https://github.com/documenso/documenso/discussions)
-Join the [Slack Channel](https://join.slack.com/t/documenso/shared_invite/zt-1qwxxsvli-nDyojjt~wakhgBGl9JRl2w) 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 areneeded for the first production release
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.
-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.
## Contributing
- To contribute please see our [contribution guide](https://github.com/documenso/documenso/blob/main/CONTRIBUTING.md).
## Tools
- To contribute, please see our [contribution guide](https://github.com/documenso/documenso/blob/main/CONTRIBUTING.md).
- This repos uses 📝 https://gitmoji.dev/ for more expressive commit messages.
- Use 🧹 for quality of code (eg remove comments, debug output, remove unused code)
## 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:
<ahref="https://cal.com/timurercan/enterprise-customers?utm_source=banner&utm_campaign=oss"><imgalt="Book us with Cal.com"src="https://cal.com/book-with-cal-dark.svg"/></a>
- [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
> **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.
After forking the repository, clone it to your local device by using the following command:
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.
3. Run `npm run dx` in the root directory
- 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.
Follow these steps to setup documenso on you local machnine:
### Manual Setup
- [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 .env.example to .env
- 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 (recommened)
- Set SENDGRID_API_KEY value in .env file
- You need 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
- Run <code>npm run dev</code> root directory to start
- Register a new user at http://localhost:3000/signup
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:
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
---
- Optional: Create your own signing certificate
- A demo certificate is provided in /app/web/ressources/certificate.p12
- To generate you own using these steps and a linux Terminal or Windows Linux Subsystem see **Create your own signging certificate**.
- 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)**.
## Updating
- If you pull the newest version from main, using <code>git pull</code>, it may be neccessary to regenerate your database client
- You can do this by running the generate command in /packages/prisma:
```sh
npx prisma generate
```
- This is not neccessary on first clone
### Run in Gitpod
# Creating your own signging certificate
- Click below to launch a ready-to-use Gitpod workspace in your browser.
For the digital signature of you documents you need a signign certificate in .p12 formate (public and private key). You can buy one (not recommended for dev) or use the steps to create a self-signed one:
[](https://gitpod.io/#https://github.com/documenso/documenso)
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>
### Run in DevContainer
2. Generate a self-signed certificate using the private key. You can run the following command to generate a self-signed certificate:\
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: \
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/ressource/certificate.p12</code>
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)
# Deploying - Coming Soon™
### Video walkthrough
- Docker support
- One-Click-Deploy on Render.com Deploy
If you're a visual learner and prefer to watch a video walkthrough of setting up Documenso locally, check out this video:
[](https://youtu.be/Y0ppIQrEnZs)
## Docker
We provide a Docker container for Documenso, which is published on both DockerHub and GitHub Container Registry.
You can pull the Docker image from either of these registries and run it with your preferred container hosting provider.
Please note that you will need to provide environment variables for connecting to the database, mailserver, and so forth.
For detailed instructions on how to configure and run the Docker container, please refer to the [Docker README](./docker/README.md) in the `docker` directory.
## Self Hosting
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.
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
[](https://railway.app/template/bG6D4p)
### Render
[](https://render.com/deploy?repo=https://github.com/documenso/documenso)
### Koyeb
[](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
For local docker run
```bash
docker run -it documenso:latest npm run start -- -H ::
```
For k8s or docker-compose
```yaml
containers:
- name:documenso
image:documenso:latest
imagePullPolicy:IfNotPresent
command:
- npm
args:
- run
- 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.
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:
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:
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
-`-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
[](https://railway.app/template/DjrRRX)
## Render
[](https://render.com/deploy?repo=https://github.com/documenso/documenso)
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.
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).
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
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
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.
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:
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:
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:
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.
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)
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:
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:
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.

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.

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.

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 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
}
```

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.
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.
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.
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.

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.

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.

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.

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:
| `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.
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.
## Let’s build the world’s 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. [Editor’s Note: Because it was solved technically a long time ago] It’s a legal acceptance problem — and everyone KNOWS DocuSign and friends and understands how they’re 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.
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: I’m not a lawyer and this isn’t 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 world’s 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 it’s now available through the early adopter’s plan. One of the most fundamental choices we had to make on this first release, was the choice of certificate. While it’s 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 don’t 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 isn’t 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 it’s hardly more work than option 1 (using Documenso at least), this would be my minimum effort recommendation. Having a self-created (“self-signed”) certificate doesn’t add much in terms of regulation but it guarantees the document’s integrity, meaning no changes have been made after signing². What this doesn’t give you, is the famous green checkmark in Adobe Acrobat. Why? Because you aren’t 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 organization’s 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. Adobe’s) 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 you’re trying to accomplish.
<center>. . .</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 Documenso’s 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 weren’t any deeper reasons we choose WiseKey, other than they offered what we needed and there wasn’t any reason to look much further. While I didn’t map the entire certificate market offering (yet), I’m 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 Let’s 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 we’ll 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).
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.
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:
- **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:
- **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.
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 world’s 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? Let’s 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!)
You can now navigate into the directory and install the project’s 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.

### 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.

### 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.
### 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.

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.

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.

### 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`.

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. You’re going live — enjoy!
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)!
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).
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.
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 customer’s 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:
> 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.
> 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
Some files were not shown because too many files have changed in this diff
Show More
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.