Files
bsk/app/globals.css
tiennm99 b88147059e feat: scaffold Phase 0 foundation (Next.js 16 + Tailwind v4 + Supabase/Upstash)
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.
2026-05-25 10:58:04 +07:00

38 lines
940 B
CSS

@import "tailwindcss";
@theme {
--color-background: oklch(1 0 0);
--color-foreground: oklch(0.145 0 0);
--color-primary: oklch(0.205 0 0);
--color-primary-foreground: oklch(0.985 0 0);
--color-muted: oklch(0.97 0 0);
--color-muted-foreground: oklch(0.556 0 0);
--color-border: oklch(0.922 0 0);
--font-sans: ui-sans-serif, system-ui, sans-serif;
--font-mono: ui-monospace, "Courier New", monospace;
--radius: 0.5rem;
}
@media (prefers-color-scheme: dark) {
@theme {
--color-background: oklch(0.145 0 0);
--color-foreground: oklch(0.985 0 0);
--color-primary: oklch(0.985 0 0);
--color-primary-foreground: oklch(0.205 0 0);
--color-muted: oklch(0.269 0 0);
--color-muted-foreground: oklch(0.708 0 0);
--color-border: oklch(0.269 0 0);
}
}
html,
body {
height: 100%;
}
body {
background: var(--color-background);
color: var(--color-foreground);
font-family: var(--font-sans);
}