diff --git a/.env.example b/.env.example index 86eec374f9..d69d5a64e9 100644 --- a/.env.example +++ b/.env.example @@ -122,7 +122,7 @@ NEXT_PRIVATE_SMTP_SECURE= # OPTIONAL: if this is true and NEXT_PRIVATE_SMTP_SECURE is false then TLS is not used even if the server supports STARTTLS extension NEXT_PRIVATE_SMTP_UNSAFE_IGNORE_TLS= # REQUIRED: Defines the sender name to use for the from address. -NEXT_PRIVATE_SMTP_FROM_NAME="Keep Contracts" +NEXT_PRIVATE_SMTP_FROM_NAME="KeepContracts" # REQUIRED: Defines the email address to use as the from address. NEXT_PRIVATE_SMTP_FROM_ADDRESS="noreply@keepcontracts.com" # OPTIONAL: Defines the service for nodemailer diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000000..de613193cc --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,3 @@ +{ + "recommendations": ["biomejs.biome", "Prisma.prisma", "spencerwmiles.vscode-task-buttons"] +} diff --git a/.vscode/settings.json b/.vscode/settings.json index 15c6dc8778..155070bf44 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -30,5 +30,22 @@ }, "[json]": { "editor.defaultFormatter": "vscode.json-language-features" - } + }, + "VsCodeTaskButtons.tasks": [ + { "label": "$(play) Dev", "task": "Dev", "tooltip": "Start the dev server" }, + { + "label": "$(check) PR Checks", + "task": "PR Checks", + "tooltip": "Run lint, typecheck, unit tests, and build (mirrors CI)" + }, + { "label": "$(wrench) Lint Fix", "task": "Lint: Fix", "tooltip": "Auto-fix lint issues" }, + { "label": "$(beaker) Test", "task": "Test", "tooltip": "Run unit tests (vitest)" }, + { + "label": "$(beaker) Test: E2E", + "task": "Test: E2E", + "tooltip": "Run the full Playwright E2E suite (matches CI)" + }, + { "label": "$(database) DB Up", "task": "DB: Up", "tooltip": "Start local Docker database" }, + { "label": "$(table) Prisma Studio", "task": "Prisma Studio", "tooltip": "Open Prisma Studio" } + ] } diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 0000000000..a0c2676e94 --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,72 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "label": "Dev", + "type": "npm", + "script": "dev", + "isBackground": true, + "presentation": { + "reveal": "always", + "panel": "dedicated" + }, + "problemMatcher": [] + }, + { + "label": "Lint", + "type": "npm", + "script": "lint", + "problemMatcher": [] + }, + { + "label": "Lint: Fix", + "type": "npm", + "script": "lint:fix", + "problemMatcher": [] + }, + { + "label": "Typecheck", + "type": "shell", + "command": "npm run typecheck -w @documenso/remix", + "problemMatcher": ["$tsc"] + }, + { + "label": "Build", + "type": "npm", + "script": "build", + "problemMatcher": [] + }, + { + "label": "Test", + "type": "shell", + "command": "npx turbo run test", + "problemMatcher": [] + }, + { + "label": "Test: E2E", + "type": "npm", + "script": "ci", + "detail": "Rebuilds the app and runs the full Playwright suite (matches CI) — requires the local DB to be up", + "problemMatcher": [] + }, + { + "label": "DB: Up", + "type": "npm", + "script": "dx:up", + "problemMatcher": [] + }, + { + "label": "Prisma Studio", + "type": "npm", + "script": "prisma:studio", + "isBackground": true, + "problemMatcher": [] + }, + { + "label": "PR Checks", + "dependsOn": ["Lint", "Typecheck", "Test", "Build"], + "dependsOrder": "sequence", + "problemMatcher": [] + } + ] +} diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index c4ee4abf07..04e96f31de 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -1,12 +1,12 @@ -# Keep Contracts Architecture +# KeepContracts Architecture -This document provides a high-level overview of the Keep Contracts (KC) codebase to help humans and agents understand how the application is structured. +This document provides a high-level overview of the KeepContracts (KC) codebase to help humans and agents understand how the application is structured. --- -## Keep Contracts Product Overview +## KeepContracts Product Overview -**What Keep Contracts is:** A document signing engine (white-labeled Documenso), running at keepcontracts.com. It is invisible infrastructure. End users never interact with it directly. Signup is disabled and only DataThink admins have accounts. +**What KeepContracts is:** A document signing engine (white-labeled Documenso), running at keepcontracts.com. It is invisible infrastructure. End users never interact with it directly. Signup is disabled and only DataThink admins have accounts. ### What is an Envelope @@ -47,7 +47,7 @@ KC doesn't do this, the DataThink app does. When KC creates an envelope it retur ## Codebase Overview -This section covers the technical architecture of the Keep Contracts codebase (forked from Documenso). +This section covers the technical architecture of the KeepContracts codebase (forked from Documenso). ## Overview diff --git a/CODE_STYLE.md b/CODE_STYLE.md index 435ad64a77..c665349ee0 100644 --- a/CODE_STYLE.md +++ b/CODE_STYLE.md @@ -1,6 +1,6 @@ -# Keep Contracts Code Style Guide +# KeepContracts Code Style Guide -This document captures the code style, patterns, and conventions used in the Keep Contracts codebase. It covers both enforceable rules and subjective "taste" elements that make our code consistent and maintainable. +This document captures the code style, patterns, and conventions used in the KeepContracts codebase. It covers both enforceable rules and subjective "taste" elements that make our code consistent and maintainable. ## Table of Contents diff --git a/README.md b/README.md index f97bf26ea2..ff23805ef7 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,14 @@ -# Keep Contracts +# KeepContracts Simple, secure document signing for DataThink's internal teams and products. -Keep Contracts is a white-labeled, self-hosted document signing service built on top of [Documenso](https://documenso.com) (v2.11.0) and maintained by [DataThink](https://datathink.dev). +KeepContracts is a white-labeled, self-hosted document signing service built on top of [Documenso](https://documenso.com) (v2.11.0) and maintained by [DataThink](https://datathink.dev). ## About -Keep Contracts powers document signing workflows across DataThink's products. It is not a public SaaS product; accounts are provisioned by DataThink admins. +KeepContracts powers document signing workflows across DataThink's products. It is not a public SaaS product; accounts are provisioned by DataThink admins. -Documents are sent and managed via API. End recipients (contractors, parents, etc.) sign through a standard signing link without needing a Keep Contracts account. +Documents are sent and managed via API. End recipients (contractors, parents, etc.) sign through a standard signing link without needing a KeepContracts account. ## Tech Stack diff --git a/apps/docs/src/app/og/docs/[...slug]/route.tsx b/apps/docs/src/app/og/docs/[...slug]/route.tsx index d746f1acdf..6db5d175c4 100644 --- a/apps/docs/src/app/og/docs/[...slug]/route.tsx +++ b/apps/docs/src/app/og/docs/[...slug]/route.tsx @@ -68,7 +68,7 @@ export async function GET(_req: Request, { params }: RouteContext<'/og/docs/[... }} > {/* eslint-disable-next-line @next/next/no-img-element */} - Keep Contracts + KeepContracts - Keep Contracts + KeepContracts ), }, diff --git a/apps/remix/app/components/dialogs/account-delete-dialog.tsx b/apps/remix/app/components/dialogs/account-delete-dialog.tsx index 25b16f34dc..cdfcc0169b 100644 --- a/apps/remix/app/components/dialogs/account-delete-dialog.tsx +++ b/apps/remix/app/components/dialogs/account-delete-dialog.tsx @@ -103,7 +103,7 @@ export const AccountDeleteDialog = ({ className }: AccountDeleteDialogProps) => - Keep Contracts will delete all of your documents, along with + KeepContracts will delete all of your documents, along with all of your completed documents, signatures, and all other resources belonging to your Account. diff --git a/apps/remix/app/components/dialogs/envelope-distribute-dialog.tsx b/apps/remix/app/components/dialogs/envelope-distribute-dialog.tsx index d85249adf8..dfacdec80b 100644 --- a/apps/remix/app/components/dialogs/envelope-distribute-dialog.tsx +++ b/apps/remix/app/components/dialogs/envelope-distribute-dialog.tsx @@ -351,7 +351,7 @@ export const EnvelopeDistributeDialog = ({ ))} - Keep Contracts + KeepContracts diff --git a/apps/remix/app/components/dialogs/token-create-dialog.tsx b/apps/remix/app/components/dialogs/token-create-dialog.tsx index f8bfc5c3c8..5a1c421c3d 100644 --- a/apps/remix/app/components/dialogs/token-create-dialog.tsx +++ b/apps/remix/app/components/dialogs/token-create-dialog.tsx @@ -171,7 +171,7 @@ export const TokenCreateDialog = ({ trigger, ...props }: TokenCreateDialogProps) - Use API tokens to authenticate with the Keep Contracts API. + Use API tokens to authenticate with the KeepContracts API. diff --git a/apps/remix/app/components/dialogs/webhook-create-dialog.tsx b/apps/remix/app/components/dialogs/webhook-create-dialog.tsx index 8738c89c51..ea5e53a915 100644 --- a/apps/remix/app/components/dialogs/webhook-create-dialog.tsx +++ b/apps/remix/app/components/dialogs/webhook-create-dialog.tsx @@ -127,7 +127,7 @@ export const WebhookCreateDialog = ({ trigger, ...props }: WebhookCreateDialogPr - The URL for Keep Contracts to send webhook events to. + The URL for KeepContracts to send webhook events to. diff --git a/apps/remix/app/components/dialogs/webhook-edit-dialog.tsx b/apps/remix/app/components/dialogs/webhook-edit-dialog.tsx index f2f5d2e357..b2be65cb58 100644 --- a/apps/remix/app/components/dialogs/webhook-edit-dialog.tsx +++ b/apps/remix/app/components/dialogs/webhook-edit-dialog.tsx @@ -111,7 +111,7 @@ export const WebhookEditDialog = ({ trigger, webhook, ...props }: WebhookEditDia - The URL for Keep Contracts to send webhook events to. + The URL for KeepContracts to send webhook events to. diff --git a/apps/remix/app/components/embed/embed-document-completed.tsx b/apps/remix/app/components/embed/embed-document-completed.tsx index 37e5648dbd..3299037285 100644 --- a/apps/remix/app/components/embed/embed-document-completed.tsx +++ b/apps/remix/app/components/embed/embed-document-completed.tsx @@ -18,7 +18,7 @@ export const EmbedDocumentCompleted = ({ name, signature }: EmbedDocumentComplet
diff --git a/apps/remix/app/components/forms/signup.tsx b/apps/remix/app/components/forms/signup.tsx index bc81260b0b..d930ba9691 100644 --- a/apps/remix/app/components/forms/signup.tsx +++ b/apps/remix/app/components/forms/signup.tsx @@ -371,6 +371,20 @@ export const SignUpForm = ({ Create account )} + +

