Skip to content

docs(web): describe the free tier and the archive we actually ship - #299

Merged
stevenfackley merged 4 commits into
mainfrom
docs/free-tier-truth
Aug 15, 2026
Merged

docs(web): describe the free tier and the archive we actually ship#299
stevenfackley merged 4 commits into
mainfrom
docs/free-tier-truth

Conversation

@stevenfackley

Copy link
Copy Markdown
Owner

Why

/pricing sold Spark as "Entity-Relationship Canvas / AI Schema Extraction / Generated Next.js Frontend", and the FAQ said "Spark generates the Next.js frontend for your described SaaS."

What tier 0 actually does (GenerationOrchestrator.RenderTier0Preview, L283-296):

// NO LLM call ... Customisation is limited to the project name by design
var rawTemplates = templateProvider.LoadTemplate(Tier0SparkTemplateSet); // "V0-Spark-NextJs"
return templateProvider.Render(rawTemplates, variables);

Every free user gets the same nine-file todo app with {{ProjectName}} swapped in. Zero AI calls, no .NET half, no download. The copy was selling a generation that does not happen.

Auditing the rest of the page against the templates turned up the same class of problem on the paid cards, so this PR makes every bullet traceable to a rendered file.

What changed — free tier

Spark is now sold as what it is and what it is good for: an instant, always-boots lap of the whole pipeline with a real Next.js 15 app live in the browser, five a month, no card. The card, the hero, the banner, the tier chooser and the delivery-page header all state plainly that the demo app is fixed and not built from your description.

Also corrected on the way through:

  • /simple metadata promised "StackAlchemist extracts the schema and hands back a compiled .NET + Next.js repo" on the page that runs a free Spark build.
  • The build narration claimed "Designing your data model…" while a fixed template rendered. It now narrates what happens.
  • SchemaFallbackView's upgrade CTA offered "the full source code — compiled, tested" for Blueprint, which is documents, and nothing anywhere is tested.

What changed — paid tiers

Claims the engine never emits, removed:

Claimed Reality
Blueprint: OpenAPI 3.0 spec, SQL migration scripts, data-flow diagram, ADRs Tier1ArtifactBuilder emits schema.json + api-docs.md. That is the whole tier.
Boilerplate: "Everything in Blueprint" Tier 2 never calls Tier1ArtifactBuilder — those two files are not in the archive.
Boilerplate: Supabase Auth Integration No auth anywhere: no JWT config in Program.cs, no auth pages, RLS enabled with no policies. The client lib and env slots ship; the wiring does not.
Boilerplate: Stripe Payments Integration Nothing. Not in the template, not in the generation prompt.
Infrastructure: GitHub Actions CI/CD, Cost Estimation Report Not in Tier3-Infrastructure.
Infrastructure: CDK "Lambda, RDS, S3, CloudFront" The stack is VPC + ECS Fargate + ALB + RDS.

Real deliverables that were going unsold — the Terraform baseline, build-report.json, the RLS-enabled migration, both Dockerfile targets — are now listed. The Compile Guarantee text matches what the gate verifies: both halves, dotnet restore/build and npm citypechecknext build, with the report in the archive.

No price changed. No product code touched.

Docs

your-output.md documented an archive that does not exist — api/YourProject.Api + YourProject.Core + YourProject.Data, a web/ frontend with (auth) and (dashboard) route groups and per-entity CRUD pages, a root README.md. The real tree is two directories, dotnet/ and nextjs/, one .NET project, and a frontend of page.tsx + lib/api.ts + types/index.ts. Rewritten from the rendered template and the golden fixture, including a "not in the archive" note so the absences are stated rather than discovered.

getting-started.md promised a README.md in every package and a schema review before purchase; simple-mode.md had "You review the generated schema before committing to purchase" as step 4. extractSchema has no callers — there is no review step on that path. Both corrected, and tiers-and-pricing.md / faq.md brought in line so the docs do not contradict the page.

Verification

npm run lint          0 errors, 0 warnings
npx tsc --noEmit      exit 0
npx vitest run        35 files, 308/308 passed
npm run e2e:smoke     29/29 passed (--workers=2)
npm run build         exit 0

The smoke suite flakes on this box at default worker count (13 failures on one run, 2 on another, across specs this PR does not touch — seo-content-routes, robots.txt, sitemap.xml); at --workers=2, which is what CI uses (workers: 1), it is green. No e2e assertion referenced the old copy, so no spec needed changing.

Two things worth a decision, not fixed here

  1. Simple Mode + Blueprint delivers an empty file. submitSimpleGeneration inserts schema_json: null and extractSchema is never called, so a Simple-Mode tier-1 purchase reaches Tier1ArtifactBuilder.Build(null, …)schema.json of an empty schema and an api-docs.md reading "No entities are defined in this schema." That is $299 for two empty documents. Product bug, out of scope for a copy PR — worth an issue.
  2. Blueprint now reads thin, because it is thin. Two files for $299. The honest copy is the floor; the better fix is to build the artifacts that were being advertised (OpenAPI, SQL DDL, ADRs) rather than to describe the gap well.

