A clean full-stack starter running on vinext, with optional Cloudflare D1 and Drizzle support.
>=22.13.0npm install
npm run dev
npm run build
This starter does not use wrangler.jsonc.
app/.openai/hosting.json declares optional Sites D1 and R2 bindingsvite.config.ts simulates declared bindings for local developmentdb/schema.ts starts intentionally emptyexamples/d1/ contains an optional D1 example surfacedrizzle.config.ts supports local migration generation when needed/api/catalog-sync is the platform catalog refresh contract. It tries the
configured Traxsource and Beatport label URLs, returns normalized release
rows, and falls back to the curated catalog when a source blocks or times out./api/news is the News tab aggregation contract. Set comma-separated
SOCIAL_FEED_URLS to RSS, Atom, JSON Feed, or simple JSON endpoints; the UI
auto-refreshes every five minutes.https://www.labelradar.com/labels/LukuluRecordings/portal.previewUrl fields in catalog data.
Until platform preview URLs are available, it keeps track metadata, Buy links,
and Stream links active while disabling playback honestly.Optional production env vars:
TRAXSOURCE_LABEL_URL=https://www.traxsource.com/label/53294/lukulu-recordings
BEATPORT_LABEL_URL=https://www.beatport.com/label/lukulu-recordings/53294
SOCIAL_FEED_URLS=
OpenAI workspace sites can read the current user’s email from
oai-authenticated-user-email.
SIWC-authenticated workspace sites may also receive
oai-authenticated-user-full-name when the user’s SIWC profile has a non-empty
name claim. The full-name value is percent-encoded UTF-8 and is accompanied by
oai-authenticated-user-full-name-encoding: percent-encoded-utf-8.
Treat the full name as optional and fall back to email when it is absent:
import { headers } from "next/headers";
export default async function Home() {
const requestHeaders = await headers();
const email = requestHeaders.get("oai-authenticated-user-email");
const encodedFullName = requestHeaders.get("oai-authenticated-user-full-name");
const fullName =
encodedFullName &&
requestHeaders.get("oai-authenticated-user-full-name-encoding") ===
"percent-encoded-utf-8"
? decodeURIComponent(encodedFullName)
: null;
const displayName = fullName ?? email;
// ...
}
Import the ready-to-use helpers from app/chatgpt-auth.ts when the site needs
optional or required ChatGPT sign-in:
getChatGPTUser() for optional signed-in UI.requireChatGPTUser(returnTo) for server-rendered pages that should send
anonymous visitors through Sign in with ChatGPT.chatGPTSignInPath(returnTo) and chatGPTSignOutPath(returnTo) for
browser links or actions.returnTo path for the destination after sign-in
or sign-out. The helper validates and safely encodes it.export const dynamic = "force-dynamic" because
they depend on per-request identity headers.Dispatch owns /signin-with-chatgpt, /signout-with-chatgpt, /callback, the
OAuth cookies, and identity header injection. Do not implement app routes for
those reserved paths. Routes that do not import and call the helper remain
anonymous-compatible.
SIWC establishes identity only; it does not prove workspace membership. Use the Sites hosting platform’s access policy controls for workspace-wide restrictions, or enforce explicit server-side membership or allowlist checks.
Use SIWC for account pages, user-specific dashboards, saved records, and write actions tied to the current ChatGPT user. Leave public content anonymous.
npm run dev: start local developmentnpm run build: verify the vinext build outputnpm test: build the starter and verify its rendered loading skeletonnpm run db:generate: generate Drizzle migrations after schema changes