+ + By creating an account, you agree to our{' '} + + Terms of Service + {' '} + and{' '} + + Privacy Policy + + . + +

diff --git a/apps/remix/app/components/general/admin-license-card.tsx b/apps/remix/app/components/general/admin-license-card.tsx index 5c81dfb052..edb60a694b 100644 --- a/apps/remix/app/components/general/admin-license-card.tsx +++ b/apps/remix/app/components/general/admin-license-card.tsx @@ -88,7 +88,7 @@ export const AdminLicenseCard = ({ licenseData }: AdminLicenseCardProps) => {

- Keep Contracts License + KeepContracts License

{match(license.status) diff --git a/apps/remix/app/components/general/admin-license-status-banner.tsx b/apps/remix/app/components/general/admin-license-status-banner.tsx index 1a86ec53cf..3133a63fb8 100644 --- a/apps/remix/app/components/general/admin-license-status-banner.tsx +++ b/apps/remix/app/components/general/admin-license-status-banner.tsx @@ -37,11 +37,11 @@ export const AdminLicenseStatusBanner = ({ license }: AdminLicenseStatusBannerPr .with('UNAUTHORIZED', () => license ? ( - Invalid License Type - Your Keep Contracts instance is using features that are not part of your + Invalid License Type - Your KeepContracts instance is using features that are not part of your license. ) : ( - Missing License - Your Keep Contracts instance is using features that require a license. + Missing License - Your KeepContracts instance is using features that require a license. ), ) .otherwise(() => null)} diff --git a/apps/remix/app/components/general/app-nav-mobile.tsx b/apps/remix/app/components/general/app-nav-mobile.tsx index f51791b408..c25be2e88c 100644 --- a/apps/remix/app/components/general/app-nav-mobile.tsx +++ b/apps/remix/app/components/general/app-nav-mobile.tsx @@ -116,10 +116,19 @@ export const AppNavMobile = ({ isMenuOpen, onMenuOpenChange }: AppNavMobileProps

- © {new Date().getFullYear()} Keep Contracts, Inc. + © {new Date().getFullYear()} KeepContracts, Inc.
All rights reserved.

+ +

+ + Terms + + + Privacy + +

diff --git a/apps/remix/app/components/general/branding-logo-icon.tsx b/apps/remix/app/components/general/branding-logo-icon.tsx index 0357d6bfd8..3f631e46d8 100644 --- a/apps/remix/app/components/general/branding-logo-icon.tsx +++ b/apps/remix/app/components/general/branding-logo-icon.tsx @@ -8,8 +8,8 @@ export type LogoProps = HTMLAttributes; export const BrandingLogoIcon = ({ className, ...props }: LogoProps) => { return ( <> - Keep Contracts - Keep Contracts + KeepContracts + KeepContracts ); }; diff --git a/apps/remix/app/components/general/branding-logo.tsx b/apps/remix/app/components/general/branding-logo.tsx index 88a9cdaa0e..d006745803 100644 --- a/apps/remix/app/components/general/branding-logo.tsx +++ b/apps/remix/app/components/general/branding-logo.tsx @@ -8,8 +8,8 @@ export type LogoProps = HTMLAttributes; export const BrandingLogo = ({ className, ...props }: LogoProps) => { return ( <> - Keep Contracts - Keep Contracts + KeepContracts + KeepContracts ); }; diff --git a/apps/remix/app/components/general/document/document-certificate-qr-view.tsx b/apps/remix/app/components/general/document/document-certificate-qr-view.tsx index 51301fe2db..35112c146c 100644 --- a/apps/remix/app/components/general/document/document-certificate-qr-view.tsx +++ b/apps/remix/app/components/general/document/document-certificate-qr-view.tsx @@ -76,7 +76,7 @@ export const DocumentCertificateQRView = ({ - This document is available in your Keep Contracts account. You can view more details, recipients, and + This document is available in your KeepContracts account. You can view more details, recipients, and audit logs there. diff --git a/apps/remix/app/components/general/envelope-editor/envelope-editor-settings-dialog.tsx b/apps/remix/app/components/general/envelope-editor/envelope-editor-settings-dialog.tsx index fa616b2c7d..2d74900416 100644 --- a/apps/remix/app/components/general/envelope-editor/envelope-editor-settings-dialog.tsx +++ b/apps/remix/app/components/general/envelope-editor/envelope-editor-settings-dialog.tsx @@ -775,7 +775,7 @@ export const EnvelopeEditorSettingsDialog = ({ trigger, ...props }: EnvelopeEdit ))} - Keep Contracts + KeepContracts diff --git a/apps/remix/app/components/general/organisations/organisation-billing-banner.tsx b/apps/remix/app/components/general/organisations/organisation-billing-banner.tsx index 8f8af7f47b..7fea12eaeb 100644 --- a/apps/remix/app/components/general/organisations/organisation-billing-banner.tsx +++ b/apps/remix/app/components/general/organisations/organisation-billing-banner.tsx @@ -128,7 +128,7 @@ export const OrganisationBillingBanner = () => { - Your plan is no longer valid. Please subscribe to a new plan to continue using Keep Contracts. + Your plan is no longer valid. Please subscribe to a new plan to continue using KeepContracts. diff --git a/apps/remix/app/components/marketing/Features.tsx b/apps/remix/app/components/marketing/Features.tsx index 0277da8b0b..e556e54c92 100644 --- a/apps/remix/app/components/marketing/Features.tsx +++ b/apps/remix/app/components/marketing/Features.tsx @@ -78,7 +78,7 @@ export function Features() { centered eyebrow="Features" title="Everything you need to get documents signed" - description="From the first upload to the final signature — Keep Contracts covers the whole workflow without getting in your way." + description="From the first upload to the final signature — KeepContracts covers the whole workflow without getting in your way." /> diff --git a/apps/remix/app/components/marketing/MarketingFooter.tsx b/apps/remix/app/components/marketing/MarketingFooter.tsx index 16e8745016..5c5b839fcb 100644 --- a/apps/remix/app/components/marketing/MarketingFooter.tsx +++ b/apps/remix/app/components/marketing/MarketingFooter.tsx @@ -1,3 +1,5 @@ +import { Link } from 'react-router'; + import { BrandingLogo } from '~/components/general/branding-logo'; import { scrollToSection } from './scroll-to-section'; @@ -7,6 +9,11 @@ const PRODUCT_LINKS = [ { label: 'How it works', href: '#how-it-works' }, ]; +const LEGAL_LINKS = [ + { label: 'Terms of Service', href: '/terms' }, + { label: 'Privacy Policy', href: '/privacy' }, +]; + export function MarketingFooter() { return (
@@ -31,10 +38,30 @@ export function MarketingFooter() { ))} +
© {new Date().getFullYear()} DataThink. All rights reserved. - Keep Contracts — secure document signing + + Source code (AGPL-3.0) + + KeepContracts — secure document signing
diff --git a/apps/remix/app/components/marketing/MarketingHeader.tsx b/apps/remix/app/components/marketing/MarketingHeader.tsx index abc8f4a16b..6d184208f4 100644 --- a/apps/remix/app/components/marketing/MarketingHeader.tsx +++ b/apps/remix/app/components/marketing/MarketingHeader.tsx @@ -39,7 +39,7 @@ export function MarketingHeader() { >
{/* biome-ignore lint/a11y/useValidAnchor: real href for pre-hydration/no-JS fallback; onClick upgrades to a JS scroll to avoid a ScrollRestoration/native-hash-nav race (see scroll-to-section.ts) */} - scrollToSection(event, 'top')} aria-label="Keep Contracts home"> + scrollToSection(event, 'top')} aria-label="KeepContracts home"> diff --git a/apps/remix/app/routes/_authenticated+/o.$orgUrl.support.tsx b/apps/remix/app/routes/_authenticated+/o.$orgUrl.support.tsx index 1cdcb57cd1..3f31700e92 100644 --- a/apps/remix/app/routes/_authenticated+/o.$orgUrl.support.tsx +++ b/apps/remix/app/routes/_authenticated+/o.$orgUrl.support.tsx @@ -60,7 +60,7 @@ export default function SupportPage() {

- Read our documentation to get started with Keep Contracts. + Read our documentation to get started with KeepContracts.

{organisation && IS_BILLING_ENABLED() && subscriptionStatus && ( diff --git a/apps/remix/app/routes/_profile+/p.$url.tsx b/apps/remix/app/routes/_profile+/p.$url.tsx index bee5aab1b3..fd4de3fd02 100644 --- a/apps/remix/app/routes/_profile+/p.$url.tsx +++ b/apps/remix/app/routes/_profile+/p.$url.tsx @@ -113,7 +113,7 @@ export default function PublicProfilePage({ loaderData }: Route.ComponentProps) {!user?.id && ( - While waiting for them to do so you can create your own Keep Contracts account and get started with + While waiting for them to do so you can create your own KeepContracts account and get started with document signing right away. diff --git a/apps/remix/app/routes/_recipient+/_layout.tsx b/apps/remix/app/routes/_recipient+/_layout.tsx index 8686c2e458..710b43f5da 100644 --- a/apps/remix/app/routes/_recipient+/_layout.tsx +++ b/apps/remix/app/routes/_recipient+/_layout.tsx @@ -12,7 +12,7 @@ import type { Route } from './+types/_layout'; export function meta() { return [ - { title: i18n._(msg`Sign Document - Keep Contracts`) }, + { title: i18n._(msg`Sign Document - KeepContracts`) }, { name: 'robots', content: 'noindex, nofollow, noarchive, nosnippet, noimageindex' }, ]; } diff --git a/apps/remix/app/routes/_recipient+/sign.$token+/_index.tsx b/apps/remix/app/routes/_recipient+/sign.$token+/_index.tsx index 793efb5004..ae0e9f9bb7 100644 --- a/apps/remix/app/routes/_recipient+/sign.$token+/_index.tsx +++ b/apps/remix/app/routes/_recipient+/sign.$token+/_index.tsx @@ -455,7 +455,7 @@ const SigningPageV1 = ({ data }: { data: Awaited Want to send slick signing links like this one?{' '} - Check out Keep Contracts + Check out KeepContracts . @@ -554,7 +554,7 @@ const SigningPageV2 = ({ data }: { data: Awaited Want to send slick signing links like this one?{' '} - Check out Keep Contracts + Check out KeepContracts . diff --git a/apps/remix/app/routes/_share+/share.$slug.tsx b/apps/remix/app/routes/_share+/share.$slug.tsx index a742ac1742..374ca422b5 100644 --- a/apps/remix/app/routes/_share+/share.$slug.tsx +++ b/apps/remix/app/routes/_share+/share.$slug.tsx @@ -12,15 +12,15 @@ export function meta({ params: { slug } }: Route.MetaArgs) { } return [ - { title: 'Keep Contracts - Share' }, - { description: 'I just signed a document in style with Keep Contracts!' }, + { title: 'KeepContracts - Share' }, + { description: 'I just signed a document in style with KeepContracts!' }, { property: 'og:title', - content: 'Keep Contracts - Join the open source signing revolution', + content: 'KeepContracts - Join the open source signing revolution', }, { property: 'og:description', - content: 'I just signed with Keep Contracts!', + content: 'I just signed with KeepContracts!', }, { property: 'og:type', @@ -53,7 +53,7 @@ export const loader = async ({ request, params: { slug } }: Route.LoaderArgs) => return {}; } - // Is hardcoded because this whole meta is hardcoded anyway for Keep Contracts. + // Is hardcoded because this whole meta is hardcoded anyway for KeepContracts. throw redirect('https://keepcontracts.com'); }; diff --git a/apps/remix/app/routes/_unauthenticated+/articles.signature-disclosure.tsx b/apps/remix/app/routes/_unauthenticated+/articles.signature-disclosure.tsx index f4152d088c..6ad7dca715 100644 --- a/apps/remix/app/routes/_unauthenticated+/articles.signature-disclosure.tsx +++ b/apps/remix/app/routes/_unauthenticated+/articles.signature-disclosure.tsx @@ -16,7 +16,7 @@ export default function SignatureDisclosure() {

- Thank you for using Keep Contracts to perform your electronic document signing. The purpose of this + Thank you for using KeepContracts to perform your electronic document signing. The purpose of this disclosure is to inform you about the process, legality, and your rights regarding the use of electronic signatures on our platform. By opting to use an electronic signature, you are agreeing to the terms and conditions outlined below. @@ -127,7 +127,7 @@ export default function SignatureDisclosure() {

- By proceeding to use the electronic signature service provided by Keep Contracts, you affirm that you have + By proceeding to use the electronic signature service provided by KeepContracts, you affirm that you have read and understood this disclosure. You agree to all terms and conditions related to the use of electronic signatures and electronic transactions as outlined herein. diff --git a/apps/remix/app/routes/_unauthenticated+/o.$orgUrl.signin.tsx b/apps/remix/app/routes/_unauthenticated+/o.$orgUrl.signin.tsx index 1cf4acc247..481d7dec65 100644 --- a/apps/remix/app/routes/_unauthenticated+/o.$orgUrl.signin.tsx +++ b/apps/remix/app/routes/_unauthenticated+/o.$orgUrl.signin.tsx @@ -204,7 +204,7 @@ export default function OrganisationSignIn({ loaderData }: Route.ComponentProps)

- Return to Keep Contracts sign in page here + Return to KeepContracts sign in page here
diff --git a/apps/remix/app/routes/_unauthenticated+/verify-email.$token.tsx b/apps/remix/app/routes/_unauthenticated+/verify-email.$token.tsx index a54105006f..75aadd58c8 100644 --- a/apps/remix/app/routes/_unauthenticated+/verify-email.$token.tsx +++ b/apps/remix/app/routes/_unauthenticated+/verify-email.$token.tsx @@ -142,7 +142,7 @@ export default function VerifyEmailPage({ loaderData }: Route.ComponentProps) {

- Your email has been successfully confirmed! You can now use all features of Keep Contracts. + Your email has been successfully confirmed! You can now use all features of KeepContracts.