Skip to content

Fix production: every route except the homepage was 404, and every API function was 500 - #2

Merged
Sukarth merged 10 commits into
mainfrom
fix/production-routing
Jul 29, 2026
Merged

Fix production: every route except the homepage was 404, and every API function was 500#2
Sukarth merged 10 commits into
mainfrom
fix/production-routing

Conversation

@Sukarth

@Sukarth Sukarth commented Jul 29, 2026

Copy link
Copy Markdown
Owner

Production was serving only /. Found while spot-checking the live site after the 1.1.0 merge.

Three faults

1. SEO output never built. The Vercel project's build command is overridden in the dashboard to vite build, so scripts/generate-seo-pages.mjs never ran in CI. No diagram pages, no route shells, no sitemap.xml. Fixed by setting buildCommand in vercel.json, which is version controlled and takes precedence over the dashboard.

2. The SPA fallback could not work with cleanUrls. The rewrite sent everything to /index.html. Compiled, cleanUrls emits a 308 from /index.html to / ahead of the filesystem, and rewrites carry check: true, so the rewritten path re-entered the route table, hit that redirect and resolved to nothing. Share links, /settings and /editor were all dead.

The rewrites now name the SPA's routes and target /. Enumerating them rather than catching everything means anything else reaches a real 404 instead of answering with the app and a 200, which would tell crawlers every mistyped URL is a page.

3. Every serverless function returned 500, pre-existing and unrelated to the above:

ERR_MODULE_NOT_FOUND: Cannot find module '/var/task/api/_lib/supabaseAdmin'
imported from /var/task/api/usage.js