Spark was sold as "AI Schema Extraction / Entity-Relationship Canvas /
Generated Next.js Frontend" and "Spark generates the Next.js frontend for
your described SaaS". It does none of that: tier 0 renders V0-Spark-NextJs
with {{ProjectName}} substituted and makes no LLM call at all, so every
free user gets the same nine-file task tracker. Copy now says so, and sells
what is genuinely there — an instant, always-boots run of the whole
pipeline with a real Next.js app live in the browser.

The same audit against the templates found the paid lists claiming files
the engine never emits (OpenAPI spec, ADRs and a data-flow diagram at
Blueprint; Stripe and an auth integration at Boilerplate; a GitHub Actions
pipeline and a cost report at Infrastructure) and omitting ones it does
(Terraform, build-report.json). Every bullet and comparison row is now
traceable to a rendered file; the sourcing rule is written next to the
data so the next edit has to keep it.

Docs corrected to the real V1 tree: two top-level directories, dotnet/ and
nextjs/, one .NET project rather than an Api/Core/Data solution, no auth
route groups or per-entity CRUD pages, no README in the archive, and the
Blueprint archive as its actual two files. Simple Mode's "you review the
generated schema before committing to purchase" is gone - extractSchema
has no callers, so there is no review step on that path.

No prices changed and no product code touched.

Verified: npm run lint (0), tsc --noEmit (0), vitest 308/308,
e2e:smoke 29/29 at --workers=2, next build clean.
@stevenfackley

Copy link
Copy Markdown
Owner Author

Review — independent verification (lane: pricing-truth)

Read the full diff, checked every changed claim against the code path it describes, and re-ran the web gates in a fresh worktree off 98280053.

Verdict: fix-needed. Two claims this PR introduces are contradicted by the code — same class of defect the PR exists to remove. Everything else checks out, and the audit is genuinely good.


🔴 1. docs/user/faq.md — new claim is false: the Advanced Mode wizard requires an account

"You can browse the site and model a schema in the Advanced Mode wizard without an account."

/advanced is an auth-gated route:

  • src/StackAlchemist.Web/src/middleware.ts:11const prefixes = ["/simple", "/advanced", "/generate"];
  • src/StackAlchemist.Web/src/middleware.ts:152-160if (!user && !isDemoMode && isProtectedRoute(...)) → redirect to /login?returnTo=…
  • src/StackAlchemist.Web/__tests__/middleware/middleware-utils.test.ts:25-28 — asserts isProtectedRoute("/advanced") === true

A signed-out visitor never reaches the wizard, let alone the ER canvas. The old copy ("explore the interface and define your schema without an account") was also wrong, but vague; this rewrite makes it specific and therefore checkable — and it fails. The second half of the sentence ("an account is required to start a build … 5 per calendar month") is correct and verified (supabase/migrations/20260530000008_enforce_free_generation_quota.sql, actions.ts:236).

Suggested:

You can browse the site — pricing, docs, FAQ — without an account. The whole build flow (/simple, /advanced, /generate) requires sign-in, including a free Spark build, which is limited to 5 per calendar month.

This also propagates: docs/user/getting-started.md and docs/user/tiers-and-pricing.md both sell "model your entities on the ER canvas" as a Spark benefit. That is still true (Spark builds are free), but only after signing in — worth a word there too.


🔴 2. docs/user/getting-started.md — "up to 3 attempts total" is off by one

Step 5 changed from "(up to 3 retries)" → "(up to 3 attempts total)". The retry budget is 3 retries on top of the first build = 4 build attempts:

  • src/StackAlchemist.Engine/Services/GenerationStateMachine.cs:7,38MaxRetries = 3, retry while context.RetryCount < MaxRetries
  • src/StackAlchemist.Engine/Services/CompileWorkerService.cs:100while (job.State == Building && job.RetryCount <= MaxRetries)
  • src/StackAlchemist.Engine.Tests/Integration/CompileWorkerRetryTests.cs:136BuildErrorHistory.Should().HaveCount(4, "initial attempt + 3 retries = 4 build attempts")

The pre-change wording was right. This also makes the PR disagree with itself: docs/user/tiers-and-pricing.md ("Steps 2–4 repeat up to 3 times", "up to 3 correction attempts") and docs/user/faq.md ("This retry loop runs up to 3 times") are all still retry-counted. Revert to "up to 3 retries".

(Note for later, not this PR: BuildReportWriter.Create(job, MaxRetries, …) writes maxAttempts: 3 into build-report.json while attemptsUsed can be 4. The published field is itself inconsistent with the loop.)


🟡 Non-blocking

a. The retired claims are still live on /about and in user-guide.md. The new comment at src/StackAlchemist.Web/src/components/home/pricing-section.tsx:1-3 says it best — "the two pages disagreeing is how a false one survives". Three surfaces were audited; two weren't:

  • src/app/about/page.tsx:238"Row Level Security policies scaffolded for your entities. Auth flows wired into the frontend. Ready for production the moment you deploy." No auth is generated; Prompts/V1-generation.md:90 enables RLS and writes zero policies. This is the exact bullet deleted from /pricing.
  • src/app/about/page.tsx:248"Lambda, RDS, S3, CloudFront". Actual CDK is VPC + ECS Fargate + ALB + RDS (Tier3-Infrastructure/infra/cdk/lib/{{ProjectNameKebab}}-stack.ts:19,33,50,58). Also the exact row deleted from the comparison table.
  • src/app/about/page.tsx:223".NET 10 Web API … controllers, repository pattern … Entity Framework-ready … Clean architecture, proper layering." One minimal-API project, Dapper, "not Entity Framework" (V1-generation.md:45,118).
  • docs/user/user-guide.md:23"Supabase auth integration", plus a Simple Mode row saying "the engine extracts the schema", which contradicts this PR's own simple-mode.md fix (extractSchema has no callers — src/lib/actions.ts:399).

