An accessible web platform with auth, payments, and encrypted messaging. Running live, and free to fork.
How it fits together. The full reference diagram adds every table, Edge Function, and route. Or read the architecture guide.
This is a real product, not a scaffold. It runs at scripthammer.com with OAuth and email sign-in, Stripe and PayPal payments, end-to-end encrypted messaging, an admin surface, and an installable offline-capable app that meets WCAG AA.
You can also fork it and build your own thing on top. That takes about five minutes.
| The app | scripthammer.com |
| Component library | scripthammer.com/storybook |
| Status dashboard | scripthammer.com/status |
You need Docker and git. That's it. Local pnpm and npm aren't supported, because everything runs in the container.
git clone https://github.com/TortoiseWolfe/ScriptHammer.git
cd ScriptHammer
cp .env.example .env # then set UID and GID: run id -u && id -g
docker compose up # first build takes 5 to 10 minutesThat gives you the dev server on http://localhost:3000. It runs without any accounts or API keys. Sign-in, payments, and messaging stay dark until you connect the services below.
Everyday commands
docker compose exec scripthammer pnpm run dev # dev server
docker compose exec scripthammer pnpm test # unit tests
docker compose exec scripthammer pnpm run storybook # component library
docker compose down && docker compose up --build # clean restartProduction builds get their own container, so they never fight the dev server for the build directory:
docker compose run --rm builder pnpm buildgh repo fork TortoiseWolfe/ScriptHammer --clone
cd YourProjectName
./scripts/rebrand.sh MyProject myusername "My project description"
cp .env.example .env
docker compose up -dThe rebrand script rewrites 200 files or so with your name. Your project name is picked up from the repository name automatically, so there's nothing else to configure.
Rebrand options, and keeping your fork up to date
./scripts/rebrand.sh MyProject myuser "Description" --dry-run # preview only
./scripts/rebrand.sh MyProject myuser "Description" --force # no prompts
./scripts/rebrand.sh MyProject myuser "Description" --keep-cname # custom domainTo pull upstream changes later:
git remote add upstream https://github.com/TortoiseWolfe/ScriptHammer.git
git fetch upstream
git merge upstream/mainWant a string to survive the rebrand? Put rebrand:keep in a comment on the same line. It is line-scoped, not file-scoped.
Full guide: docs/FORKING.md. Fresh-fork walkthrough: docs/FORK-CHECKLIST.md.
- π Authentication. Email and password, plus GitHub and Google sign-in. Protected routes and session management.
- π³ Payments. Stripe one-off and PayPal subscriptions, with consent gating and webhook handling.
- π Encrypted messaging. Direct and group chat, end-to-end encrypted with ECDH key exchange, live over Supabase.
- π‘οΈ Admin surface. Dashboard, moderation queue, security audit trail.
- π± Installable app. Works offline, syncs in the background.
- βΏ Accessibility. WCAG AA, colorblind assistance, font switching.
- π Privacy. Cookie consent gates analytics and tracking.
- π¨ 35 themes. 3 house themes plus 32 DaisyUI variants, and it remembers your pick.
- π§© Component library. Atomic design, documented in Storybook, scaffolded by a generator.
- π§ͺ Tested. Vitest, Playwright across browsers, and Pa11y, all in CI.
Built with Next.js 15.5, React 19, TypeScript 5, Tailwind 4 and DaisyUI, on Docker and pnpm.
Everything above works with no accounts. These sections are for when you want the real features on.
π Authentication (Supabase)
Nothing authenticates until you create a Supabase project and point the app at it.
- Create a project at supabase.com/dashboard. The free tier is fine to start.
- Run the database migrations. See AUTH-SETUP.md Part 1.
- Turn on the providers you want:
- Email and password, which messaging needs
- GitHub, via a GitHub OAuth App
- Google, via a Google Cloud OAuth client
- Put
NEXT_PUBLIC_SUPABASE_URLandNEXT_PUBLIC_SUPABASE_ANON_KEYin your.env. - Check your work with the Management API verification. Placeholder client IDs once sat in that field for weeks before anyone noticed, which is what issue #85 was.
Full walkthrough: docs/AUTH-SETUP.md.
π³ Payments (Stripe and PayPal)
Payments are built in but switched off. No API keys ship with the repo, so you bring your own before /payment-demo does anything real. Budget half an hour to an hour of account setup.
Where keys go, and this part matters:
| File | Committed? | What belongs there |
|---|---|---|
.env.example |
Yes | Placeholders only. Never real values. |
.env |
No | Public keys only, the NEXT_PUBLIC_ ones. They ship in the browser bundle by design. |
| Supabase Vault | No | Every server secret. |
The site is a static export with no server runtime, so anything in .env without a NEXT_PUBLIC_ prefix is unused. Edge Functions read the real secrets from the Vault.
- Stripe. Sign up at dashboard.stripe.com. From Developers β API keys take the test-mode publishable key and secret key. Add a webhook pointing at your
stripe-webhookEdge Function and copy its signing secret. - PayPal. Create a sandbox app at developer.paypal.com under Apps & Credentials. Take the client ID and secret, add a sandbox webhook, copy the webhook ID.
- Split them. Public keys go in
.env. Server secrets go in the Supabase Vault, either withsupabase secrets setor through Project Settings β Edge Functions β Secrets. - Test. Card
4242 4242 4242 4242for Stripe, sandbox buyers for PayPal. No real money moves.
Full deployment guide: docs/PAYMENT-DEPLOYMENT.md. Current status: PRP-STATUS.md.
π GitHub Actions secrets
Add these under Settings β Secrets and variables β Actions.
Required for the build and deploy to work:
| Secret | Purpose |
|---|---|
NEXT_PUBLIC_SUPABASE_URL |
Your Supabase project URL |
NEXT_PUBLIC_SUPABASE_ANON_KEY |
Your Supabase anon key |
Recommended, so the E2E suite can run:
| Secret | Purpose |
|---|---|
SUPABASE_SERVICE_ROLE_KEY |
Admin operations in tests |
TEST_USER_PRIMARY_EMAIL / _PASSWORD |
First test user |
TEST_USER_SECONDARY_EMAIL / _PASSWORD |
Second, for multi-user tests |
TEST_USER_TERTIARY_EMAIL / _PASSWORD |
Third, for group chat |
TEST_EMAIL_DOMAIN |
Domain for generated test emails |
Supabase checks that an email domain has MX records, so @example.com is always rejected. Use Gmail plus-aliases like you+test-a@gmail.com.
Optional, for author and site details:
NEXT_PUBLIC_AUTHOR_NAME, _EMAIL, _BIO, _ROLE, _AVATAR, _GITHUB, _LINKEDIN, _TWITTER, _TWITCH, plus NEXT_PUBLIC_SITE_URL, NEXT_PUBLIC_DEPLOY_URL and NEXT_PUBLIC_SOCIAL_PLATFORMS.
Optional, for integrations:
NEXT_PUBLIC_CALENDAR_PROVIDER, NEXT_PUBLIC_CALENDAR_URL, NEXT_PUBLIC_DISQUS_SHORTNAME, NEXT_PUBLIC_PAGESPEED_API_KEY, NEXT_PUBLIC_GA_MEASUREMENT_ID, NEXT_PUBLIC_SENTRY_DSN.
Error monitoring stays off until NEXT_PUBLIC_SENTRY_DSN is set, and even then it only sends anything after the visitor accepts analytics. Emails, tokens and message bodies are stripped before anything leaves the browser. Session replay and tracing are off.
Optional, for running migrations:
SUPABASE_ACCESS_TOKEN, SUPABASE_DB_PASSWORD, SUPABASE_PROJECT_REF.
π€ GitHub token for Claude Code and SpecKit
The token is for reading and filing issues. It can't push. Pushes use your SSH key, so you stay in control of what lands.
- Open fine-grained token settings.
- Name it, set 90 days, and scope it to this repository only.
- Grant read-only on Contents, Pull requests and Actions. Issues needs read and write, for
/speckit.taskstoissues. - Copy the token when it appears. You only see it once.
gh auth login # GitHub.com, then SSH, then paste the token
ssh -T git@github.com # should greet you by usernameβοΈ Automatic configuration
At build time the project reads your git remote and works out the project name, the owner, the base path for GitHub Pages, and the app manifest.
If that goes wrong, check you have a remote with git remote -v, override the values in .env, and look at src/config/project-detected.ts after a build to see what it decided.
| Developer guide | CLAUDE.md |
| Contributing | CONTRIBUTING.md |
| Creating components | docs/CREATING_COMPONENTS.md |
| Testing | docs/project/TESTING.md |
| Security | docs/project/SECURITY.md |
| Forking | docs/FORKING.md |
| Architecture | docs/architecture/README.md |
| Changelog | docs/project/CHANGELOG.md |
Fork it, branch, run the tests in Docker, open a pull request.
git checkout -b feature/your-thing
docker compose exec scripthammer pnpm testTwo checks have to pass before anything merges: Test (20.x) and accessibility. Nobody has to approve your PR, so ask for a review if the change warrants one rather than waiting for one. The details are in CONTRIBUTING.md.
π Project status and scores
Version 0.3.5. Lighthouse: performance 92, accessibility 98, best practices 95, SEO 100, PWA 92.
Component hierarchy is 22 atomic, 17 molecular, 8 organisms.
Progress by area is tracked in PRP-STATUS.md, and the design system work is in the redesign plan with its implementation plan. Phases 0 through 4 are done, molecular and organism rebuilds are next.
π§Ύ Backlog and technical debt (maintainers)
The live list is docs/TECHNICAL-DEBT.md, and open work is tracked in GitHub issues.
The SPEC-041 through SPEC-064 queue that used to sit in this file has moved to those two places. Most of the E2E stabilisation items in it were finished in 2025-12 and the entries had gone stale where they sat.
Still outstanding from that queue, as SpecKit prompts:
/speckit.workflow SPEC-049: Group Service Implementation - Complete 8 unimplemented methods in src/services/messaging/group-service.ts: addMembers, getMembers, removeMember, leaveGroup, transferOwnership, upgradeToGroup, renameGroup, deleteGroup. These throw "Not implemented". Effort: 2-3 days.
/speckit.workflow SPEC-058: Payment Security RLS - Implement payment table RLS policies in Supabase: payments table user isolation, subscriptions table RLS, admin access policies. Unblocks 25 E2E tests. Effort: 1-2 days.
π§° E2E fix loop priming prompt (maintainers)
If the E2E suite is broken and you want /loop to keep iterating on it, paste the priming prompt from docs/e2e-loop-priming.md into the loop command. It lists the current open issues, not a baseline, with concrete symptoms and what has already been tried.
Read its "Current Open Issues" section for where things actually stand. Do not treat the doc as a clean baseline.
MIT. See LICENSE.
