Web apps

Freelancer invoice builder with card payment links

Invoice app where freelancers build itemized invoices, share an unguessable link, and clients pay by card through hosted checkout.

nextjstypescriptprismapostgrestailwindstripe

Built 1 time, downloaded 0 times.

Install from your terminal

Run this in your project folder. It signs you in, shows what changes and asks before it overwrites a file.

npx claude-lab add freelancer-invoice-builder-with-card-payment-links-8e9441
CLAUDE.md
# Freelancer invoice builder

Freelancers create invoices in this app, publish them as a public link at /i/[token], and clients pay by card through Stripe Checkout. Freelancers sign in with an email link. Clients need no account. Each invoice shows its line items, tax, total and due date, and the client's Pay button creates a Stripe Checkout session for the exact stored total.

## Stack

- Next.js App Router with TypeScript in strict mode
- Tailwind CSS for styling
- Prisma with Postgres. The connection string comes from DATABASE_URL in the environment.
- Auth.js with email sign-in
- Stripe, in test mode until launch
- Zod for validating all input
- Vitest for unit tests
- Playwright for end-to-end tests

## Commands

- `npm run dev` starts the app at http://localhost:3000
- `npm run typecheck` runs the TypeScript compiler without emitting files
- `npm run lint` checks code style and common mistakes
- `npm test` runs the Vitest unit tests
- `npx playwright test` runs the end-to-end tests
- `npm run build` makes a production build
- `npx prisma migrate dev` creates and applies a migration in development
- `npx prisma studio` opens a browser view of the database

## Conventions

- Money is stored as integer cents. Each invoice stores its own currency code.
- Totals are always recomputed on the server. Never trust a total sent from the client.
- Server actions live in `app/actions/`.
- Stripe calls live only in `lib/stripe.ts`. Nothing else imports the Stripe SDK.
- Every database query that reads an invoice must filter by the signed-in owner or by the public token. A query without one of these filters is a bug.
- Invoice numbers are sequential per freelancer with no gaps. Assign them inside a database transaction.
- Keep components small. Put shared logic in `lib/`.

## Gotchas

- Stripe webhooks need the signature checked with STRIPE_WEBHOOK_SECRET against the raw request body. Parsed JSON will fail the check.
- Local webhook testing uses `stripe listen`. Follow the `stripe-test` skill.
- Never log card data, email addresses in bulk, or full secret values.
- Webhooks can arrive more than once. Payment creation must be idempotent, keyed on the Stripe session id.
- The success page does not mark an invoice paid. Only the verified webhook does.
- Never write real keys into any file. Use placeholders such as YOUR_STRIPE_SECRET_KEY in `.env.example`, and keep real values in `.env.local`, which is never committed.

## Working rules

- Explore the relevant code first. Then write a short numbered plan. Then code. Then run the `verify` skill.
- Run `/clear` between unrelated tasks.
- Ask before deleting files, running `prisma migrate reset`, running `prisma migrate deploy`, pushing to git, or changing anything in production.
- A task is not done while any check in `verify` fails.
- Review rules are in REVIEW.md, which is imported below so `/review` applies them.

@REVIEW.md

Detailed product scope is in SPEC.md. The phased build plan is in PLAN.md.
Use for my project