/about is a public marketing page under the same /pricing nav. Follow-up PR is fine, but the gap should not close silently.

b. src/StackAlchemist.Web/src/lib/faq-manifest.ts:84answer: is indented 6 spaces; every sibling key uses 4. Lint-clean, just untidy.

c. docs/user/your-output.md service table lists OpenAPI document (Development only) → http://localhost:5000/openapi/v1.json under the docker compose up quick start, but docker-compose.yml:28 sets ASPNETCORE_ENVIRONMENT: Production on the engine service, so MapOpenApi() (Program.cs:46-49) never runs in that stack — the URL 404s exactly where the reader will try it. Same wording in getting-started.md → "Common First Steps After Download".

d. your-output.md says "the layout above is the whole of it" but the tree omits nextjs/package-lock.json and nextjs/public/.gitkeep, both in the template.

e. pricing/page.tsx:33 — "Stack-agnostic — nothing in it assumes .NET or Next.js". Tier1ArtifactBuilder.cs:36-37 writes "upgrade to Tier 2 (Boilerplate) for the generated .NET / React codebase" into api-docs.md. Mentions, doesn't assume — but it does name React for a Next.js product.


✅ Verified against the code

Claim Source
Spark = fixed template, no LLM call, no download GenerationOrchestrator.cs:112-135,283-296
Spark = nine files V0-Spark-NextJs/ — 9 files
Spark runs in StackBlitz WebContainers; Chromium-only micro-ide-embed.tsx:22,57,78,141
5 free builds / calendar month / account 20260530000008_enforce_free_generation_quota.sql; actions.ts:236
Advanced-Mode schema survives to a paid run StripeWebhookHandler.cs:112,124,335-339
Blueprint = schema.json + api-docs.md, and nothing else Tier1ArtifactBuilder.cs:23-27
Blueprint = field table + 5 REST endpoints + relationship list Tier1ArtifactBuilder.cs:57-91
Tier 2 does not include the Blueprint artifacts GenerationOrchestrator.cs:140-160 vs 172-177
No auth / no Stripe anywhere in the emitted app Prompts/V1-generation.md (whole file); Program.cs has no AddAuthentication
RLS enabled, no policies V1-generation.md:90
Two top-level dirs, out-of-tree paths rejected V1-generation.md:19-31; ReconstructionService.cs:122-137 (UnmappedLlmFileException)
One .csproj, no solution, no README, no docker-compose.prod.yml, no GH Actions V1-DotNet-NextJs/ + Tier3-Infrastructure/ file lists
/api/v1/{entity}s; OpenAPI in Development only V1-generation.md:212; Program.cs:46-49
Migrations mounted into /docker-entrypoint-initdb.d docker-compose.yml:15
Dockerfile targets web + engine; Node 24 Dockerfile:11,18,33,45,54
dotnet restoredotnet build --no-restore; npm citypechecknext build DotNetBuildStrategy.cs:71-78,108-148
build-report.json at archive root BuildReportWriter.cs:26,80-82
Tier 3 = CDK (VPC/ECS Fargate/ALB/RDS) + Terraform + Helm + DEPLOYMENT.md Tier3-Infrastructure/ tree; main.tf; DEPLOYMENT.md headings
Tier 3 files appended only at tier 3 GenerationOrchestrator.cs:311-322
.env.example block quoted verbatim V1-DotNet-NextJs/.env.example
No schema-review step in Simple Mode extractSchema has zero callers (actions.ts:399)

No price changed299 / 599 / 999 identical on every surface (git diff on all price-bearing lines). No product code touched. No test file touchedgit diff --name-only 54bd0854..HEAD matches nothing under test|spec|Fixtures|.csproj, so no gate was weakened.

Gates re-run independently (fresh worktree, CI=true, npm ci from lockfile)

npm run lint       LINT_EXIT=0
npx tsc --noEmit   TSC_EXIT=0
npx vitest run     Test Files 35 passed (35) | Tests 308 passed (308) | VITEST_EXIT=0
npm run build      BUILD_EXIT=0

The V1 compile gate is not the relevant gate here — the diff touches no engine, template, or fixture file.

The FAQ answer to "Do I need an account to try it?" claimed a signed-out
visitor can model a schema in the Advanced Mode wizard. middleware.ts
lists /simple, /advanced and /generate as protected prefixes and redirects
signed-out visitors to /login, so neither build mode is reachable without
an account. Rewritten to say what is actually public.

getting-started step 5 said "up to 3 attempts total". MaxRetries = 3 and
the worker loops while RetryCount <= MaxRetries, so the ceiling is four
build attempts, and CompileWorkerRetryTests asserts exactly that. Every
sibling doc counts retries; restored the retry wording.
Whitespace only. The pricing-tiers entry indented `answer:` six spaces
where every sibling uses four.
@stevenfackley

