mirror of
https://github.com/tiennm99/bsk.git
synced 2026-06-17 20:47:46 +00:00
b88147059e
Initial code drop for the BSK educational rewrite. Repo previously held only
docs (PLAN.md, README, NOTICE, LICENSE, RESEARCH_REPORT). This commit lands
the App Router shell, i18n route group, and shared-infra factories per the
Phase 0 plan.
Scaffold:
- Next.js 16 + React 19 + TypeScript 5.9, App Router, Turbopack defaults
- Tailwind v4 via @tailwindcss/postcss with CSS-first @theme block
- shadcn/ui CLI v4 (components.json + cn helper); components install lazily
- next-intl v4 with vi default + en fallback; async-params-aware routing
- proxy.ts (Next 16's renamed middleware) wired to next-intl
- lib/supabase/{server,client,admin,session}.ts on @supabase/ssr, schema-scoped
to 'bsk', async cookies(), server factory unsafe inside 'use cache'
- lib/upstash.ts: prefixed cache helpers and Ratelimit v2, QStash signature
verifier; future code cannot write unprefixed Redis keys
- lib/env/{client,server}.ts split so the secret key types stay server-side
- ESLint flat config (eslint-config-next/core-web-vitals + typescript +
prettier), Prettier with tailwindcss plugin, .npmrc + pnpm-workspace.yaml
for pnpm 11 native-build approval
- CI runs format:check, lint, typecheck, build on PR with dummy env
PLAN.md updates:
- §1 reconciled to TypeScript 5.9 (TS 6 is GA but lacks ecosystem support)
- §3.1 notes middleware → proxy file rename and removal of `next lint`
All four gates pass locally: format:check, lint, typecheck, build (SSG for
/vi and /en, Proxy detected). Code-reviewer findings applied: env split,
session helper renamed and docstring fixed, cache.set/del types tightened,
prettierignore scope reduced, bilingual GlobalNotFound, explanatory comments
on no-op layouts and duplicate setRequestLocale.
Deferred to Phase 1: wiring updateSupabaseSession into proxy.ts (needs auth
flow first), schema migrations, sign-in form.
35 lines
1010 B
TypeScript
35 lines
1010 B
TypeScript
import "server-only";
|
|
import { createServerClient } from "@supabase/ssr";
|
|
import { cookies } from "next/headers";
|
|
import { serverEnv, SUPABASE_SCHEMA } from "@/lib/env/server";
|
|
|
|
/**
|
|
* Per-request Supabase client for RSC and Server Actions.
|
|
* MUST be called outside a `'use cache'` scope — it depends on cookies().
|
|
*/
|
|
export async function createSupabaseServerClient() {
|
|
const cookieStore = await cookies();
|
|
|
|
return createServerClient(
|
|
serverEnv.NEXT_PUBLIC_SUPABASE_URL,
|
|
serverEnv.NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY,
|
|
{
|
|
db: { schema: SUPABASE_SCHEMA },
|
|
cookies: {
|
|
getAll() {
|
|
return cookieStore.getAll();
|
|
},
|
|
setAll(cookiesToSet) {
|
|
try {
|
|
for (const { name, value, options } of cookiesToSet) {
|
|
cookieStore.set({ name, value, ...options });
|
|
}
|
|
} catch {
|
|
// setAll throws from Server Components; the proxy-layer refresh handles it.
|
|
}
|
|
},
|
|
},
|
|
},
|
|
);
|
|
}
|