Stack builder | Profullstack

STACK / BUILD

Build an app on the stack

Tick the surfaces and the house modules you want. You get a boilerplate with the house rules in AGENTS.md and CLAUDE.md. Hand it to Claude Code, codex or moshcode and let it take over.

Surfaces

House modules

Only modules that serve the ticked surfaces are shown. Ops modules always are.

Get it

Files

# My app: agent instructions

This repo is a boilerplate from the Profullstack /stack builder (https://profullstack.com/stack/build).
You are the agent taking it over. Build the app it describes.

## Your job

1. Read this whole file. The stack and house rules below are not optional.
2. Ask the owner what the app is for if the README does not say.
3. Put shared logic in `src/core/`. Every surface calls the core and nothing else.
4. Wire each module from `src/modules/`. The snippets are starting points; finish them.
5. Add tests next to the code (`bun test`). Keep CI green.
6. Ship through `bin/install.sh` (OpenInstall) or sh1pt. No manual setup steps.

## What was picked

- **App:** My app (`my-app`)
- **Surfaces:** `api`, `web`
- **Modules:** none picked yet

## Where each surface lives

- **api:** `src/api/server.ts`: Hono on Bun. `/healthz` and `/api/v1/status`.
- **web:** `app/`: Next app router. The browser talks only to `/api`.

## Hard rules

- No Stripe and no card checkout. Payments are CoinPay (crypto) and x402.
- The browser talks only to `/api`. No database client in client code.
- Auth is magic link plus passkeys.
- Secrets live in the vault and the platform env, never in a committed `.env`.
- Copy has no em dashes and no LLM flourishes. Short sentences.

---

# The stack (from https://profullstack.com/stack.md)

# The Profullstack stack

> Profullstack runs about 170 active repos on a small number of deliberate combinations. Pick the combo that matches the job, inherit the shared defaults, follow the house rules, and reuse the published packages before writing anything new.
>
> Human page: https://profullstack.com/stack · JSON: https://profullstack.com/stack.json · Skill: https://profullstack.com/skill.md · Updated 2026-10-19

## 1. Pick a combo

There is no single stack. Match the job to one of the combos below, then apply the shared defaults and house rules.

| If you are building | Use | Why |
| --- | --- | --- |
| A new product with a web UI | `web-app` | Next 16 on Turso with a Hono API inside the app. This is the default for anything new. |
| A change to an existing SaaS on Supabase or Postgres | `web-app-postgres` | Stay on the database it has. Do not migrate an app to Turso as a side effect of a feature. |
| A real-time 3D game, in the browser and on the desktop | `games` | Babylon on a pure rules core, server-authoritative multiplayer, and art generated by committed scripts rather than modelled by hand. |
| An API, crawler, poller or data service with little or no UI | `api-service` | Hono on Turso, Bun or Node, one Railway service with a health check. |
| A command-line or terminal tool, or an agent-facing bridge | `cli-tui` | Node, TypeScript, commander, hqtui for dashboards, MCP where an agent should drive it, published to npm. |
| A desktop app | `desktop` | Electron with the CLI bundled inside it, so one install gives both surfaces. |
| A mobile app | `mobile` | Expo inside the product monorepo, sharing the API and packages. |
| Code two or more products need | `library` | A runtime-neutral @profullstack/* package with subpath exports, released from GitHub. |
| Something that must be a single fast binary | `systems` | Rust (tokio, axum, clap), or Go when the upstream ecosystem is Go. |

## 2. Shared defaults (every combo)

| Concern | Choice | Notes |
| --- | --- | --- |
| Language | TypeScript, ESM | "type": "module" everywhere. Kebab-case filenames, semicolons, printWidth 100. JavaScript with JSDoc is fine in small packages. |
| Runtime | Node 22 or 24 (floor is 20) | Bun 1.4 where the repo pins it in packageManager. Runtimes are managed with mise on dev boxes. |
| Package manager | pnpm, pinned in packageManager | Bun on Bun repos. Never mix lockfiles. Workspaces via pnpm-workspace.yaml for monorepos (apps/, packages/, services/). |
| Hosting | Railway | One project per product, railway.json per service with healthcheckPath, deploys on push to the default branch. Custom domain before any URL is written down. |
| Web server | Caddy | Hosts, reverse proxies and static sites with automatic HTTPS (it gets and renews certificates itself) and IPv6 on by default. Its localhost admin API lets agents and the w3bs CLI add a site without editing config. The default web server on W3BS OS and in front of pit.world and Moshpit names (moshpit-proxy). nginx boxes keep nginx until they are moved. |
| DNS | Porkbun | No Cloudflare DNS requirement. |
| Secrets | logicsrc team vault + Railway service variables | Set on the service, record in the vault. No .env files in repos; a framework-required .env.local is a local cache, never the source. |
| Auth | Magic link + passkeys | The magic link doubles as signup. Passkeys via @simplewebauthn. An optional password only for devices that cannot open mail or hold a passkey (TVs). |
| Email | Resend | Transactional via the API; @profullstack/emailer for batch with SMTP fallback. Forward Email hosts the mailboxes. |
| Payments | CoinPay (crypto) and x402 | Crypto through @profullstack/coinpay. x402 sells access to agents and crawlers, settled by CoinPay. No Stripe and no card checkout. |
| Crawler policy | @profullstack/x402-gateway + @profullstack/throttle | Training crawlers get 402 with a daily pass to buy, robots.txt is generated from the same lists, and every route is limited to 100 req/min with a price instead of a 429. |
| Media playback | @profullstack/player | Every audio and video player: MP4, HLS, MPEG-TS and audio with one control bar. `attachSource` when a site keeps its own UI. A third-party player bump that breaks means move to it, not migrate the old player. |
| Modern CSS | @profullstack/modern-css | Subgrid cards, squircle corners, stuck headers, grid gap rules, height:auto accordions, reading-flow and @function helpers (--fluid, --alpha, --inner-radius) as opt-in classes in the components layer. Reach for these before JS or extra DOM. Every one is progressive enhancement: write the plain value first. |
| Analytics | CrawlProof stats.js | Every public site loads crawlproof.com/stats.js. Careers pages are fed from CrawlProof. |
| Referrals | @profullstack/stack/referrals | Tracked in the request proxy, 60/20 split. |
| Testing | vitest | `vitest run` in CI. `node --test` for small CLIs, `bun test` on Bun repos, Playwright for browser flows. |
| Lint + format | Prettier + ESLint | Biome or Oxlint where a repo already uses it. Do not add a second formatter to a repo. |
| CI | GitHub Actions | ci.yml, codeql.yml and threatcrush-scan.yml on every repo. Release after merge with gh release; a merged PR reaches nobody until the release is cut. |
| AI | Claude via @anthropic-ai/sdk, MCP via @modelcontextprotocol/sdk | Anything an agent should operate ships an MCP bridge. Cheap models for high-volume loops. |
| Promotion | myna (mynaposter.com) | The last phase of every ship: socials, both blogs and a CrawlProof ad from one command. Syndicated copies carry rel=canonical back to our page. |
| Data | NicheDB, RSS Amplifier, r4ck | Datasets come from and go back to nichedb.dev. Feeds are submitted through @profullstack/submit-feed. OpenProfile.md for people, /.well-known/openaccess.json for access terms. |

## 3. Combos

### Web app (`web-app`)

The default for a new product. Next 16 renders the UI, a Hono app mounted inside it serves the API, Turso holds the data, and one Railway service runs web and worker together.

**Use it when:**

- You are starting a product that has a UI and a database.
- The data fits SQLite semantics: one writer, modest joins, no Postgres extensions.
- You want one service, one deploy, one domain.

| Concern | Choice | Notes |
| --- | --- | --- |
| Framework | Next 16, React 19 | App Router. proxy.ts, not middleware.ts. Server components by default. |
| API | Hono inside Next | Mounted under /api. Versioned routes live at /api/v1/... and OAuth callbacks at /api/v1/<provider>/<function>/<endpoint>. |
| Database | Turso (libSQL) via @libsql/client | Forward-only SQL migrations in packages/db, or Drizzle with dialect turso. Migrations must be safe to run twice concurrently. |
| UI | Tailwind 4 + shadcn/ui | Scoped behind a ui.css without preflight when adding to an existing site. Plain CSS modules on marketing sites. |
| Realtime | Server-Sent Events | WebSockets only for chat, terminals and multiplayer. |
| Background work | A worker process in the same container | Supervised by the entrypoint; the container exits non-zero when either process dies. BullMQ on Redis only when the queue is the product. |
| Storage | Railway volume or Cloudflare R2 | R2 buckets private, served through signed or proxied routes. |
| Layout | apps/web, packages/db, services/worker | Root-only vitest config, tsconfig.base.json with strict flags. Copy nightcell7 or reeleel rather than inventing a layout. |

**Notes:**

- Next inlines process.env.NAME at build time, so read runtime secrets through a non-literal key.
- A 200 on /api/health proves nothing about the worker. Check the logs for its up line after a deploy.

**Examples:** [rssamplifier.com](https://rssamplifier.com) · [p0dcasters](https://github.com/profullstack/p0dcasters) · [c0upons](https://github.com/profullstack/c0upons) · [opensourcelegends.com](https://opensourcelegends.com) · [sorrycheck](https://github.com/profullstack/sorrycheck) · [sinkstate](https://github.com/profullstack/sinkstate) · [bufferoverride](https://github.com/profullstack/bufferoverride) · [nightcell7](https://github.com/profullstack/nightcell7)

### Web app on Postgres (`web-app-postgres`)

The previous generation of the same shape, and still the largest by count. Next 16 on Supabase, or on a self-hosted Postgres in the same Railway project. Kept where the data needs Postgres or the app already lives there.

**Use it when:**

- The app is already on Supabase or Postgres. Stay there.
- You need row-level security, pgvector, heavy relational joins, or a queue on Redis next to the database.
- Several services share one database and the write volume is real.

| Concern | Choice | Notes |
| --- | --- | --- |
| Framework | Next 16, React 19 | Same conventions as web-app. |
| Database | Supabase Postgres, or self-hosted Postgres on Railway | Supabase client via @profullstack/stack/supabase. New Postgres apps self-host on Railway (w3bs.org is the reference). Index every foreign key you will cascade through. |
| Auth | Magic link + passkeys on the app's own users table | Supabase Auth exists in older apps; the local users.id is always the primary key. |
| Queues | BullMQ on Redis | Custom job ids must not contain a colon. |
| Migrations | supabase/migrations or plain SQL | Applied in CI or on boot, never by hand in the dashboard. |

**Notes:**

- Do not move an app to Turso as part of a feature. Classify it first: easy Turso, needs Postgres, or consolidate.
- coinpayportal is public with 19 forks. Never put real data in a fixture there.

**Examples:** [coinpayportal.com](https://coinpayportal.com) · [ugig.net](https://ugig.net) · [crawlproof.com](https://crawlproof.com) · [marksyncr.com](https://marksyncr.com) · [logicsrc.com](https://logicsrc.com) · [w3bs.org](https://w3bs.org) · [brisk.news](https://brisk.news) · [icemap.app](https://icemap.app)

### API service (`api-service`)

Hono on Turso with no framework in front of it. For pollers, crawlers, data APIs, MCP servers and anything whose UI is a few server-rendered pages or none at all. Bun or Node, chosen per repo and pinned.

**Use it when:**

- The product is an API, a feed, a dataset or a daemon.
- The UI is small enough to render from Hono (JSX or templates) or lives in a separate app.
- You want the smallest possible service: one process, one SQLite file or one Turso database.

| Concern | Choice | Notes |
| --- | --- | --- |
| Framework | Hono 4 | Web-standard Request/Response. Same app runs on Bun and Node; the router is the only Hono-specific code. |
| Runtime | Bun or Node, pinned | Bun for stream-heavy or IO-heavy services (genrewatch, tipoffwatch, niche-db, r4ck). Node + pnpm when the service shares code with a Next app or a CLI. |
| Database | Turso (libSQL) | Embedded replica or remote. FTS5 for search, with the raw query escaped; libSQL cannot bind undefined. |
| Rate limiting | @profullstack/throttle | Credentialed callers get 600/min, anonymous 100/min, over the limit is a 402 with an offer. |
| Agent surface | MCP bridge in the CLI package | One query vocabulary across page, API, CLI and MCP. |
| Deploy | Railway, Dockerfile or Nixpacks | railway.json with healthcheckPath. Pin pnpm 10 on Nixpacks; corepack cannot launch pnpm 11. |

**Notes:**

- Bun-only gotchas: Bun.serve idleTimeout kills long streams, and Bun's SQL client stringifies arrays. Keep those behind small adapters.

**Examples:** [nichedb.dev](https://nichedb.dev) · [r4ck.dev](https://r4ck.dev) · [genrewatch.com](https://genrewatch.com) · [tipoffwatch.com](https://tipoffwatch.com) · [watchnews.now](https://watchnews.now) · [agenticjobs](https://github.com/profullstack/agenticjobs) · [tronbrowser.dev](https://tronbrowser.dev) · [reeleel](https://github.com/profullstack/reeleel)

### CLI and TUI (`cli-tui`)

Terminal tools for people and agents. Node and TypeScript, commander for arguments, hqtui for anything with a screen, an MCP bridge so an agent can drive the same commands, published to npm under @profullstack.

**Use it when:**

- The user is a developer, an operator or an agent.
- The tool wraps a site or API we run (nichedb, rssamplifier, coinpay, r4ck, readm3).
- You need a dashboard in a terminal rather than a browser.

| Concern | Choice | Notes |
| --- | --- | --- |
| Runtime | Node 20+ (Bun optional) | Node is required: CLIs run in GitHub Actions and on customer machines. Bun is fine for development. |
| Arguments | commander | Subcommands map one to one onto MCP tools. |
| TUI | @profullstack/hqtui | btop-grade dashboards, one import. A mouse must work: one click unfolds, hover highlights. |
| Config | ~/.<tool>.json + @profullstack/synconfig | Allowlisted snapshot synced with the tool's cloud. |
| Install | npm i -g @profullstack/<tool> and curl | sh | The installer does the whole job. Never document a manual follow-up step. |
| Testing | node --test or vitest | bun test on Bun repos; mock.module is process-wide there. |
| Release | GitHub release workflow publishes to npm | Bump before testing. A brand-new scoped package 404s for minutes after publish. |

**Examples:** [@profullstack/hqtui](https://www.npmjs.com/package/@profullstack/hqtui) · [@profullstack/nichedb](https://www.npmjs.com/package/@profullstack/nichedb) · [@profullstack/coinpay](https://www.npmjs.com/package/@profullstack/coinpay) · [@profullstack/readm3](https://www.npmjs.com/package/@profullstack/readm3) · [@profullstack/g1tz](https://www.npmjs.com/package/@profullstack/g1tz) · [@profullstack/r3q](https://www.npmjs.com/package/@profullstack/r3q) · [@profullstack/billing](https://www.npmjs.com/package/@profullstack/billing) · [cli-tools](https://github.com/profullstack/cli-tools)

### Desktop (`desktop`)

Electron, with the product's CLI bundled inside the app. A desktop install gives the CLI too, with no system Node, and the two surfaces cannot disagree because they are the same build.

**Use it when:**

- The product needs a tray, a window, the filesystem or OS input.
- A CLI already exists and the desktop app is a second surface for it.

| Concern | Choice | Notes |
| --- | --- | --- |
| Shell | Electron | Tauri was tried and retired. |
| Inside | Hono or Next, same as the web surface | The renderer is the web app; the main process hosts the API locally. |
| CLI | Bundled via extraResources | The installer writes a shim: ELECTRON_RUN_AS_NODE=1 exec app resources/cli/dist/bin.js. Build the bundle with pnpm deploy --prod --legacy. |
| Native modules | N-API only | Electron's ABI differs from system Node. @libsql/* passes; anything with V8 symbols does not. |
| Distribution | GitHub releases + curl installer | Headless machines get a CLI-only tarball. Homebrew, apt, rpm, scoop and nix repos exist for pairux. |
| Auto-update | From GitHub releases | Set the tool's NO_AUTO_UPDATE env when testing a dev binary. |

**Examples:** [mynaposter](https://github.com/profullstack/mynaposter) · [diskpush](https://github.com/profullstack/diskpush) · [threatcrush](https://github.com/profullstack/threatcrush) · [pairux.com](https://pairux.com) · [nixamp](https://github.com/profullstack/nixamp) · media2markdown · [r4ck.dev](https://github.com/profullstack/r4ck.dev)

### Games (`games`)

Babylon in the browser, with every gameplay rule in a package that cannot import a renderer. The same rules run in the client, in the authoritative match server and in tests, so a rule exists exactly once.

**Use it when:**

- The product is a real-time 3D scene the player acts inside, not a page they read.
- It has to run in a browser first, with the desktop build as a second surface rather than the only one.

| Concern | Choice | Notes |
| --- | --- | --- |
| Renderer | Babylon.js | WebGPU where the browser has it, WebGL2 fallback. The fallback is a supported path, not a degraded one. |
| Physics | Havok via @babylonjs/havok | Only where real collision response is needed; most props are static. |
| Rules | A pure game-core package | No Babylon, no DOM, no Electron imports. This is the rule that makes a client and a server able to agree. |
| UI | Preact, outside the frame loop | The component layer never owns a per-frame transform. HUD readouts are text-node writes behind a change check, not a render pass. |
| Multiplayer | Server-authoritative over WSS | The client sends input intent. The server owns movement validation, damage, death, respawn and score. Shared messages live in their own protocol package. |
| Build | Vite + vite-plugin-pwa | Set registerType and actually wire the update prompt; prompt with no handler means returning players never get a new build. |
| API and data | Hono, Drizzle, Postgres | Same as api-service. Never cache /api, matchmaking or tickets in the service worker. |
| Desktop | Electron | The desktop combo applies unchanged; the renderer is the same web build. |
| Art | Generated by committed Blender scripts | No asset without provenance. One Blender metre is one game metre, GLB with glTF-compatible PBR, COL_ colliders and SOCKET_ attachment points. |

**Notes:**

- Distant point lights and glows are camera-facing sprites held at a fixed screen size, never scaled geometry. A 25 mm firefly is sub-pixel past 30 m and no amount of scaling the mesh fixes that.
- Budget the shell download. Models ship geometry, UVs and a named material slot; the engine binds the real textures by that name so one atlas is not shipped ten times.

**Examples:** [nightcell7](https://github.com/profullstack/nightcell7) · [nightcell7.com](https://nightcell7.com)

### Mobile (`mobile`)

Expo and React Native, as apps/mobile inside the product monorepo. It shares the API client and packages with the web app rather than living in its own repo.

**Use it when:**

- The product needs to be in the app stores or on a phone home screen with native capabilities.
- A PWA is not enough (push, background, camera, payments in-app).

| Concern | Choice | Notes |
| --- | --- | --- |
| Framework | Expo (React Native) | React 19. Shares types and the API client with apps/web. |
| Layout | apps/mobile in the product monorepo | Standalone *-mobile repos are the old pattern and are dormant. |
| Backend | The product's own api-service or web-app | No separate mobile backend. |
| Store release | sh1pt | One codebase to every store, registry and channel. |

**Notes:**

- Start with the PWA. Most products never need this combo.

**Examples:** [threatcrush](https://github.com/profullstack/threatcrush) · [pairux.com](https://github.com/profullstack/pairux.com) · [postammo.com](https://postammo.com) · [reeleel](https://github.com/profullstack/reeleel) · [tronbrowser.dev](https://github.com/profullstack/tronbrowser.dev)

### Library (`library`)

Code that two or more products need becomes a @profullstack/* package. Runtime-neutral core, subpath exports, one npm package per concern, released from GitHub.

**Use it when:**

- You are about to copy a module from one repo into another.
- A site needs a component another site already ships (player, leaderboard, feed submission, contact-form guard).

| Concern | Choice | Notes |
| --- | --- | --- |
| Shape | ESM, TypeScript, subpath exports | `@profullstack/stack/referrals`, `/email`, `/supabase`, `/feedback`, `/coinpay`, `/crawlproof` is the pattern. Peer-depend on next, react and clients rather than bundling them. |
| Core | Web-standard APIs | fetch, Request, Response, URL, crypto.subtle, ReadableStream. Runtime-specific code behind an adapter. A /core entry must never import a node: module. |
| Build | tsup or plain tsc | Node type-stripping needs .ts specifiers; pair with rewriteRelativeImportExtensions so dist still emits .js. |
| Tests | vitest | Contract tests where the package defines a protocol (x402, submit-feed, OpenProfile). |
| Release | Bump, merge, gh release | A release workflow publishes. Ship pkg@latest in docs, never update -g. pnpm 11 refuses packages younger than a day unless excluded from minimumReleaseAge. |

**Examples:** [@profullstack/stack](https://github.com/profullstack/stack) · [@profullstack/x402-gateway](https://github.com/profullstack/x402-gateway) · [@profullstack/throttle](https://github.com/profullstack/throttle) · [@profullstack/player](https://github.com/profullstack/player) · [@profullstack/modern-css](https://github.com/profullstack/modern-css) · [@profullstack/leaderboard](https://github.com/profullstack/leaderboard) · [@profullstack/form-guard](https://github.com/profullstack/form-guard) · [@profullstack/submit-feed](https://github.com/profullstack/submit-feed)

### Systems (`systems`)

Rust when the product is a single static binary that has to be fast (benchmarks, transports, agents on servers). Go when the upstream ecosystem is Go. Python only for security tooling that lives in that world.

**Use it when:**

- A JavaScript runtime would be the bottleneck or the dependency you cannot ship.
- The upstream you build on is in that language (LiveKit for agentbbs, nmap and Kali tooling).

| Concern | Choice | Notes |
| --- | --- | --- |
| Rust | tokio, axum, clap, reqwest | c0mpute is the reference. Auto-update from GitHub releases on first run. |
| Go | Standard library + the upstream SDK | agentbbs pins livekit server-sdk-go and protocol together. |
| Python | Managed by mise, venv per project | Security tooling and GitHub Actions only (vu1nz). |
| Distribution | GitHub releases, curl installer, homebrew tap | Same installer rule: it does the whole job. |

**Examples:** [c0mpute](https://github.com/profullstack/c0mpute) · [agentbbs](https://github.com/profullstack/agentbbs) · [fiche-agentic](https://github.com/profullstack/fiche-agentic) · [vu1nz.com](https://vu1nz.com) · [kali](https://github.com/profullstack/kali)

## 4. House rules

- **Ship it, never stop at in progress.** An agent does not end its turn on "still running, I will report when it lands". Work handed to a subagent, CI or a deploy is driven to merged, released and verified live in the same turn, then reported once with the result. Stop early only for a real blocker a person must clear: a login, or a decision that is theirs.
- **Every site takes payment from launch.** Launching a site includes taking crypto: npx @profullstack/coinpay-onboard site <name> --webhook <public url> makes its CoinPay business, copies the payout wallets in, sets the webhook and writes the COINPAY_* keys into the site vault. Idempotent; every step must print a check before the launch is announced.
- **Launch on a Moshpit name.** New products launch on a Moshpit name (pit.moshcode.sh), not a new ICANN domain, served from our own box with a registry-signed certificate and listed on the Moshpit ring. Announcements give the <name>.pit.world address for browsers without Moshpit DNS.
- **Reuse the house package first.** Before adding a dependency or writing a component, grep the repo for @profullstack/ and check npm. The package usually exists and is often already installed.
- **Secrets live in the vault.** Set production secrets on the Railway service and record them in the logicsrc team vault. Never write one into a .env in the repo, and never ask a person to.
- **Auth is magic link plus passkeys.** The link proves the address and the address is the account. Passwords are optional and only for devices that cannot do either.
- **Installers do the whole job.** If a feature needs a component, the installer or update command installs it. No documented manual follow-up step. DNS routing is the one thing that stays explicit.
- **Push to the default branch deploys.** PRs are merged, not parked. Release after merge. Then announce through myna, with rel=canonical on every syndicated copy.
- **Our domains only.** Add the custom domain before writing any URL down. Never publish a *.up.railway.app address.
- **Migrations run twice.** Web and worker both migrate on boot. Ledger writes are insert-or-ignore and every migration is safe to apply concurrently.
- **Large catalogues use a sitemap index.** /sitemap.xml is an index; entities are chunked by month of creation so past files never change.
- **OAuth callbacks are namespaced.** /api/v1/<provider>/<function>/<endpoint>, using whatever API prefix the project already has.
- **Every product is a customer of another.** Wire products together when the integration is load-bearing: x402 settles through CoinPay, blogs open CrawlProof ads, myna distributes every ship, NicheDB sells the data.
- **Copy has no LLM tells.** Short sentences, no em dashes, no rule-of-three flourishes. This applies to posts, READMEs and announcements.
- **A wedged process restarts without a person.** Every container gets a HEALTHCHECK that hits its own /healthz, so a blocked event loop shows as unhealthy. watchdog-autoheal restarts what Docker marks unhealthy, three times an hour at most, then emails. In-process, watchDependencies exits when the shared DB or Redis client stops answering.
- **Agents get a first-class surface.** A site ships its data as Markdown or JSON at a stable URL, a CLI ships an MCP bridge, and training crawlers pay through x402 rather than being blocked.

## 5. Reuse these packages before writing anything

All published under `@profullstack/*` on npm. Check `grep -r "@profullstack/" package.json` in the repo first: the package is often already installed.

| Package | What it is |
| --- | --- |
| `@profullstack/coinpay-onboard` | Take crypto on CoinPay, set up in one pass: Sign in with CoinPay helpers, an idempotent onboard() (business, payout wallets, webhook), webhook verification, and the `site` launch step that writes COINPAY_* keys into the vault. Powers pay.agent. |
| `@profullstack/stack` | Shared modules for Next apps: referrals, email, supabase, feedback widget, coinpay, crawlproof. Used by 37 repos. |
| `@profullstack/x402-gateway` | Sell crawl access to AI training crawlers by the day over x402, settled by CoinPay. Next and Hono adapters, generated robots.txt. |
| `@profullstack/x402-client` | Pay x402 402s from JavaScript with a local key: fetch, CLI, adapters for axios and got. |
| `@profullstack/throttle` | App-wide rate limit whose answer to going over is a price, not a 429. |
| `@profullstack/coinpay` | CoinPay SDK and CLI: crypto payments, x402 verify and settle, finances TUI. |
| `@profullstack/watchdog` | Restart instead of hanging. In-process probes for a wedged DB or Redis client, plus watchdog-autoheal, which restarts the containers Docker marked unhealthy within a restart budget. |
| `@profullstack/emailer` | Mass email over the Resend batch API with SMTP fallback. |
| `@profullstack/autoblog` | CloudEvents and Standard Webhooks SDK for publishing posts to the blogs. |
| `@profullstack/hqtui` | Terminal UI for TypeScript: btop-grade dashboards from one import. |
| `@profullstack/player` | One web player for MP4, HLS, MPEG-TS and audio with one control bar. Knows that Chrome lies about native HLS. |
| `@profullstack/modern-css` | Modern CSS as opt-in classes and @function helpers: subgrid cards, squircles, stuck headers, gap rules, height:auto accordions. Falls back cleanly where unsupported. |
| `@profullstack/multiview` | Several live streams on one screen, driven by mouse, finger or TV remote. |
| `@profullstack/leaderboard` | Public leaderboard with badges, streaks and a commission ladder for any site. |
| `@profullstack/notifications` | Web push for any app: VAPID keys from env, subscribe from the page, one service worker handler. |
| `@profullstack/referrals` | Referral codes, links, discounts and commission, with React and Next adapters. Bring your own store. |
| `@profullstack/orgs` | Orgs, teams, members, roles and invites for Postgres. Brings no users table and owns its schema through migrate(). |
| `@profullstack/partners` | Let the people whose work is in your dataset sell it: signup, domain verification, payouts. |
| `@profullstack/form-guard` | Contact-form spam stopped with a signed proof-of-render token, not a captcha. |
| `@profullstack/submit-feed` | One way to add a feed to a directory, shared by rssamplifier and p0dcasters. |
| `@profullstack/scraper-daemon` | The updater daemon every listing site runs: periodic jobs, per-item refresh queues and resumable bulk pipelines, with robots.txt, per-host serial fetching, 429 hold-back, SSRF checks and SQLite or Postgres state. Runs on search.peptides, ch4nnels.com, r4ck.dev, rssamplifier.com and p0dcasters.com. |
| `@profullstack/openprofile` | Read, write, merge and de-duplicate OpenProfile.md documents. |
| `@profullstack/synconfig` | Sync a tool's config files with its cloud: allowlisted snapshot, digest, optimistic replace. |
| `@profullstack/billing` | Clients, rates and invoices from the terminal; integer money. |
| `@profullstack/timer` | Time tracker for the terminal and for agents. |
| `@profullstack/nichedb` | CLI and MCP bridge for NicheDB collections, sources and feeds. |
| `@profullstack/rssamplifier` | CLI for the feed directory: search, OPML export, submit. |
| `@profullstack/r4ck` | CLI and MCP bridge for the hosting search engine. |
| `@profullstack/media2md` | Turn any video, audio file or book into a chaptered Markdown bundle for an LLM. MCP server available. |
| `@profullstack/mcp-server` | Generic modular MCP server. |
| `@profullstack/sh1pt` | One codebase to every store, registry, CDN and channel. |

### Drop-in wiring

**@profullstack/coinpay-onboard**

```sh
npm install @profullstack/coinpay-onboard
```

```js
npx @profullstack/coinpay-onboard site <name> --webhook <url>
```

**@profullstack/x402-gateway**

```sh
npm install @profullstack/x402-gateway
```

```js
import { createGateway } from '@profullstack/x402-gateway';
import { x402Gateway } from '@profullstack/x402-gateway/hono';
export const gateway = createGateway({ siteUrl: process.env.SITE_URL ?? '', coinpay: { apiKey: process.env.COINPAY_X402_KEY }, payTo: process.env.CRAWL_PAY_TO });
export const crawlGateway = x402Gateway(gateway); // app.use('*', crawlGateway)
```

**@profullstack/x402-client**

```sh
npm install @profullstack/x402-client
```

```js
import { createClient } from '@profullstack/x402-client';
export const payer = createClient({ key: process.env.X402_PRIVATE_KEY, maxUsd: 5 });
// const res = await payer.fetch(url); pays a 402 once, then presents the pass
```

**@profullstack/throttle**

```sh
npm install @profullstack/throttle
```

```js
import { createThrottle } from '@profullstack/throttle';
export const throttle = createThrottle({ limit: 100, rules: [{ path: '/health', open: true }] });
// const answer = await throttle.handle(request); if (answer) return answer;
```

**@profullstack/coinpay**

```sh
npm install @profullstack/coinpay
```

```js
import { CoinPayClient } from '@profullstack/coinpay';
export const coinpay = new CoinPayClient({ apiKey: process.env.COINPAY_API_KEY ?? '' });
// await coinpay.createPayment({ businessId, amount, currency: 'USD', blockchain })
```

**@profullstack/watchdog**

```sh
npm install @profullstack/watchdog
```

```js
import { watchDependencies } from '@profullstack/watchdog';
// Pass probes, not clients: postgres resolves truthy, redis answers PONG. Call stop() first on SIGTERM.
export const startWatchdogs = (probes: Parameters<typeof watchDependencies>[0]) => watchDependencies(probes);
// startWatchdogs({ postgres: () => healthcheck(), redis: () => redis.ping() })
```

**@profullstack/emailer**

```sh
npm install @profullstack/emailer
```

```js
import { createEmailer } from '@profullstack/emailer';
export const emailer = createEmailer({ resendApiKey: process.env.RESEND_API_KEY });
// await emailer.send({ from, to, subject, html, text })
```

**@profullstack/autoblog**

```sh
npm install @profullstack/autoblog
```

```js
import { buildEvent, sendWebhook, verifyAndParse } from '@profullstack/autoblog';
export { buildEvent, sendWebhook, verifyAndParse };
// sendWebhook(url, buildEvent(post, { source: SITE_URL }), { secret: process.env.WEBHOOK_SECRET })
```

**@profullstack/hqtui**

```sh
npm install @profullstack/hqtui
```

```js
import { createApp } from '@profullstack/hqtui';
export const tui = await createApp();
// tui.render(({ ui }) => ui.panel({ title: 'Hello' }, (p) => p.text('Hello'))); await tui.start();
```

**@profullstack/player**

```sh
npm install @profullstack/player
```

```js
import { createPlayer } from '@profullstack/player';
import '@profullstack/player/player.css';
export const mountPlayer = (el: HTMLElement, src: string) => createPlayer(el, { src });
```

**@profullstack/modern-css**

```sh
npm install @profullstack/modern-css
```

```js
import '@profullstack/modern-css';
// <ul class="subgrid-cards" style="--card-rows: 3"><li class="subgrid-card squircle">...</li></ul>
// h1 { font-size: 3.6rem; font-size: --fluid(2.6rem, 3.6rem); }
```

**@profullstack/leaderboard**

```sh
npm install @profullstack/leaderboard
```

```js
import { createLeaderboard, sqlStore } from '@profullstack/leaderboard';
export const createBoards = (execute: (q: { sql: string; args: unknown[] }) => Promise<{ rows: Record<string, unknown>[] }>) =>
  createLeaderboard({ siteName: process.env.SITE_NAME ?? '', siteUrl: process.env.SITE_URL ?? '', store: sqlStore({ execute }), boards: { top: { label: 'Top', metric: 'points' } } });
```

**@profullstack/notifications**

```sh
npm install @profullstack/notifications
```

```js
import { vapidKeysFromEnv, sendPushToMany } from '@profullstack/notifications/server';
export const vapidKeys = vapidKeysFromEnv(); // VAPID_PUBLIC_KEY + VAPID_PRIVATE_KEY
export { sendPushToMany };
```

**@profullstack/referrals**

```sh
npm install @profullstack/referrals
```

```js
import { createCode, buildReferralUrl, applyReferral, calculateReferral } from '@profullstack/referrals';
export { createCode, buildReferralUrl, applyReferral, calculateReferral };
// createCode(userId, store) needs a ReferralStore wired to your database
```

**@profullstack/orgs**

```sh
npm install @profullstack/orgs
```

```js
import { migrate, createOrg, addMember, can, inviteToOrg, acceptInvite } from '@profullstack/orgs';
export { migrate, createOrg, addMember, can, inviteToOrg, acceptInvite };
// await migrate(sql) on boot, with a postgres.js client
```

**@profullstack/form-guard**

```sh
npm install @profullstack/form-guard
```

```js
import { createFormGuard } from '@profullstack/form-guard';
export const formGuard = createFormGuard({ secret: process.env.FORM_GUARD_SECRET ?? '', binding: 'contact' });
// const verdict = await formGuard.check({ fields: body, headers: request.headers });
```

**@profullstack/scraper-daemon**

```sh
npm install @profullstack/scraper-daemon
```

```js
import { createDaemon, sqliteStore } from '@profullstack/scraper-daemon';
export const daemon = createDaemon({ name: 'my-site', store: sqliteStore(db) });
// daemon.job({ name, every, run }), daemon.queue({ name, every, items, run }), daemon.start()
```

## 6. Not in the stack

- **Hetzner:** Ruled out permanently. Railway hosts the fleet; a netcup box and DigitalOcean droplets cover what needs a VM.
- **Vercel, Fly.io, Cloudflare Workers:** Not deploy targets. One repo has a fly.toml and none have a wrangler config. Railway is the host.
- **Supabase for a new app:** Turso is the default. Supabase and Postgres stay where they already are.
- **.env files as the source of secrets:** The vault and the platform env are the authority. A file is a stale copy.
- **Password-first auth, next-auth:** Magic link plus passkeys. @profullstack/auth-system is password-only and is the exception, not the pattern.
- **SvelteKit, Primate + SurrealDB, Express for new work:** Earlier generations still in maintenance. Do not start anything new on them.
- **Tauri:** Retired in favour of Electron with the bundled CLI.
- **mocha, jest, Prisma:** vitest and plain SQL or Drizzle.
- **Oxc, Oxlint, Oxfmt, Rolldown as a default:** On the roadmap since June and present in six repos. Use the repo's existing lint and format setup until parity is proven.
- **Hand-rolled players, rate limiters, contact-form guards, feed forms:** Each of these is a published package already.
- **video.js, plyr, a bare hls.js or mpegts.js:** @profullstack/player wraps hls.js and mpegts.js already. video.js 10 ships no player at all: it throws VJS8_LEGACY_* on v8 code.
- ***.up.railway.app URLs:** Our domains only.

## 7. Contact

Profullstack, Inc. · anthony@profullstack.com · https://profullstack.com