Copy link
Copy Markdown
Owner Author

Both criticals from the review are fixed on this branch (82a5e718), plus the whitespace nit (4c29fb45).

Critical 1 — faq.md, the account claim. Re-verified before changing it: src/StackAlchemist.Web/src/middleware.ts:11 lists ["/simple", "/advanced", "/generate"], middleware.ts:152-160 redirects a signed-out visitor to /login?returnTo=…, and the matcher at :173-177 covers those paths. The wizard is not reachable signed out. Rewritten to:

Yes, for anything past reading. The marketing pages, this FAQ, and the docs are public, but both build modes are gated: /simple and /advanced redirect a signed-out visitor to sign-in, so the account comes before the schema wizard, not after it. Starting a build needs one too — including a free Spark build, which is limited to 5 per calendar month.

The correct half (account required to start a build, 5 per calendar month) is preserved verbatim. Grepped the rest of the tree for the retired phrasing — it appeared only in docs/user/faq.md; faq-manifest.ts has no account question, so there is no second surface to fix.

Critical 2 — getting-started.md step 5. Reverted to the base wording, (up to 3 retries). Confirmed the ceiling independently: GenerationStateMachine.cs:7 MaxRetries = 3 retrying while RetryCount < MaxRetries, CompileWorkerService.cs:100 looping while RetryCount <= MaxRetries, and CompileWorkerRetryTests.cs:136 asserting HaveCount(4, "initial attempt + 3 retries = 4 build attempts"). Deliberately did not substitute a "4 attempts" phrasing: BuildReportWriter publishes maxAttempts: 3 in build-report.json while attemptsUsed can reach 4, so an attempt-counted doc would contradict the shipped artifact. Retry-counted keeps this page consistent with tiers-and-pricing.md, faq.md, troubleshooting.md, and user-guide.md. The maxAttempts/attemptsUsed mismatch is a pre-existing product inconsistency, untouched here.

Nit (b)faq-manifest.ts:84 answer: re-indented to 4 spaces. Whitespace only.

Gates re-run on the fixed tree (fresh worktree at 4c29fb45, npm ci from lockfile). next build statically prerenders /docs/[slug], which reads these markdown files off disk via lib/docs.ts:10,21, so the build does exercise the changed content:

npm ci             NPMCI_EXIT=0
npm run lint       LINT_EXIT=0
npx tsc --noEmit   TSC_EXIT=0
npx vitest run     Test Files 35 passed (35) | Tests 308 passed (308) | VITEST_EXIT=0
npm run build      BUILD_EXIT=0

Not merged; PR left OPEN.

