internal/planning/3357-react-on-rails-starter-2026-implementation.md
Status: Draft — 2026-05-22. Ready for AI-sub-agent execution after Phase 0 spike confirms stack compatibility. Parent plan: 3357-react-on-rails-starter-2026.md Tracking issue: https://github.com/shakacode/react_on_rails/issues/3357
This document is the executable companion to the strategic plan. Each task is scoped for a single AI sub-agent session (~15–45 min CC time), with explicit inputs, outputs, acceptance criteria, and dependencies. Tasks within the same phase are parallel-safe unless their Depends on: lines say otherwise.
If you're a coordinator or sub-agent picking this up cold on a fresh machine:
internal/planning/3357-react-on-rails-starter-2026.md (strategic plan — what we're building and why)SPIKE.md with a GREEN / AMBER / RED verdict.SPIKE.md lands GREEN, dispatch Phase 1 immediately. If AMBER, apply the named fallback decision tree (see the strategic plan's Required-Before-Implementation #3) and dispatch Phase 1 with the fallback in place. If RED, stop and escalate to Justin.Repo location for the spike: a new throwaway local branch (spike/starter-tanstack-stack-validation) on the existing react_on_rails repo. Do NOT create the public react-on-rails-starter-tanstack repo until T1.1 (after the spike passes).
Format: T<phase>.<number> — e.g. T2.4 is Phase 2, Task 4. IDs are stable; never renumber. New tasks get the next available number in their phase.
### T<phase>.<num>: <Title>
**Depends on:** <task IDs, or "none">
**Parallel-safe with:** <task IDs in same phase>
**Est. CC time:** <minutes>
**Goal:** <1–2 sentences>
**Inputs:**
- <file paths or spec sections to read>
**Outputs:**
- <files created or modified>
**Acceptance criteria:**
- [ ] <testable condition>
- [ ] <testable condition>
**Notes:**
<gotchas, references, decisions to make inline>
A coordinator (human or top-level agent) picks tasks where Depends on: is satisfied and dispatches them. Within a phase, multiple Parallel-safe with: tasks can run concurrently. Each sub-agent gets only the task card plus the named inputs — no shared conversation history needed.
A phase is "done" when every task in it passes its acceptance criteria AND the phase's PR has green CI. The next phase doesn't start until the prior one is merged. (Within a phase, all task PRs can stack on a single phase branch and merge as one squash.)
bundle exec prefix on all gem tools. Lint with (cd <project_root> && bundle exec rubocop).pnpm for package management. bun only for bunx shadcn add ....feat:, fix:, docs:, test:, chore:).# REFERENCE PATTERN: <name> — see AGENTS.md §<N> (Ruby) or // REFERENCE PATTERN: ... (JS).Goal: Validate that the three open compatibility risks all work together before public scaffold commits.
Mode: SEQUENTIAL. One throwaway branch. No public repo activity yet.
Gate to Phase 1: every task below must pass. If any fails, follow the fallback decision tree in the strategic plan, then re-spike.
Depends on: none Parallel-safe with: none (the throwaway branch starts here) Est. CC time: 30 min
Goal: Bootstrap a throwaway Rails 8 + RoR Pro app with RSC and Rspack enabled, on its own branch.
Inputs:
packages/create-react-on-rails-app/ (CLI source — to understand flags)Outputs:
spike/starter-tanstack-stack-validation containing a fresh app produced by create-react-on-rails-app --rsc --rspack.SPIKE.md at the app root with a "what we're testing" section.Acceptance criteria:
bin/setup runs clean on a fresh macOS clone.bin/dev boots web + Rspack + Node renderer without errors.localhost:3000 shows the generated welcome page.SPIKE.md lists the four validation goals (see T0.2–T0.5).Depends on: T0.1 Parallel-safe with: none (sequential spike) Est. CC time: 45 min
Goal: Confirm TanStack Router mounts cleanly under a Rails-served shell route with SSR loaders and clean hydration.
Inputs:
Outputs:
/spike/tan-router Rails route serving a TanStack Router shell./spike/tan-router/child).Acceptance criteria:
/spike/tan-router includes the loader's data (no flash of unloaded content)./child works without a full page reload.Notes: This is the single highest-risk integration. If it fails, the whole kit identity is at risk — escalate before continuing.
Depends on: T0.2 Parallel-safe with: none Est. CC time: 30 min
Goal: Confirm TanStack Query can read from a Rails JSON endpoint with CSRF, with independent loading/error states per query.
Inputs:
Outputs:
/api/spike/ping Rails JSON endpoint./spike/tan-router rendering separate cards, each with its own loading + error state.Acceptance criteria:
Depends on: T0.1 Parallel-safe with: T0.2, T0.3 (after T0.1) Est. CC time: 30 min
Goal: Confirm shadcn/ui blocks render correctly when used inside a Pro RSC bundle on Tailwind v4.
Inputs:
Outputs:
/spike/rsc-shadcn Rails route that renders a Pro RSC component (rsc: true).Card).Button with onClick) inside the RSC tree.Acceptance criteria:
'use client' boundaries.Notes: If Tailwind v4 fails, fall back to v3 per the strategic plan's decision tree. Document the fallback choice in SPIKE.md.
Depends on: T0.2, T0.3, T0.4 Parallel-safe with: none Est. CC time: 30 min
Goal: Render one throwaway route that uses TanStack Router + TanStack Query + Pro RSC + shadcn on Tailwind v4 simultaneously. Document the outcome.
Outputs:
/spike/all-the-things route.SPIKE.md with: what worked, what didn't, fallback decisions (if any), recommended adjustments to the strategic plan's stack.Acceptance criteria:
SPIKE.md includes a verdict: GREEN (proceed with planned stack), AMBER (proceed with named fallbacks), or RED (escalate before Phase 1).Required-Before-Implementation item that needs revision.Notes: This is the gate to Phase 1. Do not start any Phase 1 work until T0.5 lands GREEN or AMBER with named, accepted fallbacks.
Goal: Public template repo with a working scaffold, CI, dev tooling, and the "first-5-minutes error budget" copy.
Parallel tracks:
Depends on: Phase 0 GREEN/AMBER Parallel-safe with: none Est. CC time: 15 min
Goal: Create the public GitHub repository configured as a template, with a placeholder README pointing at the tracking issue.
Outputs:
shakacode/react-on-rails-starter-tanstack (name locked by Justin 2026-05-22).README.md with: "Scaffolding in progress — see #3357" and a link to the strategic plan.LICENSE (MIT, matching ShakaCode convention).Acceptance criteria:
Depends on: T1.1 Parallel-safe with: none Est. CC time: 30 min
Goal: Run create-react-on-rails-app --rsc --rspack, apply the spike's findings, push first commit.
Inputs:
SPIKE.md (apply any AMBER fallback choices).Outputs:
CHANGELOG.md initialized..github/ directory with placeholder issue + PR templates.Acceptance criteria:
git clone + bin/setup + bin/dev on a fresh macOS laptop boots the welcome page (TTHW measurement starts here — target ≤ 3 min from clone).git log shows one initial commit signed by the implementer.Depends on: T1.2 Parallel-safe with: T1.4, T1.5, T1.6, T1.7, T1.8 Est. CC time: 30 min
Goal: CI runs RSpec + Playwright on every push and PR. Tests can be empty stubs — the goal is green CI infrastructure.
Outputs:
.github/workflows/ci.yml with two jobs: rspec and playwright.main requires both jobs green to merge.Acceptance criteria:
bin/doctor preflightDepends on: T1.2 Parallel-safe with: T1.3, T1.5, T1.6, T1.7, T1.8 Est. CC time: 30 min
Goal: A script that checks every prerequisite a dev needs to boot the app, with actionable error messages.
Outputs:
bin/doctor (Ruby or Bash, implementer's choice)..ruby-version), Postgres reachable, Node version (≥ 20), pnpm installed, bun installed.Acceptance criteria:
bin/doctor on a healthy macOS dev box prints "all checks passed" and exits 0.bin/doctor runs in < 3 seconds.bin/setup wrapping doctor + db prep + seedDepends on: T1.4 Parallel-safe with: T1.3, T1.6, T1.7, T1.8 Est. CC time: 20 min
Goal: Single command that primes a fresh clone — runs doctor, installs deps, prepares db, seeds dev data.
Outputs:
bin/setup (overrides the default Rails one).bin/doctor, bundle install, pnpm install, bin/rails db:prepare, bin/rails db:seed.Acceptance criteria:
bin/setup exits 0 and bin/dev then boots the app.bin/doctor fails, bin/setup aborts with the doctor message.Procfile.dev with the four processesDepends on: T1.2 Parallel-safe with: T1.3, T1.4, T1.5, T1.7, T1.8 Est. CC time: 15 min
Goal: bin/dev boots web + Rspack-watch + SolidQueue + Node renderer via Foreman/Overmind.
Outputs:
Procfile.dev defining: web, rspack, worker (SolidQueue), renderer (Pro Node renderer).bin/dev script (the standard Rails one is fine if it reads Procfile.dev).Acceptance criteria:
bin/dev boots all four processes; killing one logs the failure without taking down the others.Depends on: T1.2 Parallel-safe with: T1.3, T1.4, T1.5, T1.6, T1.8 Est. CC time: 45 min
Goal: The 6–8 predictable evaluator failures each surface with problem + cause + fix.
Outputs:
config/initializers/development_error_hints.rb that:
User.count == 0 and renders "no demo user — run bin/rails db:seed" inline.bin/dev preflight: checks port 3000 is free, Postgres is reachable, Node renderer port is free — prints a fix message before booting.docs/05-troubleshooting.md lists every predictable failure mode with copy-pasteable fixes (stub now; flesh out in T9.8).Acceptance criteria:
.env.example with required varsDepends on: T1.2 Parallel-safe with: T1.3, T1.4, T1.5, T1.6, T1.7 Est. CC time: 15 min
Goal: Document every ENV var the kit reads.
Outputs:
.env.example with: RAILS_MASTER_KEY, DATABASE_URL, SOLID_QUEUE_IN_PUMA, SENTRY_DSN, mail-provider vars (SMTP_* or MAILGUN_API_KEY etc.)..gitignore entry for .env (just .env.example is tracked).Acceptance criteria:
cp .env.example .env produces a usable dev config (the dev-mode defaults work).Goal: Rails 8 auth generator + custom signup + email verification (per Required-Before-Implementation #1 spec) + WelcomeMailer, re-skinned with shadcn/ui.
Parallel tracks (after T2.1, T2.2):
Depends on: Phase 1 complete Parallel-safe with: none (must be first in phase) Est. CC time: 15 min
Goal: Commit the baseline bin/rails generate authentication output before any custom changes.
Outputs:
Acceptance criteria:
feat(auth): run Rails 8 authentication generator (baseline).Depends on: T2.1 Parallel-safe with: none Est. CC time: 20 min
Goal: Add name, email_verification_token_digest, email_verified_at, verification_sent_at columns to the generator's CreateUsers migration before any db:migrate.
Outputs:
db/migrate/.app/models/user.rb with the new attributes + validations.bin/rails db:migrate runs clean.Acceptance criteria:
User.new(email_address: "[email protected]", password: "z", name: "X") is valid.email_verification_token_digest.Notes: The strategic plan documents this approach in AGENTS.md so adopters who re-run the generator know why their migration diverges.
Depends on: T2.2 Parallel-safe with: T2.4, T2.5, T2.6 Est. CC time: 30 min
Goal: RegistrationsController (the generator does NOT provide this) with new and create, view at /signup.
Outputs:
app/controllers/registrations_controller.rb (marked # REFERENCE PATTERN: signup-controller — see AGENTS.md §2).app/views/registrations/new.html.erb (initial scaffold; re-skin in T2.8).resource :registration, only: [:new, :create] (or get/post '/signup' — pick the more idiomatic).EmailVerificationMailer.welcome(...).deliver_later (the verification mailer also acts as the post-signup mail; no duplicate).WelcomeMailer.welcome(...).deliver_later./email_verifications/sent after create.Acceptance criteria:
/signup shows the form./signup with valid params creates a user with email_verified_at: nil and a generated verification token./signup with invalid params re-renders with errors.protect_from_forgery is in ApplicationController).Depends on: T2.2 Parallel-safe with: T2.3, T2.5, T2.6 Est. CC time: 60 min
Goal: Full implementation of the email verification token lifecycle per Required-Before-Implementation #1.
Outputs:
app/controllers/email_verifications_controller.rb with:
#create — generates a fresh token, stores digest only, sets verification_sent_at, sends mail, returns identical UX whether email exists or not (enumeration defense).#show (the email-click endpoint) — looks up by digest, checks TTL (24h), checks single-use (not already consumed), on success: sets email_verified_at, nulls the token digest, rotates the session.Rails.logger.tagged("auth").resources :email_verifications, only: [:create, :show].SecureRandom.urlsafe_base64(32), digest via Digest::SHA256.hexdigest, comparison via ActiveSupport::SecurityUtils.secure_compare.Acceptance criteria:
[auth].Depends on: T2.2 Parallel-safe with: T2.3, T2.4, T2.6 Est. CC time: 30 min
Goal: Mailer + view templates for the verification email.
Outputs:
app/mailers/email_verification_mailer.rb with welcome(user) method.app/views/email_verification_mailer/welcome.html.erb and .text.erb.# REFERENCE PATTERN: mailer — see AGENTS.md §6.Acceptance criteria:
EmailVerificationMailer.welcome(user).deliver_now works in dev (visible via letter_opener)./rails/mailers/email_verification_mailer/welcome renders.Depends on: T2.2 Parallel-safe with: T2.3, T2.4, T2.5 Est. CC time: 20 min
Goal: Generic welcome email triggered on signup (separate from verification).
Outputs:
app/mailers/welcome_mailer.rb.Acceptance criteria:
require_verified_email gateDepends on: T2.4 Parallel-safe with: T2.5, T2.6, T2.8 Est. CC time: 20 min
Goal: A before_action that redirects unverified users away from protected routes.
Outputs:
app/controllers/concerns/verified_authentication.rb defining require_verified_email.email_verifications#sent (the "check your email" landing).Acceptance criteria:
/dashboard redirects to "check your email."/dashboard./session/new (not "check your email") — different failure modes get different redirects.Depends on: T2.3, generator's session/passwords views Parallel-safe with: T2.7 Est. CC time: 60 min
Goal: Replace the generator's raw scaffold styling with shadcn/ui blocks across login, signup, password reset, and password reset request views.
Outputs:
app/views/sessions/, app/views/registrations/, app/views/passwords/, app/views/email_verifications/ views using shadcn blocks (Card, Input, Button, Label).# REFERENCE PATTERN: form — see AGENTS.md §4.aria-live="polite" on flash messages, aria-describedby on input errors.Acceptance criteria:
aria-live.Depends on: T2.4, T2.5 Parallel-safe with: T2.7, T2.8 Est. CC time: 60 min
Goal: The "highest-friction touchpoint in the funnel" (Design review) as a designed UX, not a backend gate.
Outputs:
/email_verifications/sent page rendered after signup: shows the target email (masked partially: j***@gmail.com), resend button (with cooldown), "change email" link, spam-folder hint, "open letter_opener" link in dev.Acceptance criteria:
Depends on: T2.4 Parallel-safe with: T2.7, T2.8, T2.9 Est. CC time: 30 min
Goal: Rate-limit verification-email sends per Required-Before-Implementation #1.
Outputs:
config/initializers/rack_attack.rb with two throttles:
Acceptance criteria:
POST /email_verifications 6 times from the same IP returns 429 on attempt 6.Depends on: T2.4, T2.10 Parallel-safe with: T2.7, T2.8, T2.9 Est. CC time: 75 min
Goal: Request and model specs covering token expiry, single-use, replay, throttling, session rotation, enumeration defense.
Outputs:
spec/requests/email_verifications_spec.rb — happy path, expired token, consumed token, throttle hit, enumeration probe.spec/requests/registrations_spec.rb — happy path, duplicate email, weak password, mail-provider-down scenario (mock).spec/models/user_spec.rb — verification token methods, digest comparison, expiry.spec/system/signup_to_dashboard_spec.rb — full Capybara flow.:unverified, :expired_token, :verified.Acceptance criteria:
Goal: The Project resource: model, controllers (HTML and JSON), reference form pattern, factories, specs.
Parallel tracks (after T3.1, T3.2):
Depends on: Phase 2 complete Parallel-safe with: none Est. CC time: 15 min
Outputs: Migration adding projects table: name, description, status (integer enum), user_id (FK), last_activity_at, timestamps.
Acceptance criteria:
bin/rails db:migrate runs clean.user_id, last_activity_at, status.Depends on: T3.1 Parallel-safe with: none Est. CC time: 20 min
Outputs: app/models/project.rb with: belongs_to :user, status enum (active/paused/completed/archived), name validation (presence, length), scope active, scope recent.
Acceptance criteria:
Project.statuses returns the enum hash.Depends on: T3.2 Parallel-safe with: T3.5, T3.6 Est. CC time: 75 min
Goal: The HTML controller is the canonical reference pattern for "Rails controller + server-side validation + shadcn form + flash success."
Outputs:
app/controllers/projects_controller.rb with index, show, new, create, edit, update, destroy. Marked # REFERENCE PATTERN: controller — see AGENTS.md §2.app/views/projects/_form.html.erb marked # REFERENCE PATTERN: form — see AGENTS.md §4 — server-side validation errors render inline with aria-describedby, success redirects with a flash toast.index, show, new, edit) use shadcn blocks.before_action :authenticate_user, before_action :require_verified_email, before_action :set_project, only: [:show, :edit, :update, :destroy].Project.find scoped to current_user.projects.Acceptance criteria:
/projects/new → submit empty → see inline errors → submit valid → redirect to /projects/:id with flash toast.Depends on: T3.3 Parallel-safe with: T3.5, T3.6 Est. CC time: 30 min
Outputs: Confirm dialog (shadcn AlertDialog) on Project destroy. Soft-delete via archive! rather than DELETE for the demo? (Implementer decision — but the destroy reference pattern must be visible.)
Acceptance criteria:
Depends on: T3.2 Parallel-safe with: T3.3, T3.6 Est. CC time: 45 min
Outputs:
app/controllers/api/projects_controller.rb namespaced under /api.namespace :api { resources :projects, only: [:index, :show] }.GET /api/projects (list, supports status, sort, page, per_page query params), GET /api/projects/:id, GET /api/projects/:id/metrics (4 metric values for the dashboard cards).authenticate_user + require_verified_email before_actions.Acceptance criteria:
GET /api/projects?status=active returns only active projects for the current user.GET /api/projects?sort=last_activity_at&dir=desc orders correctly.GET /api/projects/:id/metrics returns 4 fields: total, active_count, completed_this_week, avg_cycle_time.Depends on: T3.2 Parallel-safe with: T3.3, T3.5 Est. CC time: 15 min
Outputs: spec/factories/projects.rb with traits: :active, :paused, :completed, :archived, :stale (old last_activity_at).
Acceptance criteria:
FactoryBot.lint passes.Depends on: T3.3, T3.5, T3.6 Parallel-safe with: T3.8 Est. CC time: 60 min
Outputs: spec/requests/projects_spec.rb covering all HTML and JSON endpoints, happy + error paths, authorization scoping.
Acceptance criteria:
Depends on: T3.3, T3.6 Parallel-safe with: T3.7 Est. CC time: 45 min
Outputs: spec/system/full_signup_to_project_flow_spec.rb — Capybara flow: signup → verify (intercept mailer) → dashboard → new project → fill form → submit → see in list.
Acceptance criteria:
Depends on: T3.2 Parallel-safe with: T3.3, T3.5, T3.6 Est. CC time: 15 min
Outputs: db/seeds.rb (guarded by Rails.env.development? || Rails.env.test?) creating [email protected] / password pre-verified + 12 sample projects across all four statuses with varied last_activity_at.
Acceptance criteria:
bin/rails db:seed works in dev.RAILS_ENV=production bin/rails db:seed is a no-op (and logs the skip reason).Goal: The kit's structural moat — TanStack Router + Query + Table operationalized end-to-end on a single dashboard.
Parallel tracks (after T4.1, T4.2):
Depends on: Phase 3 complete Parallel-safe with: T4.2 Est. CC time: 90 min
Goal: Install and configure TanStack Router with SSR loaders, mounted under a single Rails shell controller.
Outputs:
pnpm add @tanstack/react-router @tanstack/router-vite-plugin @tanstack/router-devtools etc.app/controllers/authenticated_controller.rb — base controller with auth + verification gates, renders an empty Rails view that mounts the TanStack app.app/javascript/routes/__root.tsx — the TanStack root route.app/javascript/routes/dashboard.tsx — placeholder route.getCsrfToken() helper that reads the Rails meta tag.Acceptance criteria:
/dashboard first paint includes server-rendered content (view source shows the rendered HTML, not just a <div id="root">)./settings (via TanStack Link) is a client-side navigation (no Rails round-trip).// REFERENCE PATTERN: tanstack-route — see AGENTS.md §2.Depends on: Phase 3 complete Parallel-safe with: T4.1 Est. CC time: 45 min
Goal: QueryClient, provider, and a shared apiFetch wrapper that injects CSRF token from the meta tag.
Outputs:
pnpm add @tanstack/react-query @tanstack/react-query-devtools.app/javascript/lib/queryClient.ts exporting a configured QueryClient.app/javascript/lib/apiFetch.ts — wraps fetch with CSRF + JSON + error normalization.<QueryClientProvider> wired in the root route.Acceptance criteria:
/api/projects succeeds in dev./dashboard with metric cards (TanStack Query)Depends on: T4.1, T4.2 Parallel-safe with: T4.4, T4.5, T4.6 Est. CC time: 60 min
Outputs:
/dashboard TanStack route renders 4 metric cards.useQuery against /api/projects/:id/metrics (or a per-metric endpoint).Acceptance criteria:
/dashboard renders via react_component (classic SSR through the Pro Node renderer) — NOT rsc: true. RSC lives on the public landing where its TTFB / SEO / cold-load wins apply; behind auth it doesn't earn its keep. Verify the page source contains the rendered HTML and that hydration is clean (no console errors).Depends on: T4.1, T4.2 Parallel-safe with: T4.3, T4.5, T4.6 Est. CC time: 90 min
Goal: The Projects list demonstrates the kit's signature pattern — server-driven sort/filter/paginate with URL state.
Outputs:
pnpm add @tanstack/react-table./api/projects.// REFERENCE PATTERN: tanstack-table — see AGENTS.md §7.Acceptance criteria:
?sort=last_activity_at&dir=desc&status=active loads the right state./settings/* nested routesDepends on: T4.1 Parallel-safe with: T4.3, T4.4, T4.6 Est. CC time: 60 min
Outputs:
/settings overview route./settings/profile — edit name + email (email change triggers re-verification)./settings/security — change password (uses Rails password reset flow under the hood).Acceptance criteria:
/projects/new, /projects/:id, /projects/:id/edit routesDepends on: T4.1 Parallel-safe with: T4.3, T4.4, T4.5 Est. CC time: 60 min
Outputs:
Acceptance criteria:
Depends on: T4.3 Parallel-safe with: T4.4, T4.5, T4.6 Est. CC time: 30 min
Goal: A small "what's rendering this page" drawer that names the rendering path (RSC streaming) and links to the demo portfolio for the other modes.
Outputs:
Acceptance criteria:
Depends on: T4.3, T4.4 Parallel-safe with: T4.5, T4.6, T4.7 Est. CC time: 45 min
Outputs:
/dashboard and /settings/*.<Suspense> boundaries per metric card and per Projects-list segment.Acceptance criteria:
Goal: Each pattern ships with empty / loading / error / success states. All largely parallel.
Depends on: Phase 1 complete, T0.4 GREEN (RSC + shadcn + Tailwind v4 validated) Parallel-safe with: all T5.* Est. CC time: 75 min
Goal: The public landing is where RSC earns its keep. This task ships the RSC-rendered landing that demonstrates the kit's "right tool for the right surface" thesis.
Outputs:
/ rendered via react_on_rails_component with rsc: true.// REFERENCE PATTERN: rsc-page — see AGENTS.md §11 (the RSC vs SSR vs client decision tree section).Acceptance criteria:
'use client' boundaries.Depends on: Phase 1 Parallel-safe with: each other Est. CC time: 30 min each
Each task ships one composable pattern with paired empty / loading / error / success components. Mark the canonical pattern files.
# REFERENCE PATTERN: metric-card — see AGENTS.md §3)aria-live="polite")Acceptance criteria each: All 4 states render; can be triggered manually via a dev-only playground route.
prefers-color-schemeDepends on: Phase 1 Parallel-safe with: all T5.* Est. CC time: 45 min
Outputs:
<script> in <head> that reads localStorage.theme AND falls back to prefers-color-scheme: dark if unset.localStorage.Acceptance criteria:
prefers-color-scheme: dark and empty localStorage: no light-mode flash.Depends on: Phase 1 Parallel-safe with: all T5.* Est. CC time: 30 min
Outputs: public/404.html and public/500.html styled with shadcn defaults (must be static — these load when Rails isn't reachable).
Acceptance criteria:
Depends on: Phase 1 complete Parallel-safe with: T6.4 Est. CC time: 30 min
Outputs: config/queue.yml, config/recurring.yml (for ProjectArchiveJob), Procfile.dev worker line confirmed.
Acceptance criteria: SolidQueue boots via bin/dev, worker dashboard accessible at /jobs (dev only).
Depends on: T6.1, Phase 3 Parallel-safe with: T6.4 Est. CC time: 30 min
Outputs: app/jobs/project_archive_job.rb marked # REFERENCE PATTERN: background-job — see AGENTS.md §5. Archives projects with last_activity_at < N.days.ago and status not archived.
Acceptance criteria: Manually triggering the job archives the expected projects.
Depends on: T6.2 Parallel-safe with: T6.4 Est. CC time: 45 min
Outputs: Test that forces a job failure 5 times → DLQ entry created. Test that a successful retry recovers.
Acceptance criteria: CI passes.
Depends on: Phase 1 Parallel-safe with: T6.1, T6.2, T6.3 Est. CC time: 15 min
Outputs: Gemfile entries for sentry-ruby and sentry-rails. config/initializers/sentry.rb with the full config, all commented out, single env var to enable (SENTRY_DSN). README sentence explaining how to flip it on.
Acceptance criteria: Setting SENTRY_DSN in .env and uncommenting the initializer captures a test exception.
Depends on: Phase 4 complete (so the actual structure exists) Parallel-safe with: none (anchors the rest) Est. CC time: 30 min
Outputs: AGENTS.md section: directory tree diagram (~30 lines) showing where each piece lives. Locked from this commit forward — file moves require updating this.
Acceptance criteria: Every directory referenced by other AGENTS.md sections appears in the tree.
Depends on: T7.1 Parallel-safe with: T7.3 Est. CC time: 30 min
Goal: Confirm every category has exactly one REFERENCE PATTERN: marker in the code, and no category is missing one.
Outputs: A short audit doc (delete after) listing each category and its canonical file. Add markers to any missing ones.
Acceptance criteria: grep -rn "REFERENCE PATTERN:" app/ spec/ produces exactly one match per pattern category from AGENTS.md.
Depends on: T7.1 Parallel-safe with: each other Est. CC time: 20–30 min each
Each task writes one AGENTS.md section against the actual code. Tasks:
bunx shadcn add workflow.client./'use client' contentAcceptance criteria each: Section ends with a literal command (e.g., bunx shadcn add ..., bin/rails g ...) plus the exact paths it will touch.
.cursorrules thin pointersDepends on: T7.1 Parallel-safe with: T7.3–T7.13 Est. CC time: 10 min
Outputs: CLAUDE.md and .cursorrules — one-page docs that each say "See AGENTS.md for project conventions" + the most critical 3-5 highlights (lint command, test command, never force-push).
All parallel.
Depends on: Phase 2 complete Est. CC time: 45 min
Outputs: Playwright spec covering signup → mail intercept → verification click → dashboard. Logout. Password reset request → mail intercept → token URL → new password → login.
Depends on: Phase 4 complete Est. CC time: 30 min
Outputs: Network-level test: capture the response for /dashboard and assert that multiple chunks arrive (not a single buffered response). Fail loudly if streaming silently fell back to buffered SSR.
Depends on: Phase 4 complete Est. CC time: 45 min
Outputs: Create → see in list → edit → see updated → delete with confirm → list empty.
Depends on: Phase 4 complete Est. CC time: 30 min
Outputs: Sort the Projects table, observe URL change, paste URL in a new tab, observe table loads with the same state. Also: prefetch verification on hover.
Depends on: Phase 4 complete Est. CC time: 20 min
Outputs: Test that visits /dashboard and /settings/profile, asserts zero console errors and zero hydration warnings.
Depends on: Phase 5 complete Est. CC time: 30 min
Outputs: Cold load with prefers-color-scheme: dark set in Playwright context, screenshot at first paint, assert no light-background pixels.
Depends on: Phase 5 complete Est. CC time: 60 min
Outputs: Keyboard-only navigation through signup → verification → create-project. aria-live assertion on flash and form errors. Focus management on Dialog open/close and route changes.
Depends on: Phase 3 complete Est. CC time: 30 min
Outputs: Anonymous user cannot reach /dashboard. Unverified user cannot reach /dashboard. User A cannot access User B's /projects/:id. Each test asserts the exact response code (302 for redirect, 404 for scoped not-found).
Depends on: Phase 6 complete Est. CC time: 15 min
Outputs: Procfile (production): web, worker, renderer. SolidQueue dispatcher configured.
bin/upgrade-checkDepends on: Phase 1 complete Est. CC time: 60 min
Outputs: Script that diffs the adopter's clone against the latest tagged release of the template, prints categorized changelist (config bumps vs structural vs adopter-owned).
UPGRADING.mdDepends on: none (can be written empty and grow) Est. CC time: 30 min
Outputs: UPGRADING.md with the upgrade policy: what adopters own (their app/ code) vs what they should pull from upstream (bin/, config/, package.json defaults). Stub release notes for the initial release.
Depends on: Phase 8 (so claims are testable) Parallel-safe with: each other Est. CC time: 30–60 min each
docs/01-architecture.md — single diagram (Rails ↔ Node renderer ↔ RSC bundle ↔ TanStack) + 1-page narrativedocs/02-vs-inertia.md — feature comparison + link to react-on-rails-demo-gumroad-rsc for the head-to-headdocs/03-customizing.md — rename the app, swap mailer provider, disable RSC, add a routedocs/04-deploying.md — generic guide + Mailgun/Postmark/Resend swap-in copy + RSC bundle precompile gotcha + production seed safety + secret hintsdocs/05-troubleshooting.md — every predictable failure mode with fix copy (overlaps with T1.7's middleware messages)Depends on: Phase 2 (T2.1 onward) Est. CC time: 30 min
Outputs: Verify db/seeds.rb is guarded by Rails.env.development? || Rails.env.test? (added in T3.9). config.force_ssl = true in config/environments/production.rb. assets:precompile includes the RSC bundle (verify via RAILS_ENV=production bin/rails assets:precompile succeeding and the RSC bundle being present in the manifest).
Acceptance criteria: Production seed in a Rails console is a no-op. Asset precompile in production env includes the RSC bundle.
Depends on: Phase 9 complete Est. CC time: 75 min
Outputs:
git clone … && bin/setup && bin/dev && open …) — Required-Before-Implementation #7's TTHW commitment./settings/profile, /projects/new.[email protected] / password).AGENTS.md.Depends on: Phase 8 complete Est. CC time: 45 min
Goal: Implements Goal #5 — the starter as the canonical QA vehicle for RoR Pro releases.
Outputs:
.github/workflows/pro-rc.yml workflow triggered by a workflow_dispatch event (so RoR Pro CI can call it) OR a scheduled nightly run that pulls the latest Pro RC.Acceptance criteria: A manual workflow_dispatch run completes and posts results.
Depends on: Phase 9 complete Est. CC time: 90 min
Outputs: Hosted demo at a stable URL (Fly.io or Render — implementer's choice) with [email protected] / password pre-seeded, links from the landing page.
Acceptance criteria: Demo URL responds, login works, dashboard renders.
Depends on: T10.1, T10.3 (if doing the demo) Est. CC time: 30 min
Outputs:
description set, topics tagged, "About" section filled.Quick-reference for any sub-agent picking up a task without conversation history:
bundle exec rspec # backend
pnpm test # Vitest frontend
bin/test --smoke # Playwright smoke
bin/test --a11y # accessibility-tagged Playwright
bin/test # everything
(cd <project_root> && bundle exec rubocop) # Ruby lint
pnpm lint # JS/TS lint
pnpm format # Prettier
/, /session/*, /signup, /passwords/*, /email_verifications/*, /api/*, the authenticated shell./dashboard, /dashboard/projects/*, /projects/new, /projects/:id/*, /settings/*.app/
controllers/ # Rails controllers (HTML + JSON)
api/ # JSON API controllers
views/ # Rails views (auth, layout shell, mailer templates)
javascript/
routes/ # TanStack Router route files
components/ # React components (PascalCase)
ui/ # shadcn primitives
lib/ # apiFetch, queryClient, getCsrfToken, etc.
models/ # ActiveRecord
jobs/ # SolidQueue
mailers/ # ActionMailer
middleware/ # Rack middleware (rate limit, etc.)
config/
initializers/ # Sentry, Rack::Attack, etc.
routes.rb
spec/
models/, requests/, system/, factories/
test/
playwright/ # Playwright specs
docs/ # Adopter-facing docs (Diataxis-ish)
AGENTS.md # Pattern index
CLAUDE.md # Pointer at AGENTS.md
.cursorrules # Pointer at AGENTS.md
| Phase | Tasks | Est. CC hours | Parallelizable? |
|---|---|---|---|
| 0 — Spike | 5 | 2.5 | Mostly sequential |
| 1 — Bootstrap | 8 | 3.5 | Some parallel after T1.2 |
| 2 — Auth | 11 | 7.5 | Heavily parallel after T2.2 |
| 3 — Projects | 9 | 4.5 | Parallel after T3.2 |
| 4 — TanStack | 8 | 8.5 | Parallel after T4.1, T4.2 |
| 5 — Patterns | 8 | 4.5 | Fully parallel |
| 6 — Jobs/Sentry | 4 | 2.0 | Mostly parallel |
| 7 — AGENTS.md | 14 | 5.0 | Mostly parallel after T7.1 |
| 8 — Tests | 8 | 4.5 | Fully parallel |
| 9 — Deploy | 9 | 4.5 | Mostly parallel |
| 10 — Launch | 4 | 4.0 | Some parallel |
Total: ~50 CC-hours sequentially; ~25-30 wall-clock hours with parallel dispatch across ~3-4 sub-agents.
A team of 4 AI sub-agents working in parallel could realistically land Phase 0 in a half-day, then Phases 1-10 in 3-5 working days assuming clean integration points and the Phase 0 spike lands GREEN.
These were open at the time of the strategic-plan rewrite; all locked in the same session before dispatch.
react-on-rails-starter-tanstack. Locks the identity to TanStack — sharper positioning bet than a year-suffixed name, no calendar-trap maintenance pressure./playground route (not the lead)./ (where TTFB, mobile perf, and SEO actually matter); classic SSR + TanStack lives on the authenticated /dashboard + nested routes (where TanStack's interactivity/type-safety wins apply and RSC's wins don't). The dashboard's rendering-mode drawer tells this story honestly.SPIKE.md verdict (GREEN/AMBER/RED) and dispatches Phase 1 without waiting for human approval. Justin sees results at Phase 1 PR review. Max velocity; tradeoff is that the coordinator must accurately read the spike outcome.