package.json sets "type": "module" and tsconfig uses moduleResolution: bundler, so extensionless relative imports typecheck and run locally. Vercel transpiles api/*.ts to ESM without rewriting specifiers, and Node's ESM loader does not guess extensions. Hosted AI, usage metering, checkout, the billing portal and account deletion were all dead. Hidden locally because the dev server loads these through Vite's ssrLoadModule, whose resolver maps .js onto .ts.

Also

  • A 404 page: a market with healthy demand and zero supply, so no quantity is ever traded. Generated into dist/404.html, noindexed, served by Vercel with a real 404 status.
  • A Diagrams link in the landing nav and footer. Without it the prerendered pages were reachable only from search results and nothing on the site pointed at them.
  • package-lock.json picks up the license field it should have got when the project moved from MIT to AGPL.

Verified on production

All 18 sitemap URLs return 200. All 12 links on the 404 page return 200. /nope and /diagrams/nope return 404 with the new page. /api/usage returns 401 {"error":"Not signed in."} and the POST-only endpoints return 405, none 500.

Important

Production is currently running a CLI deploy from this branch, so it is fixed right now but ahead of main. Any deploy triggered from main before this merges will put the outage back.

Summary by Sourcery

Ensure production serves all SPA routes, static SEO pages, and API endpoints correctly instead of returning 404/500 errors.

New Features:

  • Add a custom 404 HTML page with economic diagram content, linked CTAs, and integration into the static build output.
  • Expose the Diagrams hub via navigation links in the landing page header and footer so prerendered guides are discoverable from the site.

Bug Fixes:

  • Fix API serverless functions on Vercel by using explicit .js extensions in ESM imports so modules resolve correctly in production.
  • Restore generation of static SEO pages, route shells, sitemap, and the new 404 page as part of the build so they are present in production deploys.
  • Update SPA routing configuration in vercel.json so known routes are explicitly rewritten to the app while unknown paths correctly return a 404 status.

Enhancements:

  • Allow static SEO page rendering to control robots directives via a configurable meta tag instead of always indexing.
  • Document deployment and routing behaviour in generate-seo-pages.mjs to clarify the interaction between clean URLs, rewrites, and the 404 page.

Build:

  • Configure Vercel’s buildCommand in vercel.json to run the full npm build pipeline instead of just vite build, ensuring all static assets and SEO pages are generated.
  • Update package-lock.json metadata to reflect the project’s AGPL license change.

Summary by CodeRabbit

  • New Features
    • Added “Diagrams” links to the landing page’s desktop navigation and footer.
    • Added a dedicated, crawl-excluded /404 page.
    • Exposed OpenAPI schema availability and improved deployment routing for key app paths.
  • Bug Fixes
    • Fixed billing interval selection (reliable monthly default; correct annual handling).
    • Resolved API loading issues caused by ESM import paths missing required extensions.
    • Ensured malformed share links and certain navigations return a real 404 instead of requiring reload.
  • Refactor
    • Centralized client routing and shared-link detection for consistent navigation and deployability checks.

Sukarth added 3 commits July 29, 2026 08:36
Two independent faults, both invisible locally because `npm run build` and
the dev server exercise neither.

The project's Vercel build command is overridden in the dashboard to
`vite build`, so generate-seo-pages.mjs never ran in CI. None of the
diagram pages, route shells or sitemap.xml existed in the deployment. Set
`buildCommand` in vercel.json, where it is version controlled and beats
the dashboard, instead of fixing it by hand in a UI nobody diffs.

The SPA fallback rewrote everything to `/index.html`, which cannot work
with `cleanUrls: true`. Compiled, cleanUrls emits a 308 from
`/index.html` to `/` ahead of the filesystem, and rewrites carry
`check: true`, so the rewritten path re-entered the table, hit that
redirect and resolved to nothing. Every route below `/` returned
NOT_FOUND, taking share links, /settings and /editor with it.

The rewrites now name the SPA's routes and target `/`. Enumerating them
rather than catching everything means anything else falls through to a
real 404 instead of answering with the app and a 200, which would tell
crawlers every mistyped URL is a page.

Also: a 404 page, generated into dist/404.html and noindexed, which Vercel
serves with a 404 status. And a Diagrams link in the landing nav and
footer, without which the prerendered pages were reachable only from
search results and nothing on the site linked to them.

package-lock.json picks up the license field it should have got when the
project moved from MIT to AGPL.
Every serverless function has been returning 500 in production:

  ERR_MODULE_NOT_FOUND: Cannot find module '/var/task/api/_lib/supabaseAdmin'
  imported from /var/task/api/usage.js

package.json sets "type": "module" and tsconfig uses
moduleResolution "bundler", so extensionless relative imports typecheck
and run locally. Vercel transpiles api/*.ts to ESM without rewriting
specifiers, and Node's ESM loader does not guess extensions, so every
function crashed on import. Hosted AI, usage metering, checkout, the
billing portal and account deletion were all dead in production.

It never showed up locally because the dev server loads these through
Vite's ssrLoadModule, whose resolver maps a .js specifier onto the .ts
file and also tolerates the bare one.

Unrelated to the routing commit before it: the function bundles in the
deployment that first exposed this are byte for byte the same size as the
ones in the deployment before, and nothing here touched api/.
The equilibrium annotation sat on top of the line it was annotating.
Copilot AI review requested due to automatic review settings July 29, 2026 05:50
@vercel

vercel Bot commented Jul 29, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
ib-econgraph-ai Ready Ready Preview, Comment Jul 29, 2026 9:05am

@sourcery-ai

sourcery-ai Bot commented Jul 29, 2026

Copy link
Copy Markdown

Reviewer's Guide

Fixes production routing and serverless function failures by enforcing the correct Vercel build command, adding a static 404 page and diagrams navigation, and making all serverless imports Node-ESM compatible so routes and APIs work in production.

Flow diagram for updated Vercel routing and static 404 handling

flowchart TD
    Request["Incoming HTTP request (path)"]

    Request --> CheckFile{"Static file exists in dist?"}

    CheckFile -- Yes --> StaticFile["Serve static file (e.g. /diagrams/*, /404.html)"]
    CheckFile -- No --> CheckSpaRoute{"Path matches SPA route (vercel.json rewrites)?"}

    CheckSpaRoute -- Yes --> SpaRewrite["Rewrite to / (SPA index shell)"]
    SpaRewrite --> SpaHandler["SPA handles client-side route"]

    CheckSpaRoute -- No --> NotFound["Serve dist/404.html with 404 status\nrobots: noindex, follow"]
Loading

File-Level Changes

Change Details Files
Ensure SEO/static assets and route shells are generated during production builds.
  • Expanded documentation comment in SEO generation script to explain dependency on vercel.json buildCommand and the routing model (named SPA routes vs catch‑all).
  • Clarified that generated SEO pages are only produced when the build pipeline runs npm run build, not just vite build.
  • Updated the final log message to include the new 404 page in the generation count.
scripts/generate-seo-pages.mjs
Add a proper HTML 404 page that Vercel serves with a real 404 status for unknown routes.
  • Introduced a render404Page helper that builds a fully styled 404 HTML page using the common pageShell layout.
  • Extended pageShell to accept a configurable robots meta value with a default of index, follow so the 404 can be noindex, follow.
  • Generated dist/404.html as part of the SEO build and ensured it’s excluded from the sitemap while still being fully navigable.
  • Explained in comments how Vercel serves dist/404.html for unmatched paths and why SPA rewrites are enumerated rather than catch‑all.
scripts/generate-seo-pages.mjs
Expose the diagrams hub via primary navigation so prerendered diagram pages are discoverable.
  • Added a /diagrams anchor link to the top navigation bar (desktop) in the landing page header.
  • Added a /diagrams anchor link in the landing page footer copy to provide a crawlable path and better UX.
  • Documented that /diagrams is a static, prerendered page outside the SPA bundle, not a client-side route.
components/LandingPage.tsx
Make all API route imports production-safe under Node ESM by adding explicit .js extensions.
  • Updated imports in serverless API handlers to include .js extensions for local _lib utilities.
  • Updated imports from shared services modules used by API handlers to include .js extensions so they resolve correctly in Node’s ESM loader.
  • Ensured both direct API handlers and nested webhook handlers follow consistent ESM-compliant import specifiers so Vercel’s transpiled output runs without ERR_MODULE_NOT_FOUND.
api/checkout.ts
api/delete-account.ts
api/generate.ts
api/portal.ts
api/webhooks/polar.ts
api/_lib/supabaseAdmin.ts
api/usage.ts
Keep dependency lockfile in sync with package metadata changes.
  • Updated package-lock metadata so the recorded license matches the AGPL license declared in package.json.
package-lock.json
Align Vercel deployment configuration with the intended build and routing behavior.
  • Configured buildCommand in vercel.json to run the full npm run build pipeline rather than the dashboard’s default vite build, ensuring SEO pages, SPA route shells, sitemap, and 404 are generated in CI.
  • Documented in comments and configuration that SPA rewrites enumerate known routes and rely on dist/404.html for true 404s, instead of a catch-all rewrite that would 200 every URL.
vercel.json

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@coderabbitai

coderabbitai Bot commented Jul 29, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 4d63964d-2e41-46e9-b9f4-edf7f08db56c

📥 Commits

Reviewing files that changed from the base of the PR and between 28c7541 and 4e9bedb.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (4)
  • App.tsx
  • CHANGELOG.md
  • package.json
  • scripts/generate-seo-pages.mjs
🚧 Files skipped from review as they are similar to previous changes (1)
  • App.tsx

📝 Walkthrough

Walkthrough

The PR updates API imports for ESM resolution, centralizes client route matching, refines checkout interval parsing, narrows Vercel rewrites, generates a noindex 404 page, validates route coverage, and adds /diagrams links to the landing page.

Changes

Application routing and runtime

Layer / File(s) Summary
Route contract and client parser
routes.mjs, App.tsx
Supported client paths and share-link patterns are centralized in routes.mjs, and App.tsx derives views, shared slugs, and navigation paths from those definitions.
ESM API imports and checkout interval
api/**/*.ts
Internal API imports now use .js extensions, and checkout defaults to 'month', accepting 'year' only when explicitly provided.

