Commit Graph
5 Commits
Author SHA1 Message Date
Alaister YoungandAlaister Young 2d5ec97df8 chore: split CLAUDE.md into root and studio-specific files (#48202)
Splits agent guidance into a lean monorepo-wide root file and a
studio-specific file that Claude Code lazy-loads when working under
`apps/studio/`. This keeps every session's baseline context small while
giving studio work much richer, enforceable guidance.

**Changed:**
- `.claude/CLAUDE.md` — now monorepo-wide only: corrected pnpm version
(10 → 11), expanded workspace table (design-system, ui-library,
lite-studio, ui-patterns, api-types, pg-meta, shared-data), commands
(`format`, `generate:types`, `api:codegen`), CI gates + never-hand-edit
generated files, monorepo-wide conventions (incl. the named-exports
rule, which lives in the shared eslint preset and applies to all six
apps), and monorepo-wide skill triggers. Studio detail is replaced by a
pointer to the nested file. Also corrects a long-standing error
inherited from the old file: the `_Shadcn_` convention was inverted —
`Button_Shadcn_` is the only suffixed export left and is rarely the
right choice; primitives are unsuffixed.
- `.claude/skills/studio-ui-patterns/SKILL.md` — removed the same stale
`_Shadcn_` claim from the forms section (this skill also feeds
CodeRabbit reviews).
- `apps/studio/components/README.md` — component template now uses a
named export, matching the lint-enforced convention (was the one doc
still showing `export default`).
- `apps/studio/TANSTACK_MIGRATION.md` — cleanup checklist gains an item
to remove the migration section from `apps/studio/CLAUDE.md` when the
migration finishes.
- `.gitignore` — removed the blanket `CLAUDE.md` ignore rule (added in
#40231 for personal local files, no longer used that way). Nested
`CLAUDE.md` files are now tracked by default, so shared guidance can't
silently fail to land. For *personal* notes, use `CLAUDE.local.md`
(Claude Code loads it automatically alongside `CLAUDE.md`, and it's now
gitignored here) — or `.git/info/exclude` if you prefer a different
filename.

**Added:**
- `apps/studio/CLAUDE.md` — studio guidance, loaded on demand: mandatory
skill routing (always load `studio-best-practices`, plus a task → skill
table), TanStack Start migration rules (pages/routes mirroring, when a
manual mirror is needed, never delete `pages/**` files),
data-layer/state orientation, a default-to-shipping-tests-with-changes
policy, and a "defaults that differ here" list (ESLint warning ratchet +
local `lint:ratchet` command, `copyToClipboard` await rule, `useParams`
from `common`, dayjs/sonner, `ui` vs `ui-patterns` import split,
`@tanstack/react-table` over `react-data-grid`, etc.).

## Accuracy

Every factual claim in both files (62 total) was verified against the
code by parallel review agents instructed to refute each one. Results:
54 correct as written, 2 wrong (the inherited `_Shadcn_` inversion, and
a fabricated `useExecuteSqlQuery` hook name — the real export is
`useExecuteSqlMutation`), 6 imprecise (e.g. dayjs plugins load in both
runtime entries, the ratchet counts occurrences regardless of severity).
All fixed in this PR.

## Context cost

| File | Size | When it loads | % of a 200k window |
|---|---|---|---|
| `.claude/CLAUDE.md` | 70 lines, ~1.2k est. tokens | every session |
~0.6% |
| `apps/studio/CLAUDE.md` | 53 lines, ~1.6k est. tokens | only when
touching studio files | ~0.8% |

The always-loaded footprint grew only ~0.2k est. tokens vs the old
45-line file — everything studio-heavy sits behind the lazy load, so
docs/www sessions pay nothing for it. Both files are well under Claude
Code's large-file warning threshold (~40k chars) and the <200-line
adherence guidance, with room to roughly double before it's worth
worrying about.

## To test

- Open a fresh Claude Code session from the repo root and read any file
under `apps/studio/` — `apps/studio/CLAUDE.md` should get pulled into
context automatically.
- `git check-ignore apps/studio/CLAUDE.md` exits 1 (not ignored); `git
check-ignore CLAUDE.local.md` exits 0 (ignored).
- Skim both files — every claim has been code-verified (see Accuracy
above), but a human sanity pass on the *judgment* calls (what's
included/omitted) is welcome.

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **Documentation**
* Refreshed monorepo onboarding conventions with updated tooling
requirements, expanded inventory, standardized common scripts, and
clearer CI gating and checks.
* Added/updated Studio contributor guidance, including the TanStack
Start migration rules and Studio development/testing/UI conventions.
  * Updated Studio component documentation to use named exports.
* Refreshed the “Forms” UI pattern guidance and adjusted the referenced
UI primitives.
* **Chores**
* Updated ignore rules so the primary top-level onboarding document is
tracked.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com>
2026-07-23 01:49:22 +08:00
Danny WhiteandJoshen Lim 0324f3422a chore(studio): polish vercel deploy-button new project interstitial (#48113)
## I have read the
[CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md)
file.

YES

## What kind of change does this PR introduce?

Studio UI polish for the Vercel deploy-button new-project connect flow
(DEPR-616 follow-up).

## What is the current behavior?

- Deploy-button project creation still used
`VercelIntegrationWindowLayout` (top bar + Docs/Support footer) while
install and choose-project already use shared `InterstitialLayout`
- The remove-integration note sat as a floating admonition above the
form
- Advanced / internal-only config sections could show double dividers,
and the Oriole radio bottom border could clip inside the collapsible

## What is the new behavior?

- Deploy-button new-project uses `InterstitialLayout` with
`VercelIntegrationLogo` and `VercelIntegrationFooter`, matching the
other Vercel connect surfaces
- Regular `/new` project creation is unchanged; Panel chrome is only
flattened when `isVercelIntegrationFlow` is set
- Removes unused `VercelIntegrationWindowLayout` /
`IntegrationWindowLayout`
- Fixes Advanced/Internal-only dividers and collapsible border clipping

| Before | After |
| --- | --- |
| <img width="965" height="1107" alt="Supabase"
src="https://github.com/user-attachments/assets/99c1225c-c9e5-4fac-bd64-17920403e447"
/> | <img width="965" height="1107" alt="Create Vercel Project Supabase"
src="https://github.com/user-attachments/assets/c42bff96-5f9f-4c8b-8f3c-093e380f90ed"
/> |

## Additional context

### Testing

With Studio running locally and while signed in:

1. Open
`http://localhost:8082/integrations/vercel/<your-org-slug>/deploy-button/new-project`
2. Confirm the interstitial card: Vercel + Supabase logo pair, “Create a
new project” title, form fields, and the muted remove-integration footer
under the card
3. Confirm there is no old window chrome (no “Marketplace Connector” /
“Deploy Button” top bar, no Docs/Support footer)
4. Optionally submit and confirm project creation still works
5. Spot-check `/new` to confirm the normal project creation form is
unchanged

If you have advanced config enabled, expand Advanced Configuration and
confirm single dividers (not doubles) and that the Oriole option’s
bottom border is not clipped.

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

## Summary by CodeRabbit

* **New Features**
* Added configurable width to the shared interstitial layout for Vercel
project creation.
  * Updated the Vercel “new project” flow to use the interstitial UI.

* **Bug Fixes**
* Prevented child borders/shadows from being clipped in expandable
configuration sections.

* **Refactor**
* Removed legacy Vercel/window layout components and updated routing to
rely on the interstitial flow.
* Switched advanced and internal-only configuration sections to render
inside panel content.

* **Documentation**
* Refreshed Vercel integration route guidance in the migration checklist
and inline route comments.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Joshen Lim <joshenlimek@gmail.com>
2026-07-22 00:08:00 +10:00
18431efb25 fix(studio): TanStack post-merge fixes — Monaco loader, fonts, CSP (from #46424) (#47657)
Post-merge fixes for the TanStack Start migration (#46424) — things that
broke on the TanStack build as master evolved under the migration
branches. Kept on their own branch off master rather than piling onto
the E2E-matrix PR (#47119); all land on master and cascade up to S6 +
the big PR.

Common theme: a master PR changed something the Next pipeline handles
via `next/font` / `pages/_app.tsx` / `next.config.ts`, but the
hand-rolled TanStack equivalent (`routes/__root.tsx`,
`styles/fonts.css`, `vercel.ts`) wasn't updated to match — invisible on
the Next deploy, broken only on TanStack.

---

## 1. Monaco loader path (#47182)

#47182 re-nested the served Monaco assets from a flat
`public/monaco-editor/` layout into `public/monaco-editor/vs/` and
updated `pages/_app.tsx`, but `routes/__root.tsx` still pointed
`loader.config` at the old path, so `loader.js` 404'd and **no Monaco
editor mounted anywhere in the TanStack build**. Now mirrors the Next
config (`${origin}${BASE_PATH}/monaco-editor/vs`, window-guarded for
SSR). Was failing the whole `tanstack` E2E shard on #47119.

## 2. Inter + Manrope fonts (#47306)

#47306 renamed Tailwind's sans var `--font-custom` → `--font-sans` and
added `--font-heading` (Manrope), set via `next/font` on Next.
`fonts.css` still only set the now-ignored `--font-custom`, so the body
fell back to the theme's system chain (`Circular, custom-font,
Helvetica…`) at weight 450 — that's the "Inter weights look wrong".
Manrope was missing entirely.

- Wire `--font-sans` (Inter) + `--font-heading` (Manrope) to match
`next/font`.
- **Vendor all three families** (Inter, Manrope, Source Code Pro) via
`@font-face` so nothing depends on the Google Fonts CDN — matches
`next/font` self-hosting, and (see below) `font-src` doesn't allow
`fonts.gstatic.com` anyway.

Verified in-browser: computed `body` → `Inter`, headings → `Manrope`,
all loading from local `/assets/*.woff2`.

## 3. Security headers / CSP (next.config.ts `headers()`)

The Next build sets X-Frame-Options / X-Content-Type-Options / HSTS /
**Content-Security-Policy** / Referrer-Policy via `next.config.ts`. The
TanStack build never carried these over — `vercel.ts` only set
cache-control, so **the deployed TanStack dashboard shipped with no CSP
at all**.

The TanStack deploy serves a static shell (no server to attach headers),
so they go in the Vercel config:
- `security-headers.ts` — shared source of truth, reuses `getCSP()`,
env-gated exactly like next.config.
- `vercel.ts` — apply to every response (all base-path prefixes): full
`getCSP()` + HSTS on platform.
- `scripts/serve.js` — the non-platform set (`frame-ancestors 'none'`)
for the self-hosted server.

**Tested the policy in a real browser** (temporarily enforced it on the
TanStack build via /test-supabase-local): everything passed except one
real gap — `font-src` was missing `data:`, so GraphiQL's bundled Monaco
codicon font and Stripe's payment-element fonts (both data: URIs) were
blocked (37 violations on a cold load). Added `data:` to `font-src` in
`csp.ts` → violations drop to zero, SQL editor Monaco renders clean.
That gap affects the Next build too.

---

## 4. `node:path` import crashing `/project/[ref]/merge`

Found by a full-site click-through of the TanStack build (all product
areas, ongoing — see below). `useEdgeFunctionsDiff.ts` +
`EdgeFunctionsDiffPanel.tsx` did `import { basename } from 'path'` in
client code. Webpack (Next) polyfills `path` in the browser; Vite
externalizes it, so the whole `/merge` route crashed with "Module
\"path\" has been externalized for browser compatibility". Replaced the
two `basename` call sites with a string helper. Verified in-browser:
`/merge` renders.

## 5. URL shape — Next-style search-param semantics + shim fixes

The dashboard produced malformed URLs vs the Next build (strange query
params, trailing slashes, `##` hashes). Root cause + audit verified
empirically against `@tanstack/react-router@1.170.10`; all fixed with
unit tests and browser-verified:

- **`createRouter` used TanStack's default JSON search codec** —
`?flag=true` became `?flag=%22true%22` via links, repeated
`?filter=…&filter=…` collapsed into a JSON array (breaking
multi-filter/sort table-editor URLs and the account-page round-trip,
which double-encoded), and search values arrived as numbers/booleans
where the app expects strings. New `lib/router-search-params.ts`
(Next-style: strings in, strings out, repeated keys → string[]) wired
into the router.
- **Link shim** (`compat/next/link.tsx`): `URL.hash` includes the
leading `#` while TanStack's `hash` prop adds its own → every
`href="…#section"` navigated to `##section` (hash-scroll broke);
`Object.fromEntries(searchParams)` dropped repeated query params. Both
fixed.
- **Trailing slash injected before the query** on every `?`-only
relative navigation (`/auth/providers/?provider=…`): fixed in the compat
router (prefix current pathname) and via a custom nuqs adapter
(`lib/nuqs-tanstack-adapter.tsx`) replacing the stock tanstack-router
adapter, whose `navigate({ to: '?…' })` writes hit the same TanStack
behavior (123 files use nuqs).
- **Pathname-less `router.push({ query })` leaked path params** — Next
re-consumes `ref`/`id` from `query` into the path pattern; the shim
didn't, yielding
`/editor/17597?schema=public&ref=<ref>&id=17597&filter=…` from
table-editor filter/sort, linter panels, and advisor shortcuts. The shim
now defaults the pathname to the current route pattern and backfills
omitted params.
- **Redirects dropped query + hash** (Next's `redirects()` preserves
them): `__root.tsx` `matchRedirect` and `routes/index.tsx` now carry
incoming params/hash through (consumed rule params excluded,
destination's own params win). `/?next=new-project&projectName=zzz` →
`/new/new-project?projectName=zzz`; `/sql/quickstarts?template=x#frag` →
`/sql/examples?template=x#frag`.

Browser-verified post-fix: advisors `?preset=WARN`, providers
`?provider=Google`, `?schema=auth` — all clean (no `/?`, no leaks);
repeated `filter` params survive hydration; `=true` unquoted; single
`#`.

## 6. TanStack `navigate` corrupting query values (Logs Explorer SQL
newline loss)

TanStack router-core treats a query string embedded in `navigate({ to
})` as part of the *path*: `decodePath` percent-decodes it and
`sanitizePathSegment` strips control characters, silently deleting every
`%0A`. Logs Explorer's SQL (`s` param) lost its newlines on Run/reload —
`order by timestamp desc` / `limit 5` glued into `desclimit 5`, which
then failed the LIMIT lint. Pre-existing on the TanStack build (the
stock nuqs adapter had the same shape); Next unaffected.

Fixed by never embedding query strings in `to`: the nuqs adapter and the
compat `router.push`/`replace`/`prefetch` (plus the `next/navigation`
shim) now pass search as an object through the app codec
(`splitInternalUrl` hoisted to `lib/internal-url.ts`). Guard test drives
a real `createRouter` with multi-line SQL through both producers.
Browser-verified: newlines survive the full Run → reload → re-Run cycle.

## 7. Integration overview markdown never loaded (all integrations)

`MarkdownContent` used a template-literal dynamic import
(``import(`@/static-data/integrations/${id}/overview.md`)``) — webpack
builds a context module for that, Vite can't analyze it, so every
integration detail page threw `Failed to resolve module specifier` and
rendered no overview text. Fixed with an explicit lazy registry of
literal imports (`static-data/integrations/overviews.ts`, drift-guarded
by a test) plus an `mdRawLoader()` Vite plugin mirroring next.config's
turbopack raw-loader rule. Both runtimes keep working; md stays out of
the main bundle.

## 8. GraphiQL editor never mounted (`exports is not defined`)

Our `umdAmdShortCircuit()` Vite plugin (which disarms Monaco's global
AMD loader for deps like papaparse) rewrote `typeof define ===
'function' && define.amd` to `false` inside `monaco-editor`'s bundled
copy of marked — whose UMD relies on its own *local* `define` shim — so
the whole optimized monaco chunk failed to evaluate and GraphiQL's
editor pane stayed blank. The check now only short-circuits when
`define` is the global AMD loader. Browser-verified: all four GraphiQL
Monaco panes mount, queries execute. (Known follow-up: GraphiQL's Monaco
workers fall back to the main thread under Vite — functional, worker
wiring is Next-specific `setup-workers/webpack`.)

## 9. `@sentry/nextjs` bundling Next internals — built TanStack bundle
crashed (caught by E2E)

The E2E suite against the **built** TanStack bundle (not the dev server)
found lazy chunks like `table-editor-*.js` dead on arrival:
`@sentry/nextjs` (imported by ~25 client files) drags in
`next/dist/shared/lib/constants`, whose module scope evaluates
`process?.features?.typescript` — optional chaining doesn't guard an
undeclared `process` in the browser, so the whole chunk failed at load
with `ReferenceError: process is not defined`. Dev shims `process`,
which is why weeks of dev-server testing never saw it.

Fixed by aliasing `@sentry/nextjs` → `compat/sentry-nextjs.ts`
(re-exports `@sentry/react`, same deduped 10.59.0, plus explicit
stand-ins for the three Next-only APIs) in the Vite build only.
Verified: fresh build has zero Next-internals markers in any chunk;
table editor loads clean; full E2E suite run against the built bundle.

Note for the stack: `alaister/tanstack-start` / the E2E-matrix branch
already carried a different fix for the same crash (a `next/constants`
shim) that never made it to master — the cherry-pick onto those branches
keeps **both** (the shim covers any other transitive importer; the alias
keeps Next internals out of the client bundle entirely).

**Follow-up found while fixing:** Sentry is never *initialized* in the
TanStack runtime — `instrumentation-client.ts` /
`sentry.server.config.ts` are Next-convention files nothing imports
under TanStack, so `captureException` calls are silent no-ops. Needs an
`@sentry/react` init (+ `tanstackRouterBrowserTracingIntegration`) wired
into the TanStack client entry as its own PR.

## 10. GraphiQL Monaco workers + edge-function Deno typings (Vite-only
gaps)

- **GraphiQL's Monaco workers ran on the main thread** under Vite
("Could not create web worker(s)…" — `setup-workers/webpack`'s `new
URL(...)` form isn't rewritten by Vite). A `graphiqlViteWorkers()`
plugin resolves the import to graphiql's own `setup-workers/vite`
variant for client builds (SSR untouched, Next untouched); the
setup-workers chain is `optimizeDeps.exclude`d because the Rolldown
optimizer can't load `?worker` ids.
- **Edge-function editors silently lost their Deno typings** —
`AIEditor` loaded `public/deno/*.d.ts` via `/* @vite-ignore */` imports
that always failed at runtime under Vite. The `.md` raw loader is
generalized into `rawTextLoader` (exact-path allowlist for the two
typings files, served as virtual string modules so the dep scanner never
parses `.d.ts` syntax), and the imports are now static-analyzable
literals that both bundlers handle (turbopack's raw-loader rules match
them on the Next side).

## Split out for reviewability

App-level fixes that reproduce on the Next build too (DOM-nesting
hydration errors, the ghost deleted-snippet nav, the recurring pg-meta
`migrations` 400) moved to their own PR: #47667. Sentry initialization
for the TanStack runtime (captures were silent no-ops) is #47666,
stacked on this PR.

## Full-site test campaign

Drove every dashboard product area on the local TanStack build
(Playwright, human-style) hunting migration regressions:
redirects/404/catch-alls, org, account, project home/branches/merge,
table editor CRUD, SQL editor (Monaco/run/save/templates/AI), all
database pages, all auth pages, storage CRUD, edge functions + realtime,
logs/observability, advisors, settings, integrations hub incl. nested
routes, global UI (palette/connect/switchers/theme/fonts), and a
cross-cutting sweep (document titles, back/forward chain, hard-refresh
hydration on deep URLs, trailing-slash active state). Every failure
found is fixed above and re-verified in-browser; remaining console
quirks were cross-checked against the deployed Next build and are
pre-existing (tracked separately).

## To test

Most fixes are already browser-verified + covered by unit tests and the
self-hosted E2E suite; the last two landed after the final browser pass
and still need an in-browser check:

1. **GraphiQL Monaco workers** — restart the dev server (clear
`apps/studio/node_modules/.vite` once first — the optimizer cache may
hold a stale prebundle of the worker chain). Open
`/project/<ref>/integrations/graphiql/graphiql` with the console open:
the `Could not create web worker(s). Falling back to loading web worker
code in main thread` warning must be gone, and DevTools → Sources →
Threads shows the three workers (json, editor, graphql). Autocomplete in
the query editor stays responsive.
2. **Edge-function Deno typings** — `/project/<ref>/functions/new`: no
"Failed to load … typings" console error, and typing `Deno.` in the
editor offers typed completions (e.g. `Deno.env`).

Spot-checks for the rest (all previously verified):
- `/project/<ref>/merge` renders (no "Module path" crash).
- Multi-line SQL in Logs Explorer survives Run → reload (no `desclimit`
gluing, no LIMIT-lint false failure); `s` param keeps `%0A`.
- `/auth/providers` → open a provider → `?provider=…` with no trailing
slash before `?`; table-editor filter/sort URLs carry no leaked
`ref`/`id` params; `/?next=new-project&projectName=x` lands on
`/new/new-project?projectName=x`.
- Integration detail pages (cron/queues/vault/data_api) show their
overview prose; GraphiQL query editor mounts.
- Built bundle (`MODE=test vite build` + `start:tanstack`): table editor
loads with no `process is not defined`.
- `curl -sI` any page on a platform deploy: `X-Content-Type-Options:
nosniff` (was the invalid `no-sniff`).


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Centralized integration overview markdown loading with registry-based
lookup.
* Improved Monaco loading/asset path handling for smoother editor
startup.
* **Bug Fixes**
* Next-style navigation/search handling now preserves pathname, hash,
repeated query keys, and special characters (including newlines).
* Redirects now reliably carry over query and hash with correct
precedence.
* **Security/Configuration**
* Updated CSP font sourcing and unified security headers delivery across
environments; conditional HSTS behavior.
* Refreshed font CSS variables and font-face definitions to match the
theme.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->


---

### Review feedback: non-prod favicon (Joshen)

The TanStack `__root.tsx` hardcoded the prod favicon; local + hosted
staging now use the white staging favicon (`/favicon/staging`), matching
what `pages/_app.tsx` passes to `MetaFaviconsPagesRouter` for non-prod.
Rather than pull the pages-router component into the TanStack head, it
reuses the same synchronous `NEXT_PUBLIC_ENVIRONMENT` signal the file
already uses for `IS_DEV_TOOLBAR_ENABLED` (the `head()` route option
isn't a React component, so it can't run `_app`'s async CLI check — but
the env signal covers the reported local/staging case).

---------

Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com>
Co-authored-by: Joshen Lim <joshenlimek@gmail.com>
2026-07-08 14:52:59 +08:00
Alaister YoungandAlaister Young 32798c3162 [FE-3423] chore(studio): flag pages/** edits to mirror into TanStack routes (#47650)
Adds a PR-time reminder to mirror any edit to `apps/studio/pages/**`
into the corresponding `apps/studio/routes/**` file, since the Next.js
pages router and the TanStack Start route tree ship side-by-side during
the migration and can silently drift.

**Added:**
- A CodeRabbit `path_instructions` rule (`.coderabbit.yaml`) scoped to
`apps/studio/pages/**` that prompts authors to check whether a page
change needs mirroring into `routes/**`. It encodes the migration's
nuance so it isn't noise — pure body edits on re-export (Path A) pages
propagate automatically, but layout/`getLayout`, `staticData` props,
`withAuth`, redirect-path, or new-page changes must be mirrored by hand.
Framed as verify-not-block, and explicitly tells authors *not* to delete
the `pages/**` file.

**Changed:**
- `apps/studio/TANSTACK_MIGRATION.md` — documents the guardrail under
the Runtime model section, and adds a cleanup-checklist line to remove
it once `pages/**` is deleted (FE-3106).

This is temporary scaffolding — it comes out with the final `pages/**`
cleanup pass.

## To test

- This needs to land on `master` first, then open a throwaway PR that
touches a file under `apps/studio/pages/**` and confirm CodeRabbit
leaves the reminder comment.
- `path_instructions` can be flaky — if CodeRabbit doesn't fire
reliably, the fallback is a GitHub Action + sticky PR comment scoped to
`paths: ['apps/studio/pages/**']`.

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Documentation**
* Added migration guidance for Studio page changes to help keep mirrored
routes in sync during the transition period.
* Clarified when page updates need to be reflected in the matching route
files, including new pages and changes to layout, access control,
titles, static data, or paths.
* Added a cleanup reminder for removing the temporary review guidance
once the migration is complete.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com>
2026-07-06 15:26:43 +00:00
9eab4f8fbf build(studio): Vite/TanStack-Start build pipeline behind flag (stack 1/6, from #46424) (#47107)
**Stack 1/6** of the TanStack Start migration (#46424), split into
reviewable, independently-mergeable PRs.

> [!IMPORTANT]
> **Next stays the default and only active framework after this PR.**
This wires up the Vite/TanStack-Start build pipeline behind the
`STUDIO_FRAMEWORK` flag, but there are no TanStack routes yet — so the
TanStack build isn't functional or tested until later PRs in the stack.
Nothing about the Next build, dev, or deploy changes behaviourally here.

## What's in this PR
- **Dispatch:** `dev`/`build`/`start` now go through
`scripts/dispatch.js`, which runs the Next variant unless
`STUDIO_FRAMEWORK=tanstack`. The original commands are preserved as
`dev:next`/`build:next`/`start:next`.
- **Build pipeline:** `vite.config.ts`, `serve.js`, `smoke-server.mjs`,
vite/tanstack deps, `turbo.jsonc`.
- **`tsconfig.json`:** `jsx: react-jsx`, `moduleResolution: Bundler`,
`target: ES2022`. Because `include` is `**/*.ts(x)`, this re-typechecks
the whole app, so the companion adaptations below land with it.
- **Shared adaptations (companions to the tsconfig change):**
`BufferSource` casts, `packages/ui` unused-`React` import removals, etc.
- **Routing/middleware plumbing:** `next.config.ts` +
`redirects.shared.ts` (redirect rules now shared with `vercel.ts`),
`proxy.ts`/`start.ts` middleware + `hosted-api-allowlist.ts`.

## Verification
Run locally off `master`: frozen install ✓, `studio` typecheck ✓, **Next
build ✓** (compiles + generates all routes), lint ratchet ✓ ("some rules
improved"), prettier ✓.


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Added a hosted API endpoint allowlist to return 404 for non-supported
`/api/*` routes.
* Introduced a TanStack route-migration checklist and expanded TanStack
Start routing support.
* **Improvements**
* Enhanced deployment refresh/detection by tightening cookie handling
for “latest deployment” updates.
* Centralized redirect/maintenance-mode rules for consistent platform vs
self-hosted behavior.
* Improved production serving with a dedicated static + proxy server and
a post-build smoke test.
* **Dependencies**
* Updated TanStack-related packages and React Table/query tooling
versions.
* **Documentation / Chores**
* Updated formatting and tooling config; added shared build environment
parsing utilities.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com>
Co-authored-by: Ivan Vasilov <vasilov.ivan@gmail.com>
2026-06-24 17:55:22 +08:00