Files
HiveGrid-Wireframes/hivegrid-cloud/docs/porting-guide.md
T

15 KiB

Documentation Porting Guide

Purpose and Scope

This guide is the canonical rename and replacement map for porting inherited boilerplate documentation to the current generic boilerplate documentation set. It is for documentation updates only: use it to update prose, examples, tables, diagrams, and verification notes in docs, but do not use it as authority to rename runtime imports, package exports, queue names, database identifiers, or historical decision records.

The current web runtime source lives under apps/web/app and apps/web/public. Root scripts still provide the top-level developer entrypoints, while apps/api, apps/worker, and selected packages/* boundaries document or host target extraction surfaces. Documentation should describe the current state precisely instead of implying that every package boundary is fully runtime-wired.

Source Evidence

Use these source files as the confirmed baseline for this guide:

  • README.md: current quick start, package manager, runtime commands, database setup, worker Redis note, CI summary, and manual E2E policy.
  • docs/architecture-migration-status.md: authoritative boundary status for root runtime, apps/*, packages/*, runtime-wired surfaces, skeleton-only surfaces, UrlUtils migration notes, and feature-pruning interpretation.
  • docs/feature-inventory.md: current pruned-core, plugin-candidate, and remove-candidate classifications for downstream feature documentation.
  • scripts/verify-porting-docs-baseline.mjs: Porting Docs documentation inventory roots and terms that the baseline scanner already tracks.
  • .tc/baselines/porting-docs/summary.md: baseline-health handoff and report location .tc/baselines/porting-docs/baseline-health.md.

Downstream documentation slices should compare their proposed edits against the baseline report and explain whether remaining legacy terms are intentional historical references, protected runtime identifiers, or newly introduced drift. Use docs/porting-verification.md as the final post-port documentation checklist before closing downstream porting work.

Rename/Replace Map

Legacy or ambiguous source term Preferred documentation term Apply in docs when Notes and examples
SaasRock, SaasRock Boilerplate, saasrock Current boilerplate wording Product, project, setup, architecture, and roadmap prose that describes the current repository. Keep historical references only when naming an archived upstream source or old decision context.
saasrock.com, www.saasrock.com, SaasRock marketing domains Neutral local/example domain wording Domain examples, mail examples, deployment examples, and screenshots that should represent the current project. Prefer app.localhost:3000 and admin.localhost:3000 for the default web dev loop; use api.localhost:3001 only when the standalone API runtime is started separately. Use example.com / app.example.com for tenant-safe examples unless a deployment-specific domain is explicitly documented.
SaasRock LLC, old SaasRock legal branding, old trademark/legal wording Current project/legal owner wording or neutral placeholder Legal, privacy, imprint, footer, and branding documentation. Do not invent legal claims. If ownership is unknown, use a placeholder and mark the document as needing legal review outside the code task summary, not with inline TODO markers.
Product-brand variants in prose Generic boilerplate wording Human-readable product or brand references. Keep actual package names, queue names, runner labels, and other runtime identifiers unchanged.
Root package display names inherited from old boilerplate toolctrl-boilerplate Documentation that names the root package.json project. Confirm against root package.json before changing package-manager or script examples.
Generic SaaS boilerplate where it means this repository Current boilerplate Repository-specific docs, quick-start text, architecture handoffs, and migration plans. Keep generic SaaS only when the sentence describes the product category rather than the repository name.
Old monolith wording that implies all runtime code is root-only apps/web web source plus workspace boundaries Architecture docs and migration status docs. State that apps/web/app owns web source while root scripts keep top-level command compatibility and apps/api, apps/worker, and selected packages/* provide target or runtime-wired boundaries.
Remix runtime wording where it describes current root app execution React Router runtime Current runtime commands, build, route, and app-shell descriptions. Preserve remix-i18next and dependency names when referring to actual package names.
npm, yarn, unpinned package-manager examples pnpm with Corepack and pinned pnpm@10.33.0 Setup, CI, and local verification commands. README confirms corepack enable, corepack prepare pnpm@10.33.0 --activate, and pnpm install.
Root-only database ownership wording packages/db boundary plus root Prisma schema/migrations DB architecture and migration docs. Current state: packages/db owns the server-side Prisma client boundary and command surface, while schema and migrations still physically live under prisma/.
Broad database provider examples that imply multiple active providers PostgreSQL through Prisma, with Supabase only as an example connection target Setup and deployment docs. README names PostgreSQL as default and gives a Supabase-style PostgreSQL URL example. Do not imply a second ORM or active non-Postgres provider.
Generic Redis requirement for all local development Optional worker Redis Quick start and worker docs. WORKER_ENABLED=true and BULLMQ_REDIS_URL are only required when running the worker; REDIS_URL is a platform-binding fallback.
Mail providers such as Postmark when describing active transactional mail Mailjet transactional mail boundary Mail setup, architecture, and feature inventory docs. packages/mail provides the Mailjet adapter and MailProvider contract. Historical provider comparisons may remain if clearly labelled historical.
Email as a product/marketing feature transactional mail for core mail, Email Marketing as plugin candidate Feature classification docs. Core keeps password reset, invitations, and system mail; Email Marketing is a plugin-candidate product surface.
Full-boilerplate retention language Pruned core with plugin candidates and removal candidates Roadmap, feature inventory, and migration overview docs. docs/feature-inventory.md is the current classification source.
Claims that plugin candidates are already extracted plugins Plugin-candidate or extraction target Feature docs, architecture docs, and roadmap docs. Use plugin-candidate unless the code has actually moved and the slice verifies the new boundary.
Claims that remove candidates are supported legacy behavior Remove-candidate or pruning target Feature inventory and feature decision docs. R003 means replacement/removal, not permanent compatibility adapters.
Vercel-only or generic hosted deployment wording Current CI/deployment wording with Gitea, Docker smoke, Coolify, and documented deploy guides CI and deployment docs. README confirms Gitea CI, Docker smoke gates, docs/deployment.md, and docs/deployment-porting.md.
Registry-push or production-deploy claims in baseline CI Local Docker smoke validation only CI docs for this milestone. The baseline Docker smoke job validates build/configuration without registry login, image push, artifact publishing, deployment, or browser/E2E flows.
Broad E2E runs by default language E2E/browser verification is manual unless explicitly approved Verification sections and CI docs. Auto-mode docs should name non-E2E checks and mark browser/E2E as manual.
apps/web as skeleton-only apps/web active web source home Workspace and architecture docs. The physical React Router app source and public assets live under apps/web; root-level app/ is not the active tree.
apps/api as health-only or fully extracted API apps/api runtime-wired Hono API app with temporary proxy exceptions API architecture docs. It owns the canonical /v1 route surface, route-access inventory, and OpenAPI docs. Some /v1 routes proxy web-owned internal handlers until service extraction, so docs must name both boundaries when relevant.
apps/worker as always-on production worker Opt-in worker runtime with queue-group processors Worker and queue docs. The worker exits unless WORKER_ENABLED=true; current processors are wired by WORKER_QUEUE_GROUP for general, mail, import, webhook, and plugin workloads.
packages/config, packages/queue, packages/ui, packages/shared as fully wired runtime packages Skeleton-only or contract package surfaces Package and architecture docs. Describe their current contract status precisely.
Public form/portal/site URLs as tenant-app routes Separate public URL boundaries UrlUtils and routing docs. Do not normalize public slugs or share URLs through internal tenant-app helper wording.
Direct tenant-app path concatenation as desired pattern UrlUtils helper migration target Internal routing migration docs. Use UrlUtils.getModulePath(...) or documented helper plans for internal tenant-app links; public URLs are separate.

Do-Not-Replace Rules

Do not blindly rename the following public, runtime, package, or historical identifiers while porting documentation:

  • @toolctrl/* workspace imports and package names, including @toolctrl/config, @toolctrl/db, @toolctrl/mail, @toolctrl/queue, and @toolctrl/ui.
  • Root package and workspace package names that are confirmed by package.json files, including toolctrl-boilerplate.
  • Queue names and runtime strings such as toolctrl.email when they represent actual queue identifiers or integration contracts.
  • Environment variable names such as APP_NAME, SESSION_SECRET, CRYPTO_SECRET, DATABASE_URL, DIRECT_URL, WORKER_ENABLED, BULLMQ_REDIS_URL, and REDIS_URL.
  • Database, Prisma, migration, and generated-client paths such as prisma/, prisma/schema/schema.prisma, packages/db/generated/prisma/client, and @toolctrl/db/client.server.
  • Current local examples that are still accurate, especially app.localhost:3000 and admin.localhost:3000 for the default web loop, api.localhost:3001 only for the standalone API runtime, 127.0.0.1, seeded users such as admin@email.com, and sample passwords used only in local seed documentation.
  • Third-party product names that describe actual dependencies or providers, including Prisma, PostgreSQL, Supabase-style PostgreSQL URLs, Redis, BullMQ, Mailjet, Hono, React Router, Gitea, Docker, Fly.io, Vercel, AWS Lightsail, and Coolify.
  • Historical decision/report references, milestone IDs, slice IDs, decision IDs, and files under .tc/ or docs/feature-decisions/ unless a task explicitly updates those records.
  • Public route shapes and user-facing slugs in examples when the document is explaining public boundaries, for example public forms, portals, sites, help pages, or share links.

Doc-Specific Application Notes

README and quick-start docs

  • Keep the quick start centered on Corepack, pnpm@10.33.0, .env, Prisma setup, seed data, and pnpm dev.
  • Preserve the distinction between required database settings and optional worker Redis settings.
  • Prefer app.localhost:3000 and admin.localhost:3000 for the default web dev loop; use api.localhost:3001 only when the standalone API runtime is started separately.
  • Do not add browser/E2E execution as an automatic task-level check; label it manual unless a later human-approved verification plan says otherwise.

Architecture and migration docs

  • Describe boundary status in present tense and distinguish runtime-wired, partially runtime-wired, skeleton-only, and source-only surfaces.
  • Keep the split clear: apps/web/app owns web source, while root scripts still expose the top-level developer command surface.
  • For packages/db, say the package owns the server-side Prisma client boundary and commands, while root Prisma schema and migrations still live under prisma/.
  • For packages/mail, say Mailjet is the active transactional mail provider boundary.
  • For packages/queue, say BullMQ contracts exist but production wiring is not complete unless a later task proves otherwise.

Feature inventory and pruning docs

  • Use the pruned-core classification from docs/feature-inventory.md as the source of truth.
  • Keep Auth, Accounts, Tenants, Admin/Tenant shell, DB/ORM, transactional mail, Billing, i18n, and UI primitives described as core surfaces.
  • Describe CRM, Email Marketing, Workflow Engine, Knowledge Base, Portals/Sites, Forms/Surveys, Analytics/Metrics, Events/Webhooks/Audit Trails, No-code Entity Builder, AI/Chatbot/Prompt Builder/MCP, Help Desk, Onboarding Builder, Feature Flags, and Widgets as plugin candidates or review/removal targets according to the inventory.
  • Do not imply optional product areas are already extracted unless the relevant code and tests have moved.

Deployment and CI docs

  • Align CI prose with the active Gitea pipeline summary from README.md and the baseline gate runner.
  • Treat pnpm run verify:ci-baseline and pnpm run verify:gitea-ci-workflow as static local verification commands for the baseline CI contract.
  • Explain Docker smoke as local image/build, web artifact validation, web/api/worker runtime smoke, and compose validation, not registry publishing or production deployment.
  • Keep baseline CI wording separate from the deploy workflow: baseline CI Docker smoke does not push or deploy, while .gitea/workflows/deploy.yml publishes full-SHA staging images, updates the staging alias, triggers Coolify staging, and promotes verified staged images to the production main alias through workflow_dispatch.

Provider and runtime wording

  • Use PostgreSQL and Prisma for the active database stack.
  • Use Mailjet for transactional mail provider wording.
  • Use BullMQ and Redis only where worker/queue behavior is being described.
  • Use React Router for the current @toolctrl/web runtime under apps/web/app.
  • Use Hono for the apps/api runtime-wired API app.

Verification

Use these exact non-E2E checks after creating or editing this guide:

test -s docs/porting-guide.md
grep -n "^## Rename/Replace Map" docs/porting-guide.md
grep -n "^## Do-Not-Replace Rules" docs/porting-guide.md
grep -n "^## Verification" docs/porting-guide.md
node -e "const fs=require('fs'); const text=fs.readFileSync('docs/porting-guide.md','utf8'); const banned=/\\b(TODO|TBD|FIXME|XXX)\\b/; if (banned.test(text)) { console.error('unresolved marker in docs/porting-guide.md'); process.exit(1); }"

Manual downstream review: after each documentation slice ports another file, compare remaining legacy terms against this map and the baseline inventory report at .tc/baselines/porting-docs/baseline-health.md. Any remaining old brand, provider, domain, package, database, runtime, or deployment wording should be classified as intentionally protected, historically accurate, or changed in the same documentation slice.