Deployment and SEO output

Layer / File(s) Summary
Deployment rewrites and generated SEO pages
scripts/generate-seo-pages.mjs, vercel.json
Vercel uses an explicit build command and route rewrites; SEO generation emits configurable robots metadata, a standalone noindex dist/404.html, and build-time route validation.
Diagrams navigation and release metadata
components/LandingPage.tsx, CHANGELOG.md, package.json
Desktop navigation and the footer include direct /diagrams links, and release metadata is updated to version 1.1.1.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Possibly related PRs

  • Sukarth/IB-EconGraph-AI#1: Earlier routing and SEO groundwork that this PR extends through App.tsx, vercel.json, and scripts/generate-seo-pages.mjs.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main production routing and API fixes addressed by the changeset.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/production-routing

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

Restore Vercel routing, SEO builds, and serverless APIs

🐞 Bug fix ✨ Enhancement ⚙️ Configuration changes 🕐 20-40 Minutes

Grey Divider

AI Description

• Restores production builds, generated SEO pages, and explicit SPA routing on Vercel.
• Fixes serverless ESM imports so API functions load under Node.
• Adds a noindexed 404 page and discoverable diagram navigation.
Diagram

graph TD
  Config["Vercel Config"] --> Build["Build Pipeline"] --> Generator["SEO Generator"] --> Output["Deploy Output"] --> Router["Route Resolver"] --> Pages["Static and SPA"]
  Build --> Output
  Router --> APIs["ESM API Functions"]
  Router --> Missing["404 Page"]
Loading
High-Level Assessment

The chosen approach is appropriate: source-controlled build configuration prevents dashboard drift, explicit SPA rewrites preserve genuine 404 responses, and explicit .js specifiers match Node ESM runtime requirements. A dashboard-only fix would remain unauditable, while restoring a catch-all rewrite would reintroduce soft-404 SEO behavior.

Files changed (11) +141 / -24

Enhancement (2) +120 / -5
LandingPage.tsxExpose diagram guides from primary navigation +17/-0

Expose diagram guides from primary navigation

• Adds direct links to the prerendered diagrams hub in the landing-page navigation and footer, improving discovery and internal linking.

components/LandingPage.tsx

generate-seo-pages.mjsGenerate a crawl-safe custom 404 page +103/-5

Generate a crawl-safe custom 404 page

• Extends the shared page shell with configurable robots metadata and emits a noindexed 'dist/404.html' containing recovery links and diagram guides. Documentation now explains the production build and explicit-route requirements.

scripts/generate-seo-pages.mjs

Bug fix (8) +20 / -18
supabaseAdmin.tsMake entitlement import Node ESM-compatible +1/-1

Make entitlement import Node ESM-compatible

• Adds the emitted '.js' extension to the entitlement import so Vercel's Node ESM runtime can resolve the shared module.

api/_lib/supabaseAdmin.ts

checkout.tsFix checkout handler ESM imports +3/-3

Fix checkout handler ESM imports

• Adds explicit '.js' extensions to Supabase, Polar, and entitlement imports, preventing checkout initialization failures in Vercel serverless functions.

api/checkout.ts

delete-account.tsFix account deletion handler ESM imports +3/-3

Fix account deletion handler ESM imports

• Makes all relative imports resolvable by Node ESM so account deletion can load its Supabase, Polar, and entitlement dependencies.

api/delete-account.ts

generate.tsFix hosted generation handler ESM imports +2/-2

Fix hosted generation handler ESM imports

• Adds explicit extensions to Supabase and diagram-prompt imports so the hosted AI function loads successfully in production.

api/generate.ts

portal.tsFix billing portal handler ESM imports +2/-2

Fix billing portal handler ESM imports

• Updates Supabase and Polar imports for Node ESM resolution, restoring billing portal session creation.

api/portal.ts

usage.tsFix usage endpoint ESM import +1/-1

Fix usage endpoint ESM import

• Adds the required extension to the Supabase helper import so usage metering no longer fails during module loading.

api/usage.ts

polar.tsFix Polar webhook ESM imports +2/-2

Fix Polar webhook ESM imports

• Adds explicit extensions to Supabase and entitlement imports so Polar webhook processing can initialize on Vercel.

api/webhooks/polar.ts

vercel.jsonRestore complete builds and explicit production routing +6/-4

Restore complete builds and explicit production routing

• Pins Vercel to 'npm run build', adds the configuration schema, and replaces the broken catch-all rewrite with known SPA routes targeting '/'. Unmatched paths can now reach the generated 404 page instead of becoming soft 404s.

vercel.json

Other (1) +1 / -1
package-lock.jsonSynchronize lockfile license metadata +1/-1

Synchronize lockfile license metadata

• Changes the root package license metadata from MIT to AGPL-3.0-or-later to match the project manifest.

package-lock.json

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've left some high level feedback:

  • The SPA routes now exist both in SPA_ROUTES (for shell generation) and in vercel.json (for rewrites); consider centralizing them in a single source of truth (or generating one from the other) to avoid future drift when routes change.
  • The 404 page’s large inline SVG and HTML string inside render404Page make the generator script quite dense; consider extracting this markup into a separate template/module or at least breaking it into smaller helpers to keep generate-seo-pages.mjs easier to scan and modify.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The SPA routes now exist both in `SPA_ROUTES` (for shell generation) and in `vercel.json` (for rewrites); consider centralizing them in a single source of truth (or generating one from the other) to avoid future drift when routes change.
- The 404 page’s large inline SVG and HTML string inside `render404Page` make the generator script quite dense; consider extracting this markup into a separate template/module or at least breaking it into smaller helpers to keep `generate-seo-pages.mjs` easier to scan and modify.

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

@qodo-code-review

qodo-code-review Bot commented Jul 29, 2026

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (0) 📎 Requirement gaps (0) 🎨 UX issues (0) 🔗 Cross-repo conflicts (0) 📜 Skill insights (0)

Grey Divider


Remediation recommended

1. Invalid shares return homepage ✓ Resolved 🐞 Bug ≡ Correctness
Description
The /s/:slug rewrite accepts any single-segment slug, while parsePath rejects malformed slugs
and defaults them to the landing view. Requests such as /s/x or /s/foo.bar therefore return the
homepage with HTTP 200 instead of the generated 404 page.
Code

vercel.json[15]

+    { "source": "/s/:slug", "destination": "/" }
Evidence
The rewrite matches arbitrary single-segment values under /s/, but the SPA recognizes only slugs
matching its 6–64 URL-safe-character expression and otherwise renders the landing page. Generated
links use exactly 24 lowercase hexadecimal characters, and the SEO generator explicitly expects
unmatched routes to fall through to the custom 404.

vercel.json[11-15]
App.tsx[83-93]
services/shares.ts[27-35]
scripts/generate-seo-pages.mjs[496-501]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The `/s/:slug` rewrite routes malformed share paths into the SPA. Because the client parser treats invalid slugs as the landing route, these URLs return the homepage with HTTP 200 rather than the generated 404 response.

## Issue Context
Generated share IDs are 24 lowercase hexadecimal characters. The server-side rewrite should match the application's accepted share format—or preferably the generated format—so malformed share URLs fall through to `dist/404.html`.

## Fix Focus Areas
- vercel.json[11-15]
- App.tsx[83-93]
- services/shares.ts[27-35]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

To customize comments, go to the Qodo configuration screen, or learn more in the docs.