Still open, not addressed here (reported as non-blocking in the review, left for the owner's call): the retired claims surviving on /about and docs/user/user-guide.md; the /openapi/v1.json 404 under docker compose (ASPNETCORE_ENVIRONMENT: Production means MapOpenApi() never runs); your-output.md omitting nextjs/package-lock.json and nextjs/public/.gitkeep; and the "nothing in it assumes .NET or Next.js" line on pricing/page.tsx:33 against Tier1ArtifactBuilder.cs:36-37.

@stevenfackley

Copy link
Copy Markdown
Owner Author

Review — round 2 (re-review at 4c29fb4)

Re-ran everything in a fresh worktree off 54bd085 at the PR head, and re-derived every changed claim from the code path it describes.

Both round-1 criticals are fixed

  1. docs/user/faq.md — "Do I need an account to try it?" — now reads "both build modes are gated: /simple and /advanced redirect a signed-out visitor to sign-in". That matches src/StackAlchemist.Web/src/middleware.ts:11 (prefixes = ["/simple", "/advanced", "/generate"]) and middleware.ts:152-159 (redirect to /login?returnTo=…). The "5 per calendar month" half is src/StackAlchemist.Web/src/lib/actions.ts:236 (FREE_TIER_MONTHLY_LIMIT = 5) + actions.ts:238-245 (UTC calendar-month window) + actions.ts:319-327 / actions.ts:495-503 (per-account precheck on both submit paths). Correct.
  2. docs/user/getting-started.md step 5 — back to (up to 3 retries), consistent with GenerationStateMachine.cs MaxRetries = 3 / CompileWorkerService.cs:100 (while … RetryCount <= MaxRetries → 4 attempts) and with the sibling docs. Correct.

Claims I re-derived from source

Claim Source
Spark = fixed template, zero LLM call GenerationOrchestrator.cs:112-135, RenderTier0Preview at :292-296
Spark = nine files, a todo/task tracker src/StackAlchemist.Templates/V0-Spark-NextJs/ (9 files, app/api/todos/…)
"a real Next.js 15 app" V0-Spark-NextJs/package.jsonnext 15.5.21, React 19, app/ router
StackBlitz WebContainers, Chromium-only components/micro-ide-embed.tsx:53-79, :141
"read it, edit it, re-run it" micro-ide-embed.tsx:64 view: "default" (editor + live preview), no read-only flag
Advanced-Mode schema saved on the build, buyable later actions.ts:507-522 inserts schema_json: schema at tier 0; StripeWebhookHandler.cs:113-127 re-enqueues that same row's schema on checkout
Blueprint = schema.json + api-docs.md, nothing else Tier1ArtifactBuilder.cs:23-27; fields/keys/nullability/default at :63-68; 5 endpoints at :74-78; relationships at :82-91
Blueprint has no build-report.json CompileWorkerService.cs:86-98 — the Packing branch skips the build entirely
Boilerplate .NET shape (records + DTO, Dapper repos, {Entity}Endpoints.cs, MapGroup) Prompts/V1-generation.md:59-81, few-shot :131-233; mirrored in PromptBuilderService.cs:224-243
Migration: uuid-ossp, UUID PKs, FKs, RLS enabled V1-generation.md:85-90, :240-251
/api/v1/{entity}s, /openapi/v1.json in Development V1-generation.md:212; Program.cs MapOpenApi() inside IsDevelopment()
Two top-level dirs, paths outside them rejected V1-generation.md:19-31, PromptBuilderService.cs:211-214
Docker Compose + multi-stage Dockerfile, web/engine targets, Node 24 V1-DotNet-NextJs/Dockerfile (node:24-alpine, aspnet:10.0), docker-compose.yml
Migrations mounted into the Postgres init hook docker-compose.yml./dotnet/Migrations:/docker-entrypoint-initdb.d:ro
.env.example block quoted in your-output.md matches V1-DotNet-NextJs/.env.example verbatim
Compile Guarantee commands DotNetBuildStrategy.cs:72,78 (dotnet restore, build --no-restore), :108-113 (npm ci), :131-138 (npm run typecheck), :146-148 (npm run build)
build-report.json = command + exit code + per-half verdict Models/BuildReport.csBuildStepReport.Command/ExitCode, BuildHalfSummary.Status
Tier 3 = CDK (VPC/ECS Fargate/ALB/RDS) + Terraform + Helm + DEPLOYMENT.md; no CI/CD, no cost report Tier3-Infrastructure/infra/cdk/lib/…-stack.ts:14,19,33,58; infra/terraform/main.tf (VPC/ECS/ALB/RDS/log group); infra/helm/templates/{deployment,service,ingress,hpa,configmap,secrets}.yaml; DEPLOYMENT.md §Preflight/CDK/Terraform/Helm/Rollback. No .github/workflows and no cost report anywhere in the tree.
No README.md, no solution file, no docker-compose.prod.yml in the archive full file listing of V1-DotNet-NextJs/ + Tier3-Infrastructure/
"no schema-review step in Simple Mode" extractSchema (actions.ts:399) has zero call sites in src/
Simple Mode paid run reads the prose directly GenerationOrchestrator.cs:466-472 (BuildUserPrompt) + :440-460 (falls back to V1-generation.md with {} when Schema is null)
Simple Mode always starts a free Spark build SimpleModePage.tsx:75submitSimpleGeneration(prompt, 0)

No price changed$299 / $599 / $999 are byte-identical everywhere in the diff, and no price literal exists outside copy.

No gate weakenedgit diff main…HEAD --stat -- src/StackAlchemist.Engine.Tests src/StackAlchemist.Templates .github is empty. Docs + web copy only.

Gates I re-ran (CI=true, fresh worktree, npm ci)

npm run lint      LINT_EXIT=0     (eslint --max-warnings 0)
npx tsc --noEmit  TSC_EXIT=0
npx vitest run    Test Files 35 passed (35) / Tests 308 passed (308)   VITEST_EXIT=0
npm run build     BUILD_EXIT=0

e2e:smoke not re-run here; instead I grepped e2e/ and __tests__/ for every string this PR removed (view-only, Live Preview, AI Schema Extraction, Try Before You Buy, Free Preview, Architecture is Ready, Designing your data model, Entity-Relationship Canvas, OpenAPI 3.0, Stripe Payments) — the only hit is a test title at e2e/smoke/simple-mode-flow.spec.ts:4, no assertion. The claim that no spec needed changing holds.


One thing to fix before merge

/about still ships the two claims this PR just deleted from /pricing as false.

src/StackAlchemist.Web/src/app/about/page.tsx:238

"Row Level Security policies scaffolded for your entities. Auth flows wired into the frontend. Ready for production the moment you deploy."

src/StackAlchemist.Web/src/app/about/page.tsx:248

"Lambda, RDS, S3, CloudFront — all as TypeScript infrastructure code."

Both are checkably false against the same sources this PR used. No auth code is generated anywhere (V1-generation.md §Required Output emits Models/Repositories/Endpoints/migration/types/api.ts/page.tsx and nothing else; no [Authorize], no JWT config in Program.cs, no login route). The migration enables RLS with no policies (V1-generation.md:90). The CDK stack is VPC + ECS Fargate behind an ALB + RDS PostgreSQL (…-stack.ts:19,33,58) — there is no Lambda, no S3 and no CloudFront construct in the tree.

/about is a live public route, and after this PR the two pages contradict each other on a $599 purchase input: /pricing now says "Supabase client and env wiring preinstalled (auth flows are yours to write)" while /about says "Auth flows wired into the frontend." That's exactly the failure mode the PR's own new comment in components/home/pricing-section.tsx:4-6 warns about — "the two pages disagreeing is how a false one survives." Not introduced here, but it's the same surface, the same claim, and a two-line fix; leaving it means the sweep landed on the pricing page rather than on the site.

(docs/user/user-guide.md:23 carries the same "Supabase auth integration" claim, but it is not in docs-manifest.ts, so it isn't published — worth the same edit, lower priority.)

Nits, not blocking

  • api-docs.md isn't quite stack-neutral. /pricing bullet "Stack-agnostic — nothing in it assumes .NET or Next.js", but the generated file's own preamble reads "upgrade to Tier 2 (Boilerplate) for the generated .NET / React codebase" (Tier1ArtifactBuilder.cs:36-37). The contract is stack-neutral; the upsell paragraph inside it isn't. Either soften the bullet or drop the stack names from the preamble.
  • your-output.md archive tree omits two real filesnextjs/package-lock.json (the Dockerfile copies it) and nextjs/public/.gitkeep — while asserting "the layout above is the whole of it." Same class of imprecision the PR is fixing, just tiny.
  • npm ci has a documented fallback. Docs say the loop runs npm ci; DotNetBuildStrategy.cs:112-127 falls back to npm install when the LLM added a dependency and the lockfile disagrees. Not worth a docs paragraph, but "npm ci" isn't the whole truth.
  • Simple Mode + Blueprint — agreed with the PR body: schema_json: null (actions.ts:337) reaching Tier1ArtifactBuilder.Build(null, …) yields an empty schema.json and "No entities are defined in this schema." for $299. Product bug, correctly out of scope. Worth an issue before Blueprint gets any traffic from /simple.

Everything else in the diff checks out. Fix /about and this is good to go.

/about carried the two claims this branch deletes from /pricing as false,
on a live public route. Verified against the same sources:

- "Row Level Security policies scaffolded ... Auth flows wired into the
  frontend" — the generation prompt emits only models, repositories,
  endpoints, the migration, types, api.ts and page.tsx. There is no
  [Authorize], no JWT configuration in the template Program.cs and no
  login route; the migration runs ENABLE ROW LEVEL SECURITY with no
  CREATE POLICY. The Supabase client and its env slots are preinstalled
  and nothing more.
- "Lambda, RDS, S3, CloudFront" — the CDK stack is VPC + ECS Fargate
  behind an ALB + RDS PostgreSQL. No Lambda, S3 or CloudFront construct
  exists anywhere in the Tier 3 tree.

Three neighbours in the same six-item list failed the same check and are
corrected with them: the backend is a Dapper/Npgsql minimal API, not
controllers with model validation and Entity Framework-ready data access;
the migration emits no indexes; and .env.example says to copy and fill it
before running, so "no config required" was wrong.

Also fixes docs/user/user-guide.md, which is unpublished (absent from
docs-manifest.ts) but described a Tier 3 tree that does not exist —
bin/app.ts, database-stack.ts, api-stack.ts, frontend-stack.ts,
auth-stack.ts and a .github/workflows pair, none of which ship. Replaced
with the real cdk/terraform/helm layout.

Adds a sourcing note above the list so the next edit keeps /about and
/pricing in substance identical.
@stevenfackley

Copy link
Copy Markdown
Owner Author

Round-2 critical fixed in d20a4fa.

/about carried the same two false claims this branch deletes from /pricing. Re-verified both against the sources rather than taking them on trust:

  • "Row Level Security policies scaffolded … Auth flows wired into the frontend"Prompts/V1-generation.md §Required Output (L59-101) emits only Models / Repositories / Endpoints / migration / types / api.ts / page.tsx. The template Program.cs has no authentication or JWT block, grep -riE "authorize|jwt|bearer" over V1-DotNet-NextJs/dotnet/ returns nothing, and the tree has no login route. The migration runs ENABLE ROW LEVEL SECURITY (V1-generation.md:90) with no CREATE POLICY — confirmed absent from the golden fixture too. Supabase is a preinstalled client plus two env passthroughs in next.config.ts:14-15; nothing constructs it.
  • "Lambda, RDS, S3, CloudFront" — the CDK stack is VPC + ECS Fargate behind an ALB + RDS PostgreSQL ({{ProjectNameKebab}}-stack.ts:19,33,58). grep -riE "lambda|cloudfront|s3" over the whole Tier3-Infrastructure/ tree returns zero hits.

Both rows now read the same as the /pricing lists, and I added a sourcing note above the array so the next edit keeps the two pages in substance identical.

Three neighbours in the same six-item list failed the same check, so I corrected them rather than leave known-false copy beside the two I was fixing:

Row Was Why it was false
.NET 10 Web API "controllers, … model validation, and Entity Framework-ready data access" Minimal-API Map…Endpoints extension methods, not controllers; csproj references Dapper + Npgsql with no EF package; no validation is wired anywhere
PostgreSQL "Foreign keys, indexes, and constraints" The prompt specifies no indexes and the golden fixture emits no CREATE INDEX
Next.js 15 "No config required to run" .env.example opens with "Copy to .env and fill in values before running"

Also fixed docs/user/user-guide.md. You flagged it lower-priority because it is absent from docs-manifest.ts (confirmed — the manifest lists 11 slugs, user-guide is not one). But its Tier 3 tree was fabricated wholesale: bin/app.ts, database-stack.ts, api-stack.ts, frontend-stack.ts, auth-stack.ts and a .github/workflows pair, none of which ship. Replaced with the real cdk / terraform / helm layout, and softened the "Supabase auth integration" line in the overview.

Gates

No gate weakened — git diff 54bd0854...HEAD --stat -- src/StackAlchemist.Engine.Tests src/StackAlchemist.Templates .github is still empty. Prices byte-identical.

Ran locally with CI=true:

npm run lint                                    LINT_EXIT=0
npx tsc --noEmit                                TSC_EXIT=0
npx vitest run          35 files / 308 tests    VITEST_EXIT=0
npm run build                                   BUILD_EXIT=0
dotnet test (excl. compile gate)  394 passed, 1 skipped (R2 real-creds)
dotnet test V1TemplateCompileTests  9 passed, 0 skipped, 5m55s   <- genuinely ran, not skipped

Grepped the prerendered .next/server/app/about.html: none of the old strings survive, the corrected ones are present.

One note for the record: dotnet restore floated Engine.Tests/packages.lock.json to newer test packages (the [10.*, ) / [18.*, ) wildcards) and next build rewrote next-env.d.ts. Both were side effects of my verification, not intended changes — I reverted them so they do not ride along on a docs PR. The commit is the two copy files only.

All 14 checks green on d20a4fa. Leaving this open and unmerged for you.

@stevenfackley

Copy link
Copy Markdown
Owner Author

Review round 3 — d20a4fa1approve

Fresh detached worktree at d20a4fa1, CI=true, clean npm ci. Round-2 critical is genuinely fixed; I re-verified it against the sources rather than the commit message, and re-walked every claim in the diff.

Round-2 critical: closed

Both strings are gone from the built page, not just the source. Grepping the prerendered .next/server/app/about.html and pricing.html after a clean next build:

OLD: Auth flows wired into the frontend | Lambda, RDS, S3, CloudFront |
     Supabase Auth Integration | Stripe Payments Integration | OpenAPI 3.0 |
     Cost Estimation Report | AI Schema Extraction | Try Before You Buy | view-only
  → zero hits

NEW: about.html   "ECS Fargate behind an Application Load Balancer"
     about.html   "the policies and the auth flows are yours to write"
     pricing.html "auth flows are yours to write"
     pricing.html "not generated from your"
  → present

The three neighbouring rows you corrected unprompted check out too:

  • .NET 10 Web APIProgram.cs is top-level minimal API with [[LLM_INJECTION_START: RouteRegistrations]], no controllers; the csproj ({{ProjectName}}.csproj:12-13) references Dapper 2.1.66 + Npgsql 9.0.4 and no EF package. "Minimal-API endpoint groups with a Dapper repository per entity over Npgsql" matches V1-generation.md:61-73 exactly.
  • PostgreSQL / indexesV1-generation.md:85-91 specifies uuid-ossp, UUID PKs, FK constraints and ENABLE ROW LEVEL SECURITY; the worked example at :240-251 emits no CREATE INDEX. Dropping "indexes" was right.
  • Next.js "No config required to run".env.example:2 literally reads "Copy to .env and fill in values before running." "Copy .env.example and it runs" is the honest form.

Every changed claim, re-checked

Claim Source
Spark = fixed template, no LLM call GenerationOrchestrator.cs:113-134 — "NO LLM call", returns before the codegen path
…nine files, task tracker Templates/V0-Spark-NextJs/ — 9 files, app/api/todos/, _data/store.ts
…runs in StackBlitz WebContainers, editable micro-ide-embed.tsx:53-77template: "node", view: "default", crossOriginIsolated: true; no read-only flag
5 builds / calendar month, no card lib/actions.ts:236 FREE_TIER_MONTHLY_LIMIT = 5; enforced at :323 and :499
Advanced-Mode schema survives a free build actions.ts:516 inserts schema_json: schema at tier 0; upgrade reuses the same row id (upgrade-modal.tsx:19-26) and StripeWebhookHandler.cs:336 reads schema_json back off it — so "come back and buy a paid run against it" holds
Blueprint = schema.json + api-docs.md, nothing else Tier1ArtifactBuilder.cs:19-28 — the dictionary has exactly two keys
Tier 2 does not ship the Blueprint files GenerationOrchestrator.cs:159-176 — the tier-1 branch returns early; the ≥2 path never calls Tier1ArtifactBuilder. The bb: false / infra: false on "Schema + API contract documents" is correct
Boilerplate = record + DTO, I…Repository + Dapper impl, …Endpoints.cs per entity V1-generation.md:61-73
Migration: UUID keys, FKs, RLS enabled V1-generation.md:85-91 + example :240-251
Docker Compose + multi-stage Dockerfile, web and engine targets Dockerfile:33,54 (AS web, AS engine); docker-compose.yml builds target: engine / target: web
Supabase client + env wiring preinstalled, no auth nextjs/package.json has @supabase/supabase-js ^2.49.4; next.config.ts:14-15 + compose pass the env through; zero supabase references under nextjs/src/
build-report.json in the archive BuildReportWriter.cs:26 FileName = "build-report.json"
Compile Guarantee = dotnet restorebuild --no-restore, npm citypechecknext build DotNetBuildStrategy.cs:72,78,108,131-137
Tier 3 = CDK (VPC/ECS Fargate/ALB/RDS) + Terraform + Helm + DEPLOYMENT.md {{ProjectNameKebab}}-stack.ts:19,33,50,58; infra/terraform/{main,variables,outputs}.tf; infra/helm/templates/{deployment,service,ingress,hpa,configmap,secrets}.yaml
No Lambda / S3 / CloudFront anywhere in Tier 3 grep -riE "lambda|cloudfront|aws-s3|s3\." Tier3-Infrastructure/0 hits
FAQ: "both build modes are gated" middleware.ts:12["/simple", "/advanced", "/generate"]
Docs: two top-level source dirs, prompt rejects paths outside them V1-generation.md:30-31 — "Every file path you emit MUST begin with dotnet/ or nextjs/"
Docs: /api/v1/{entity}s, OpenAPI at /openapi/v1.json in Development V1-generation.md:212; Program.cs MapOpenApi() inside IsDevelopment()
Docs: tables lowercase plural, columns snake_case, Guidstring V1-generation.md:243-251 (CREATE TABLE products, created_at) vs :252-258 (id: string)

No price changed. $299 / $599 / $999 appear on both sides of every hunk that touches them; the only pricing-table delta is a new Free column for Tier 0.

No gate weakened. git diff 54bd0854...HEAD --stat -- src/StackAlchemist.Engine.Tests src/StackAlchemist.Templates src/StackAlchemist.Engine .githubempty. Docs + web copy only.

Gates I re-ran

npm ci            0 vulnerabilities
npm run lint      LINT_EXIT=0     (eslint --max-warnings 0)
npx tsc --noEmit  TSC_EXIT=0
npx vitest run    Test Files 35 passed (35) / Tests 308 passed (308)   VITEST_EXIT=0
npm run build     BUILD_EXIT=0

V1TemplateCompileTests deliberately not re-run: the diff provably touches no Engine, Template or workflow file, so it cannot move that gate. All 14 checks are green on d20a4fa1.


One finding — not blocking this PR, but open an issue

The two claims you deleted as false are still live on ~20 other public pages. /pricing no longer sells "Supabase Auth Integration" or "Stripe Payments Integration"; /compare/* and /solutions/* still do, in winsForUs bullets and indexed meta descriptions:

  • src/StackAlchemist.Web/src/lib/compare-manifest.ts:48 — "Supabase + Stripe + Postgres wired by default"
  • src/StackAlchemist.Web/src/lib/compare-manifest.ts:89 — "Compile-gated output: frontend + backend + DB + auth + Stripe"
  • src/StackAlchemist.Web/src/lib/compare-manifest.ts:153 — "Backend + DB schema + auth + Stripe in one generation, not bolted on"
  • src/StackAlchemist.Web/src/lib/solutions-manifest.ts:20,46,72,123,279… — "…with Stripe, auth, and inventory in 12 minutes. Verified build."
  • plus ~20 files under content/{compare,solutions,blog,press}/ carrying the same class

The build output confirms these are real routes (● /solutions/[vertical], 18 prerendered paths). Same failure mode as the /about row, but this is a 20-file sweep across SEO-indexed marketing copy, not a two-line fix — it belongs in its own PR with its own read of the templates. Blocking a correct copy fix on it would just make the honest page hostage to the dishonest ones. Please open the tracking issue before merging so the sweep doesn't die with this branch.

Carried-over nits, still open (fine to leave)

  1. api-docs.md isn't quite stack-neutral. /pricing says "Stack-agnostic — nothing in it assumes .NET or Next.js" (pricing/page.tsx:69), but the generated file's preamble names them (Tier1ArtifactBuilder.cs:36-37). The contract is neutral; the upsell paragraph inside it isn't.
  2. your-output.md tree omits nextjs/package-lock.json and nextjs/public/.gitkeep while asserting "the layout above is the whole of it" — and the lockfile matters, since the same doc tells the reader to run npm ci. Same class the PR is fixing, just tiny. (infra/ also being top-level at Tier 3 slightly bends "exactly two top-level source directories".)
  3. npm ci has a documented fallback. DotNetBuildStrategy.cs:104-126 falls back to npm install when the LLM adds a dependency — the code comment calls it "the DOCUMENTED common path", so a buyer reading "npm ci" in the docs may find npm install in their build-report.json.
  4. getting-started.md Step 4 now narrates the tier-2/3 pipeline with a Spark caveat but no Blueprint one — a Blueprint buyer reads steps 3-5 (restore/build/retry) that never run for them.
  5. "Chromium-based browsers only" (tiers-and-pricing.md:34, getting-started.md:80) mirrors the app's own error string at micro-ide-embed.tsx:141, so it's internally consistent — but WebContainers also run on Firefox and Safari 16.4+, so both the docs and that string are probably understating support.

Approving. Leaving it to you to merge.

@stevenfackley
stevenfackley merged commit 37c55f2 into main Aug 15, 2026
17 checks passed
@stevenfackley
stevenfackley deleted the docs/free-tier-truth branch August 15, 2026 23:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant