Skip to content
BoringStack
Star

What's new

8 min read

A log of substantial changes to the docs, templates, and tooling. For per-commit detail, see the git history of each workspace app. For released images, see the Image updates runbook (Compose) and Production releases (k3s).

  • The root pre-push hook runs the secret scan, each changed app’s bun run check, the UI tests for changed files, shared packages and the static Compose checks. Full suites, builds, budgets and scanners are the pull request’s required checks. FULL_PREPUSH=1 git push runs the whole gate locally.

Template fixes from the first product’s code

Section titled “Template fixes from the first product’s code”

A diff of every template file the first product changed found bugs it had to fix.

  • Billing. Pro grants its features from one typed plan catalog. Checkout refuses a second subscription and reuses an open session. A delayed payment no longer activates a plan. The plan list is public, and an optional yearly price is supported. See Billing.
  • Sessions. Reloading after the access cookie expires refreshes the session instead of logging out. A revoked refresh cookie is cleared, and the first write after a refresh keeps its request body.
  • CI in private repositories. Every workflow that uses dorny/paths-filter grants pull-requests: read, enforced by lint-meta. Without it, every pull request check fails in a private repository.
  • Shared packages in images. packages/* reaches the API and UI images through a BuildKit build context and the dev containers through a read-only mount.
  • Split layout on Compose and OpenTofu. The public site is on the apex (https://<domain>) and the app is on https://app.<domain>. WITH_SITE is on in dev and prod. Set PUBLIC_SITE_HOST, PUBLIC_UI_HOST=app.<domain>, SITE_CONTACT_EMAIL and a pinned SITE_IMAGE_TAG in prod. OpenTofu creates an app DNS record and outputs site_url, app_url and api_url. Set WITH_SITE=0 to keep the single-domain layout. See Public site and Deployment.

Lessons from the first product (Tinkercaster)

Section titled “Lessons from the first product (Tinkercaster)”

A first product built on the template reported where the template slowed it down or let problems through. The fixes are tracked in the repository’s product feedback ledger.

  • Coordinated production release (k3s). One workflow builds the API, migrations, UI and public site for a commit and pins all four digests in one GitOps commit. The Argo Application no longer uses argocd-image-updater. The migration Job runs db:migrate only, as a Sync hook, and the API and migration roots are read-only. See Production releases.
  • Public marketing site. New apps/site, an Astro static site on the apex domain with a Markdown blog, consent-gated analytics and an nginx image. The app moves to app.<domain>. Local dev is on :7333, and WITH_SITE is on by default in dev and prod. See Public site.
  • Business metrics. CloudNativePG runs aggregate queries over sign-ups, active users, plans, cancellations and Stripe events, with a Grafana dashboard. Only aggregates leave the database. See Observability.
  • Conventional Commits gate. Commit subjects and PR titles are checked by the commit-msg hook and the pr-title workflow. See Agent docs.
  • Shared packages. packages/* workspaces are discovered by bun run check and the pre-push hook. See Repository layout.
  • Bundle budget reasons. A raised UI budget or a new budget entry needs a recorded reason in apps/ui/budgets.md. See Lint as the contract.
  • Self-hosted CI runners. CI_RUNNER moves jobs to self-hosted runners. Fork pull requests always stay on GitHub-hosted runners, and a lint-meta rule enforces that guard. See Security pipeline.
  • Structured verification. Feature runs record new test-inventory cases automatically. Removed cases still need an explicit acknowledgement. See Verified workflow.
  • The API security specification now gates the behaviors covered by 22 fixed findings, with positive controls and per-case manifest reconciliation.
  • Authentication now documents browser-bound OAuth, OAuth MFA and refresh-family replay handling. The rollout runbook covers the lineage migration and mixed-writer limits.
  • Billing and ACL document effective entitlement expiry, immediate loss of plan features on past_due, and transactional seat admission. Notification delivery and SSE lifetime boundaries are documented in Notifications.
  • Structured verification adds owned disposable services, explicit synchronization, named-test inventories and pass/fail/blocked evidence.
  • The optional account-resource generator supplies an explicit tenant/role policy. A separate Projects evaluator checks known-good behavior and deliberate defects; no live-agent benchmark is claimed.
  • Account switching resets cached data before refetching under the new account. Tooling now follows the API’s strict script lint, typecheck and formatting policy.
  • Cost calculator on Why BoringStack. Four-stage tier picker with three solution categories (BoringStack VPS, Managed-PaaS bundle, Hosted SaaS platform). Numbers cite public rate cards; methodology lives on its own reference page.
  • Decision log shipped. Twelve ADR-style entries covering every “boring” pick (Postgres, Valkey, Bun + Elysia, Drizzle, Compose, Traefik, Cloudflare Tunnel, OpenTofu, Astro for docs, Bun everywhere, architecture-as-lint, OpenAPI boundary, React, Mailpit, GlitchTip, WUD notify-only).
  • Recipes section added to the sidebar with four how-tos: Add Stripe Checkout, Add S3-compatible uploads, Add a background job, Add a service to Compose. Each follows the same Goal / Prereqs / Steps / Verify / What changes in code shape.
  • “What you’ll have in 10 minutes” deliverables callout at the top of Quickstart so readers see the outcome before the steps.
  • llms.txt + llms-full.txt + llms-small.txt now publish so AI assistants (Claude, ChatGPT, Perplexity, Cursor) can discover and consume the docs cleanly. Generated via starlight-llms-txt at build time.
  • Broken-link CI workflow added at .github/workflows/docs-linkcheck.yml. Runs lychee against the built site on every PR; fails on broken internal links, warns on flaky external 4xx/5xx.
  • Glossary links on first use. Three high-traffic terms (overlay, feature folder, view object) now link to the Glossary on first prose use across the docs. Anchors stable per term.
  • Reading time on every page. Each docs page now displays an estimated read time pill below the title, computed from the page body at build.
  • Related navigation on every page. Twelve pages that previously dead-ended (overview pages, runbooks, topics, reference) now end with a ## Related block linking 3–5 adjacent pages.
  • Changelog & 404. This page, plus a custom 404 with suggested starting points and a search hint.
  • Emerald accent migration. Site accent moved from amber #fbbf24 to emerald #4ade80 across Starlight tokens, custom CSS, Mermaid theme variables, the landing hero gradient, badges, and asides. Tip badges and asides reassigned to cyan so they stay distinct from the brand green; caution keeps amber for semantic warnings.
  • Amber accent migration. Site accent moved from violet #8b5cf6 to amber #fbbf24 across Starlight tokens, custom CSS, Mermaid theme variables, the landing hero gradient, badges, and asides. Light-mode contrast tuned to amber-600 / amber-950 ink.
  • Server-rack icon. Header logo and favicon replaced with a sharp, minimalistic server/rack SVG.
  • Mermaid restyle. Diagrams adopted the amber + cyan + pink brand palette with gradient borders and per-element accents.
  • Homepage rewrite. Splash hero, CTAs, fit-check table, and comparison row against managed-PaaS bundles. The 3-layer architecture diagram moved closer to the entry point.
  • Quickstart slimmed. The first-deploy production checklist moved to Deployment so Quickstart stays a five-minute path.
  • Lint as the contract restructured from a plugin catalog into a narrative: problem, solution, feature grid, then the plugin inventory underneath.
  • ACL & multi-tenant docs. Server-authoritative permissions and the accountId scoping primitive each got their own page.
  • Memory context docs. New page covering the memory layer in the API template.
  • Security pipeline docs. osv-scanner, gitleaks, and CodeQL wiring explained alongside the supply-chain protections (seven-day minimum release age across all repos).
  • Agent docs as an index. AGENTS.md is now a navigation table over docs/agents/; the docs site mirrors the same shape.
  • @boring-stack-pkg namespace. All custom ESLint plugins moved to the @boring-stack-pkg/* npm scope; docs and lint configs updated in lockstep.

Listed for honesty so the gap is visible, not buried in commit history.

  • Per-page OG images. Attempted with astro-og-canvas (Satori-based); blocked by a Cloudflare-adapter incompatibility (__dirname is not defined inside the worker bundle when canvaskit-wasm loads). Picking this back up means either a static OG generator that works in Cloudflare Workers or moving the doc site off the Cloudflare adapter for the OG generation step.
  • Asciinema cast on Quickstart. Needs an actual ~90-second recording of ./scripts/compose-up.sh going from a clean clone to a working dashboard. Record once with asciinema rec, upload to asciinema.org, embed via <asciinema-player>. Until that exists, the “What you’ll have in 10 minutes” callout substitutes for the visual proof.
  • Star the boringstack-xyz GitHub org to surface releases in your feed.
  • Check the Image updates runbook for how the WUD overlay can notify you when new container images are published.