Qodo Logo

Comment thread vercel.json Outdated

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Restores correct production behavior on Vercel by ensuring the full build pipeline runs (including SEO/static page generation), SPA routes resolve without the cleanUrls redirect trap, and serverless functions work under Node ESM by using explicit .js specifiers.

Changes:

  • Configure Vercel to run npm run build and replace the SPA catch-all rewrite with explicit SPA route rewrites.
  • Enhance the SEO/static generator to support configurable robots and to emit a custom dist/404.html.
  • Fix Vercel serverless function imports by adding explicit .js extensions for ESM module resolution; add “Diagrams” navigation entry points.

Reviewed changes

Copilot reviewed 10 out of 11 changed files in this pull request and generated no comments.

Show a summary per file
File Description
vercel.json Ensures the full build runs on Vercel and rewrites only known SPA routes to /, allowing unknown paths to fall through to a real 404.
scripts/generate-seo-pages.mjs Documents deployment behavior, adds configurable robots meta, and generates dist/404.html alongside sitemap + route shells.
package-lock.json Updates lock metadata to reflect AGPL licensing.
components/LandingPage.tsx Adds direct navigation links to the prerendered /diagrams hub.
api/webhooks/polar.ts Adds explicit .js extensions for internal ESM imports.
api/usage.ts Adds explicit .js extension for supabase admin import to fix ESM resolution on Vercel.
api/portal.ts Adds explicit .js extensions for internal ESM imports.
api/generate.ts Adds explicit .js extensions for internal ESM imports.
api/delete-account.ts Adds explicit .js extensions for internal ESM imports.
api/checkout.ts Adds explicit .js extensions for internal ESM imports.
api/_lib/supabaseAdmin.ts Adds explicit .js extension for entitlement import to fix ESM resolution on Vercel.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 11 files

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread vercel.json Outdated
/s/:slug matched any single path segment, but parsePath only treats
[A-Za-z0-9_-]{6,64} as a share route. Anything else, /s/x or /s/foo.bar,
was rewritten to the app and rendered as the landing page with a 200,
where it should have reached the 404 page.

The pattern mirrors parsePath rather than the narrower 24-hex format
shares are actually minted in. If the two disagreed, the edge would reject
links the client can still open, and the client is what decides whether a
share resolves.
Serving the SPA's routes by name is what lets an unknown URL return a real
404, but it means a route added to parsePath and to neither SPA_ROUTES nor
vercel.json gets no shell and no rewrite. It then works perfectly in dev
and 404s in production, which is the same shape as the build command
override this branch started with: invisible locally, total in production.

The generator now reads the routes out of parsePath and checks each is
covered by a shell or a rewrite, and that some /s/ rewrite exists for
share links. It refuses to pass vacuously: if the regex stops finding the
routes, that is itself a failure rather than an empty list quietly
satisfying the check.

Verified by removing the /settings rewrite and separately by renaming the
/terms shell; each fails the build naming the route, and both pass again
once restored.

Raised by review as SPA_ROUTES and vercel.json duplicating each other.
They do not overlap: one holds the routes with prerendered shells, the
other those without. The risk is not drift between them but a route in
neither, which is what this checks. The review also suggested extracting
the 404 markup; every other page in this file is built the same way inline,
so moving one of them out would make the file less consistent, not more.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 2 files (changes from recent commits).

Tip: Review your code locally with the cubic CLI to iterate faster.

Re-trigger cubic

Comment thread scripts/generate-seo-pages.mjs Outdated
Comment thread scripts/generate-seo-pages.mjs Outdated
Both fair. The guard matched `pathname === 'literal'` in App.tsx, so a
route written any other way was silently absent from a check whose whole
job is catching absent routes, and it leaned on a hard floor of five
routes to notice when the scrape stopped working, which couples build
validity to how many routes the app happens to have.

