mirror of
https://github.com/stack-auth/stack.git
synced 2026-06-21 21:09:49 +08:00
## Summary
Two related improvements to Stack Auth's AI setup story, both driven by
`packages/stack-shared/src/ai/prompts.ts`:
### 1. Clearer env-var guidance in the cloud-project flow (existing
commit)
The previous wording suggested `STACK_PROJECT_ID` should be prefixed via
a generic _"if available, prefix with your framework's convention"_
comment, and the backend section additionally listed
`NEXT_PUBLIC_STACK_PUBLISHABLE_CLIENT_KEY` — which the SDK does not
actually read in the cloud-project setup. Agents would dutifully
fabricate that third variable.
This is now spelled out:
- The exact prefix per framework (Next.js →
`NEXT_PUBLIC_STACK_PROJECT_ID`, Vite → `VITE_STACK_PROJECT_ID`, etc.) is
given inline.
- A note clarifies that on the client, **only** the project ID is read —
there is no separate publishable / client key.
- A note clarifies that the backend setup reads exactly two variables
(`STACK_PROJECT_ID` + `STACK_SECRET_SERVER_KEY`); a third slot in
`.env.local` is wrong.
### 2. First-class TanStack Start support (new commit)
Until now `mainType: "tanstack-start"` was silently routed through
`@stackframe/react` and inherited the React-only setup steps. Agents had
to guess at the TanStack-specific bits (where to mount `StackProvider`,
what to do with `routeTree.gen.ts`, how `useUser()` behaves under SSR,
where the handler route lives).
`prompts.ts` now:
- Recognizes TanStack Start as its own `mainType` and routes the install
to `@stackframe/tanstack-start`.
- Lists TanStack Start alongside Next.js / React in the
supported-frameworks list and the package table.
- Adds three TanStack-specific steps that don't apply to vanilla React:
1. Mount `StackProvider` / `StackTheme` inside the root route's
`component` (the inner React tree), keeping `shellComponent` as the
document shell.
2. Wrap `<Outlet />` in `Suspense` inside `RootComponent`.
3. Register the Stack handler splat at `src/routes/handler/\$.tsx` with
`ssr: false`.
- Surfaces the two notes that aren't obvious from the React docs:
`routeTree.gen.ts` is generated and shouldn't be hand-edited, and
`useUser()` resolves the SSR user from TanStack Start's request cookies
for free as long as `tokenStore: \"cookie\"` is set.
The auto-generated outputs
(`docs-mintlify/guides/getting-started/setup.mdx`,
`docs-mintlify/snippets/home-prompt-island.jsx`) are regenerated from
the prompt.
### 3. tanstack-start-demo SSR-vs-client examples
Two paired routes (`/ssr` and `/client`) render the same `AuthDemoCard`
so the SSR-vs-\`ssr: false\` tradeoff is observable side-by-side. The
new \`AuthDemoCard\` shows the resolved Stack Auth user (or sign-in/up
buttons) plus the snippet that produced it. The
\`ClientMountedUserButton\` workaround in the header is dropped now that
SSR cookie reading just works, and the empty \`Suspense
fallback={null}\` in \`__root.tsx\` is replaced with a
\`RouteLoadingState\` skeleton.
## Test plan
- [ ] \`pnpm typecheck\` and \`pnpm lint\` both pass on the touched
packages (\`stack-shared\`, \`tanstack-start-demo\`).
- [ ] \`docs-mintlify/guides/getting-started/setup.mdx\` and
\`docs-mintlify/snippets/home-prompt-island.jsx\` are byte-identical to
a fresh \`scripts/generate-setup-prompt-docs.ts\` run.
- [ ] In \`tanstack-start-demo\`, \`/ssr\` renders the user card during
the server response (no flash from signed-out → signed-in), and
\`/client\` renders the empty card on first paint, then resolves to the
user after hydration.
- [ ] \`/handler/sign-in\`, \`/handler/sign-up\`, OAuth callbacks, and
password reset all render correctly through the new splat route.
- [ ] Following the new TanStack Start prompt steps from scratch in an
empty \`npm create @tanstack/start@latest\` project produces a working
sign-in flow without any extra changes.
Made with [Cursor](https://cursor.com)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Added TanStack Start support, provider/theme wiring, SSR and
client-only demo pages, plus an Auth demo card component.
* **Documentation**
* Updated setup guides and snippets across frameworks; clarified env-var
guidance (client reads only project ID; secret is server-only) and
removed misleading publishable-key example.
* Clarified OAuth callback and hosted-domain behavior.
* **Improvements**
* Added loading skeleton UI, refined demo navigation, and tightened
setup wording.
<!-- review_stack_entry_start -->
[](https://app.coderabbit.ai/change-stack/hexclave/stack-auth/pull/1438?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack)
<!-- review_stack_entry_end -->
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---------
Co-authored-by: Cursor <cursoragent@cursor.com>
141 lines
4.0 KiB
TypeScript
141 lines
4.0 KiB
TypeScript
/* eslint-disable */
|
|
|
|
// @ts-nocheck
|
|
|
|
// noinspection JSUnusedGlobalSymbols
|
|
|
|
// This file was automatically generated by TanStack Router.
|
|
// You should NOT make any changes in this file as it will be overwritten.
|
|
// Additionally, you should also exclude this file from your linter and/or formatter to prevent it from being checked or modified.
|
|
|
|
import { Route as rootRouteImport } from './routes/__root'
|
|
import { Route as SsrRouteImport } from './routes/ssr'
|
|
import { Route as ProtectedRouteImport } from './routes/protected'
|
|
import { Route as ClientRouteImport } from './routes/client'
|
|
import { Route as IndexRouteImport } from './routes/index'
|
|
import { Route as HandlerSplatRouteImport } from './routes/handler/$'
|
|
|
|
const SsrRoute = SsrRouteImport.update({
|
|
id: '/ssr',
|
|
path: '/ssr',
|
|
getParentRoute: () => rootRouteImport,
|
|
} as any)
|
|
const ProtectedRoute = ProtectedRouteImport.update({
|
|
id: '/protected',
|
|
path: '/protected',
|
|
getParentRoute: () => rootRouteImport,
|
|
} as any)
|
|
const ClientRoute = ClientRouteImport.update({
|
|
id: '/client',
|
|
path: '/client',
|
|
getParentRoute: () => rootRouteImport,
|
|
} as any)
|
|
const IndexRoute = IndexRouteImport.update({
|
|
id: '/',
|
|
path: '/',
|
|
getParentRoute: () => rootRouteImport,
|
|
} as any)
|
|
const HandlerSplatRoute = HandlerSplatRouteImport.update({
|
|
id: '/handler/$',
|
|
path: '/handler/$',
|
|
getParentRoute: () => rootRouteImport,
|
|
} as any)
|
|
|
|
export interface FileRoutesByFullPath {
|
|
'/': typeof IndexRoute
|
|
'/client': typeof ClientRoute
|
|
'/protected': typeof ProtectedRoute
|
|
'/ssr': typeof SsrRoute
|
|
'/handler/$': typeof HandlerSplatRoute
|
|
}
|
|
export interface FileRoutesByTo {
|
|
'/': typeof IndexRoute
|
|
'/client': typeof ClientRoute
|
|
'/protected': typeof ProtectedRoute
|
|
'/ssr': typeof SsrRoute
|
|
'/handler/$': typeof HandlerSplatRoute
|
|
}
|
|
export interface FileRoutesById {
|
|
__root__: typeof rootRouteImport
|
|
'/': typeof IndexRoute
|
|
'/client': typeof ClientRoute
|
|
'/protected': typeof ProtectedRoute
|
|
'/ssr': typeof SsrRoute
|
|
'/handler/$': typeof HandlerSplatRoute
|
|
}
|
|
export interface FileRouteTypes {
|
|
fileRoutesByFullPath: FileRoutesByFullPath
|
|
fullPaths: '/' | '/client' | '/protected' | '/ssr' | '/handler/$'
|
|
fileRoutesByTo: FileRoutesByTo
|
|
to: '/' | '/client' | '/protected' | '/ssr' | '/handler/$'
|
|
id: '__root__' | '/' | '/client' | '/protected' | '/ssr' | '/handler/$'
|
|
fileRoutesById: FileRoutesById
|
|
}
|
|
export interface RootRouteChildren {
|
|
IndexRoute: typeof IndexRoute
|
|
ClientRoute: typeof ClientRoute
|
|
ProtectedRoute: typeof ProtectedRoute
|
|
SsrRoute: typeof SsrRoute
|
|
HandlerSplatRoute: typeof HandlerSplatRoute
|
|
}
|
|
|
|
declare module '@tanstack/react-router' {
|
|
interface FileRoutesByPath {
|
|
'/ssr': {
|
|
id: '/ssr'
|
|
path: '/ssr'
|
|
fullPath: '/ssr'
|
|
preLoaderRoute: typeof SsrRouteImport
|
|
parentRoute: typeof rootRouteImport
|
|
}
|
|
'/protected': {
|
|
id: '/protected'
|
|
path: '/protected'
|
|
fullPath: '/protected'
|
|
preLoaderRoute: typeof ProtectedRouteImport
|
|
parentRoute: typeof rootRouteImport
|
|
}
|
|
'/client': {
|
|
id: '/client'
|
|
path: '/client'
|
|
fullPath: '/client'
|
|
preLoaderRoute: typeof ClientRouteImport
|
|
parentRoute: typeof rootRouteImport
|
|
}
|
|
'/': {
|
|
id: '/'
|
|
path: '/'
|
|
fullPath: '/'
|
|
preLoaderRoute: typeof IndexRouteImport
|
|
parentRoute: typeof rootRouteImport
|
|
}
|
|
'/handler/$': {
|
|
id: '/handler/$'
|
|
path: '/handler/$'
|
|
fullPath: '/handler/$'
|
|
preLoaderRoute: typeof HandlerSplatRouteImport
|
|
parentRoute: typeof rootRouteImport
|
|
}
|
|
}
|
|
}
|
|
|
|
const rootRouteChildren: RootRouteChildren = {
|
|
IndexRoute: IndexRoute,
|
|
ClientRoute: ClientRoute,
|
|
ProtectedRoute: ProtectedRoute,
|
|
SsrRoute: SsrRoute,
|
|
HandlerSplatRoute: HandlerSplatRoute,
|
|
}
|
|
export const routeTree = rootRouteImport
|
|
._addFileChildren(rootRouteChildren)
|
|
._addFileTypes<FileRouteTypes>()
|
|
|
|
import type { getRouter } from './router.tsx'
|
|
import type { createStart } from '@tanstack/react-start'
|
|
declare module '@tanstack/react-start' {
|
|
interface Register {
|
|
ssr: true
|
|
router: Awaited<ReturnType<typeof getRouter>>
|
|
}
|
|
}
|