This is a Next.js project bootstrapped with create-next-app.
Copy the example env file and fill in real values:
cp .env.example .envSet required keys (for example ANTHROPIC_API_KEY, BREVO_API_KEY, SUPPORT_EMAIL/WAITLIST_EMAIL, and Upstash Redis values if rate limiting is enabled).
Preferred method: DNS TXT verification. Alternative: HTML file verification (do not use the AdSense meta tag).
- Go to Google Search Console -> Add Property -> URL prefix -> https://plain.tools
- Choose HTML file verification method
- Download the verification file and replace
public/google-search-console-verify.htmlwith the actual file content from Google - Deploy, then click Verify in Search Console
- Once verified, submit https://plain.tools/sitemap.xml under Sitemaps
- Go to https://www.bing.com/webmasters and add
https://plain.tools - Copy your
msvalidate.01verification code - Replace the placeholder in
app/layout.tsx:<!-- <meta name="msvalidate.01" content="[YOUR_BING_CODE]" /> -->
- Deploy and click Verify in Bing Webmaster Tools
Run after each significant content update to notify Bing, Yandex, and other IndexNow participants immediately:
pnpm run ping-indexnowThe site uses Plausible Analytics for privacy-first product analytics.
- Script is loaded in
app/layout.tsxwithdata-domain="plain.tools". - CSP allowlist includes
https://plausible.ioinscript-srcandconnect-src. - No cookies are required.
Setup steps:
- Create a site in Plausible for
plain.tools. - Confirm the script is active on production (
View Page Sourceor browser network). - Verify custom events appear in the Plausible dashboard:
Tool DownloadAI Limit ReachedShare Click
The Pro subscription stack uses Clerk (auth) + Stripe (billing + tax).
- Create Stripe product
Plain Prowith:- Monthly:
€7.00 - Annual:
€59.00
- Monthly:
- Enable Stripe Tax in dashboard.
- Configure env vars:
STRIPE_SECRET_KEYSTRIPE_PUBLISHABLE_KEYSTRIPE_PRO_MONTHLY_PRICE_IDSTRIPE_PRO_ANNUAL_PRICE_IDSTRIPE_WEBHOOK_SECRETNEXT_PUBLIC_STRIPE_PRO_MONTHLY_PRICE_IDNEXT_PUBLIC_STRIPE_PRO_ANNUAL_PRICE_ID
- Configure Clerk keys:
CLERK_SECRET_KEYNEXT_PUBLIC_CLERK_PUBLISHABLE_KEY
- Stripe webhook endpoint:
POST /api/stripe/webhook- enable events:
checkout.session.completedcustomer.subscription.deletedinvoice.payment_failed
This project sets strict browser security headers at the framework level via next.config.ts for all non-API routes.
Strict-Transport-Security: max-age=63072000; includeSubDomains; preloadX-Frame-Options: DENYX-Content-Type-Options: nosniffReferrer-Policy: strict-origin-when-cross-originPermissions-Policy: camera=(), microphone=(), geolocation=()Content-Security-Policy:default-src 'self'script-src 'self' 'unsafe-eval' 'unsafe-inline' https://translate.googleapis.com https://translate.google.comstyle-src 'self' 'unsafe-inline' https://fonts.googleapis.comfont-src 'self' https://fonts.gstatic.comimg-src 'self' data: blob: https://translate.googleapis.com https://www.gstatic.comscript-srcalso allowshttps://plausible.iofor privacy-first analyticsconnect-src 'self' https://api.anthropic.com https://translate.googleapis.comconnect-srcalso allowshttps://plausible.ioworker-src 'self' blob:frame-src 'none'object-src 'none'base-uri 'self'
/api routes are intentionally excluded from this header set. API CORS and route-level response headers are handled in API route logic (lib/api-cors.ts and route handlers).
API routes also emit structured JSON error and warning logs (lib/logger.ts) suitable for production ingestion. On Vercel, these logs are captured automatically and can be forwarded through log drains. For production monitoring, connect a drain provider such as Axiom, Logtail, or Papertrail.
The app is configured with withAxiom(...) in next.config.ts and uses next-axiom in lib/logger.ts for production log ingestion.
- Create an Axiom dataset.
- Create an Axiom token with ingest permissions.
- Set these Vercel environment variables:
NEXT_PUBLIC_AXIOM_DATASETAXIOM_TOKEN
- In Vercel, enable log drain forwarding to Axiom (or use Axiom ingestion directly via env vars above).
Public health endpoint:
GET /api/health- Response:
{ "status": "ok", "version": "1.0.0", "timestamp": "<ISO-8601>" }
This endpoint is intentionally crawl-allowed in robots.txt for uptime tooling compatibility.
- All env vars in
.env.exampleare set in Vercel project settings -
ANTHROPIC_API_KEYis valid and has sufficient quota -
ALLOWED_ORIGINis set tohttps://plain.tools - Upstash Redis is provisioned and
UPSTASH_REDIS_REST_URL/UPSTASH_REDIS_REST_TOKENare set (or in-memory fallback is acceptable) - Vercel deployment is on Production branch (
main) - Custom domain
plain.toolsis connected and SSL is active in Vercel -
pnpm run buildpasses locally on latestmain -
pnpm run lintpasses with 0 errors -
pnpm exec tsc --noEmitpasses -
pnpm run test:e2epasses
- Homepage loads at
https://plain.tools - Merge PDF tool: upload two PDFs, merge, download result
- Split PDF tool: upload a multi-page PDF, split, download
- Compress PDF tool: upload a PDF, compress, download
- OCR tool: upload an image-based PDF, run OCR, download searchable PDF
- AI Summarise: upload a PDF, request summary (confirm API key works)
- Support form: submit a test message, confirm no 500 error
- Verify Claims page loads
-
/sitemap.xmlreturns valid XML with no 404 URLs -
/robots.txtreferences sitemap and disallows/api/ - Security headers present: check via
https://securityheaders.com
- Revert to previous commit:
git revert HEAD && git push origin main - Or use Vercel dashboard:
Deployments > previous deployment > Promote to Production
First, run the development server:
npm run dev
# or
yarn dev
# or
pnpm dev
# or
bun devOpen 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 to automatically optimize and load Geist, a new font family for Vercel.
To learn more about Next.js, take a look at the following resources:
- Next.js Documentation - learn about Next.js features and API.
- Learn Next.js - an interactive Next.js tutorial.
You can check out the Next.js GitHub repository - your feedback and contributions are welcome!
The easiest way to deploy your Next.js app is to use the Vercel Platform from the creators of Next.js.
Check out our Next.js deployment documentation for more details.