Both problems are the regex. routes.mjs now holds the route table and the
share pattern; App.tsx routes with it and the generator imports it. There
is nothing left to extract, so nothing to miscount, and a route cannot be
spelled in a way the guard cannot see.

While the table was moving, the share pattern became checkable too: the
guard compares the character class in routes.mjs against the one in the
vercel.json rewrite. A stricter edge rejects links the client can open, a
looser one hands the app URLs it will not route, and those render as the
landing page rather than a 404. That agreement was a comment before.

Verified by breaking each branch in turn: a route with nothing serving it,
a removed rewrite, an edge pattern narrowed to {24,24}, and no /s/ rewrite
at all. Each fails the build naming the specific fault, and the build
passes again once restored.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@App.tsx`:
- Around line 84-94: Update parsePath to handle the root pathname explicitly as
the landing view, while preserving configured routes and SHARE_PATH matches. For
every other unmatched pathname, return the 404 state instead of defaulting to
landing, using the existing ViewType value or 404 rendering mechanism.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 7073e17a-302a-4f46-92e3-e7dd66221e64

📥 Commits

Reviewing files that changed from the base of the PR and between b15a281 and 28c7541.

📒 Files selected for processing (4)
  • App.tsx
  • routes.mjs
  • scripts/generate-seo-pages.mjs
  • vercel.json
🚧 Files skipped from review as they are similar to previous changes (1)
  • vercel.json

Comment thread App.tsx
navigateToView took any ViewType and pushed `/${newView}`, which assumes both
that a view's name is its path segment and that every view has a path. 'shared'
breaks the second: you reach it by opening a share link, there is no /shared
rewrite, so pushing it would work until the first reload and then 404 at the
edge. No caller does that today, but nothing stopped one.

Read the path out of the shared route table instead, and exclude 'shared' from
the parameter type so navigating somewhere unservable is a compile error rather
than a production-only 404.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 3 files (changes from recent commits).

Tip: Review your code locally with the cubic CLI to iterate faster.

Re-trigger cubic

Comment thread App.tsx Outdated
Comment thread routes.mjs
The previous commit's comment claimed excluding 'shared' made an unservable
navigation a compile error. That holds for 'shared' alone: RoutableView
subtracts from ViewType, so a view added later joins it automatically, and the
`?? '/'` fallback would then push / while showing the new view, a URL and view
mismatch that hides the missing route until someone reloads.

Resolve the path before committing to the view, and refuse to navigate if there
is none. Staying put is poor, but it is a visible fault rather than a URL that
404s on the next reload.

That is the runtime backstop. The build guard now does the real work, checking
ViewType against the route table so the case cannot ship: it previously only
checked table -> deployment, which cannot see a view the table never mentions.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 2 files (changes from recent commits).

Tip: Review your code locally with the cubic CLI to iterate faster.
Tip: cubic used a learning from your PR history. Let your coding agent read cubic learnings directly with the cubic MCP.

Re-trigger cubic

Comment thread scripts/generate-seo-pages.mjs Outdated
Comment thread scripts/generate-seo-pages.mjs
Two gaps in yesterday's guard, both found by review.

Reading only single-quoted members meant a double-quoted ViewType would parse
to an empty list and satisfy the check vacuously, which is the same failure the
"could not find the alias" branch exists to prevent. Quote style is formatting,
so accept either.

The view -> table check also only reported views with no route. Retyping an
existing view's name is caught by that, since the real view then looks stranded,
but adding an entry that names a view which does not exist leaves coverage
intact and passed: `'/studio': 'studo'` built cleanly, would have been served,
and would have rendered as an unknown view rather than a 404. Compare the other
way as well so the two sets have to agree exactly.
A production-only bugfix release: the deployed site served a 404 for every
page but the homepage, and none of the API functions could start. Both were
invisible locally, so 1.1.0 shipped with them.
@Sukarth
Sukarth merged commit 6c7d490 into main Jul 29, 2026
4 of 5 checks passed
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.

2 participants