Shared paper for users and agents. Built with Next.js, Clerk, Convex, Neon, and sketchbook-ui.
- Next.js app router
- Clerk auth
- Convex realtime backend
- Neon + Drizzle
sketchbook-uifor the paper UI
npm install
cp env.example .env.localFill in .env.local, then run:
npx convex dev
npx drizzle-kit push
npm run doctor
npm run dev:stack# Clerk
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_...
CLERK_SECRET_KEY=sk_...
CLERK_ISSUER_URL=https://your-clerk-subdomain.clerk.accounts.dev
CLERK_WEBHOOK_SIGNING_SECRET=whsec_...
# Neon
DATABASE_URL=postgresql://...
# Convex
CONVEX_DEPLOYMENT=dev:...
NEXT_PUBLIC_CONVEX_URL=https://your-deployment.convex.cloud
NEXT_PUBLIC_CONVEX_SITE_URL=https://your-deployment.convex.site
# AI
OPENAI_API_KEY=sk-...
# ANTHROPIC_API_KEY=sk-ant-...Use deploy/vercel.production.env as the import template.
Important values:
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY: production Clerk key for the same Clerk instanceCLERK_SECRET_KEY: matching production Clerk secretNEXT_PUBLIC_CLERK_SIGN_IN_URL=/sign-inNEXT_PUBLIC_CLERK_SIGN_IN_FALLBACK_REDIRECT_URL=/dashboardNEXT_PUBLIC_CLERK_SIGN_UP_FALLBACK_REDIRECT_URL=/dashboardCONVEX_DEPLOYMENT=prod:intent-mole-436CONVEX_DEPLOY_KEY=...NEXT_PUBLIC_CONVEX_URL=https://intent-mole-436.convex.cloudNEXT_PUBLIC_CONVEX_SITE_URL=https://intent-mole-436.convex.siteCONVEX_TMPDIR=.convex-tmp
Use deploy/convex.production.env for the Convex dashboard values.
Important value:
CLERK_ISSUER_URL=https://clerk.paper.ruixen.app
This value is the Clerk Frontend API URL that Convex trusts in auth.config.ts. It should match the Clerk production instance and the publishable key used by the frontend.
npm run build now does a real production Convex deploy before the Next.js build:
npx convex deploy --cmd 'npm run build:app'That matters because production needs both:
- the frontend bundle built by Next.js
- the current Convex functions pushed to
intent-mole-436
If you only want a local app build without deploying Convex, use:
npm run build:app- The Clerk production instance currently uses the custom domain family under
paper.ruixen.app - Clerk Frontend API:
https://clerk.paper.ruixen.app - Clerk account portal:
https://accounts.paper.ruixen.app - Convex auth expects audience
convex - The Clerk JWT template named
convexmust exist
In this repo, the browser always requests the explicit convex JWT template before talking to Convex.
To keep the current production auth setup working:
- app domain should be
paper.ruixen.app - Clerk DNS records in Cloudflare should stay
DNS only, not proxied - Convex production should trust
https://clerk.paper.ruixen.app
If you later change the Clerk production domain again, you must recheck:
- Clerk publishable key in Vercel
CLERK_ISSUER_URLin Convex- Clerk DNS verification / SSL
Before shipping:
npm run lint
npm run test:unit
npx tsc --noEmit
npm run buildnpm run doctor is also useful when auth/env wiring changes.
npm run doctor
npm run dev:stack
npm run bootstrap
npm run clean
npx convex run health:stack '{}'