mirror of
https://github.com/stack-auth/stack.git
synced 2026-06-04 21:04:37 +08:00
Enhance TanStack Start integration and improve user experience
- Updated the default not found component in the TanStack Start demo to provide a user-friendly 404 page. - Refactored the Header component to use a client-mounted UserButton for better rendering performance. - Improved cookie handling in the template library to support dynamic imports for TanStack Start server APIs. - Added a new function to retrieve the server request host, enhancing compatibility with different platforms. These changes improve the overall integration of TanStack Start, enhance user experience, and ensure better performance across the application.
This commit is contained in:
parent
1e0e1df407
commit
6703f29d46
@ -361,6 +361,3 @@ A: Invalid `tools` entries are rejected by `requestBodySchema` in `apps/backend/
|
||||
|
||||
## Q: Why did the internal metrics E2E snapshots need to change in April 2026?
|
||||
A: The `/api/v1/internal/metrics` response now intentionally includes `analytics_overview.daily_anonymous_visitors_fallback`, `analytics_overview.anonymous_visitors_fallback`, and `active_users_by_country`. Those additions are reflected in `packages/stack-shared/src/interface/admin-metrics.ts` and the backend route, so the E2E snapshots must include them instead of treating them as regressions.
|
||||
|
||||
## Q: How should a TanStack Start SDK package be added without dragging Dashboard V2 logic into the same PR?
|
||||
A: Keep the integration PR scoped to generated package registration (`packages/tanstack-start/package.json`, `.gitignore`, `scripts/generate-sdks.ts`, `scripts/utils.ts`), template/package dependency metadata, and SDK runtime changes needed by TanStack Start (`cookie.ts`, token-store handling, handler SSR guard). Leave dashboard routes, hooks, app wiring, and admin API types in the dashboard PR.
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import { Link } from "@tanstack/react-router";
|
||||
import { UserButton } from "@stackframe/tanstack-start";
|
||||
import { useEffect, useState } from "react";
|
||||
|
||||
export function Header() {
|
||||
return (
|
||||
@ -14,10 +15,19 @@ export function Header() {
|
||||
Protected
|
||||
</Link>
|
||||
</nav>
|
||||
<UserButton />
|
||||
<ClientMountedUserButton />
|
||||
</div>
|
||||
</header>
|
||||
<div className="h-14" />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
function ClientMountedUserButton() {
|
||||
const [isMounted, setIsMounted] = useState(false);
|
||||
useEffect(() => {
|
||||
setIsMounted(true);
|
||||
}, []);
|
||||
|
||||
return isMounted ? <UserButton /> : <div className="h-9 w-9" />;
|
||||
}
|
||||
|
||||
@ -5,5 +5,14 @@ export function getRouter() {
|
||||
return createRouter({
|
||||
routeTree,
|
||||
scrollRestoration: true,
|
||||
defaultNotFoundComponent: () => (
|
||||
<main className="grid min-h-screen place-items-center bg-zinc-100 px-4 text-zinc-950 dark:bg-zinc-950 dark:text-zinc-50">
|
||||
<div className="w-full max-w-md rounded-lg border border-zinc-200 bg-white p-8 shadow-sm dark:border-zinc-800 dark:bg-zinc-900">
|
||||
<p className="mb-2 text-sm font-medium text-zinc-500 dark:text-zinc-400">404</p>
|
||||
<h1 className="text-2xl font-semibold tracking-tight">Page not found</h1>
|
||||
<p className="mt-4 text-zinc-600 dark:text-zinc-300">This route is not part of the TanStack Start demo.</p>
|
||||
</div>
|
||||
</main>
|
||||
),
|
||||
});
|
||||
}
|
||||
|
||||
@ -69,22 +69,23 @@ type DeleteCookieOptions = { noOpIfServerComponent?: boolean, domain?: string };
|
||||
|
||||
// IF_PLATFORM tanstack-start
|
||||
type TanStackStartServerCookieApi = typeof import("@tanstack/react-start/server");
|
||||
const tanStackStartServerCookieApiImportPath = "@tanstack/react-start/server";
|
||||
let tanStackStartServerCookieApiPromise: Promise<TanStackStartServerCookieApi> | null = null;
|
||||
let tanStackStartCookieHelperPromise: Promise<CookieHelper> | null = null;
|
||||
|
||||
declare global {
|
||||
// eslint-disable-next-line @typescript-eslint/consistent-type-definitions
|
||||
interface ImportMetaEnv {
|
||||
SSR: boolean,
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/consistent-type-definitions
|
||||
interface ImportMeta {
|
||||
readonly env: ImportMetaEnv,
|
||||
}
|
||||
}
|
||||
|
||||
async function getTanStackStartServerCookieApi(): Promise<TanStackStartServerCookieApi> {
|
||||
tanStackStartServerCookieApiPromise ??= import(tanStackStartServerCookieApiImportPath);
|
||||
tanStackStartServerCookieApiPromise ??= import(/* @vite-ignore */ "@tanstack/react-start/server");
|
||||
return await tanStackStartServerCookieApiPromise;
|
||||
}
|
||||
// END_PLATFORM
|
||||
|
||||
@ -84,6 +84,17 @@ const prefetchedCrossDomainHandoffTtlMs = 55 * 60 * 1000;
|
||||
|
||||
const allClientApps = new Map<string, [checkString: string | undefined, app: StackClientApp<any, any>]>();
|
||||
|
||||
async function getServerRequestHost(): Promise<string | null> {
|
||||
// IF_PLATFORM next
|
||||
return (await sc.headers?.())?.get("host") ?? null;
|
||||
// ELSE_IF_PLATFORM tanstack-start
|
||||
const api = await import(/* @vite-ignore */ "@tanstack/react-start/server");
|
||||
return api.getRequestHeader("host") ?? null;
|
||||
// ELSE_PLATFORM
|
||||
return null;
|
||||
// END_PLATFORM
|
||||
}
|
||||
|
||||
type StackClientAppImplConstructorOptionsResolved<HasTokenStore extends boolean, ProjectId extends string> = StackClientAppConstructorOptions<HasTokenStore, ProjectId> & { inheritsFrom?: undefined };
|
||||
|
||||
export class _StackClientAppImplIncomplete<HasTokenStore extends boolean, ProjectId extends string = string> implements StackClientApp<HasTokenStore, ProjectId> {
|
||||
@ -821,12 +832,9 @@ export class _StackClientAppImplIncomplete<HasTokenStore extends boolean, Projec
|
||||
let hostname;
|
||||
if (isBrowserLike()) {
|
||||
hostname = window.location.hostname;
|
||||
} else {
|
||||
hostname = await getServerRequestHost();
|
||||
}
|
||||
// IF_PLATFORM next
|
||||
else {
|
||||
hostname = (await sc.headers?.())?.get("host");
|
||||
}
|
||||
// END_PLATFORM
|
||||
if (!hostname) {
|
||||
console.warn("No hostname found when queueing custom refresh cookie update");
|
||||
return;
|
||||
@ -1031,7 +1039,7 @@ export class _StackClientAppImplIncomplete<HasTokenStore extends boolean, Projec
|
||||
protected _useTokenStore(overrideTokenStoreInit?: TokenStoreInit): Store<TokenObject> {
|
||||
// IF_PLATFORM tanstack-start
|
||||
if (!isBrowserLike()) {
|
||||
return this._getOrCreateTokenStore(use(createCookieHelper()), overrideTokenStoreInit);
|
||||
return this._getOrCreateTokenStore(use(createCookieHelper()), overrideTokenStoreInit);
|
||||
}
|
||||
// END_PLATFORM
|
||||
suspendIfSsr();
|
||||
|
||||
Loading…
Reference in New Issue
Block a user