This document is for AI coding agents working on easyword.kr (쉬운 전문용어). It summarizes the architecture, constraints, and repeatable recipes to safely implement changes.
Read this alongside README.md and the codebase. Prefer server-driven data access via Supabase SSR and keep UI/UX copy in Korean.
- Dev:
bun run dev - Build:
bun run build - Lint:
bun run lint - Format (lint --fix):
bun run format - Typecheck:
bun run typecheck - Full check (format + lint + typecheck):
bun run check
Environment variables (set in .env.local):
NEXT_PUBLIC_SUPABASE_URLNEXT_PUBLIC_SUPABASE_ANON_KEY
- Framework: Next.js 15 (App Router), React 19, TypeScript (strict)
- Styling/UI: Tailwind CSS v4, shadcn/ui (Radix primitives), cmdk palette
- Data/Auth: Supabase (Postgres, Auth)
- Server components/pages: SSR client from
lib/supabase/serverviacreateClient() - Client components/hooks: browser client from
lib/supabase/clientviagetClient()
- Server components/pages: SSR client from
- Notable patterns: Hybrid SSR + client pagination (TanStack Query), RPC-based search (wrapped in
lib/supabase/repository.ts), Korean locale time with dayjs
Key directories:
app/: App Router pages. Public routes by default; protected paths are checked in middlewarecomponents/: Presentational/interactive UI. Includesjargon/JargonInfiniteList,comment/*,navigation/NavBar*,ui/*hooks/: Client hooks (useSearch,useCurrentUserNameAndImage,useUserQuery,useDebounce)lib/supabase/:client.ts(browser),server.ts(SSR),middleware.ts(session),types.ts(generated types),repository.ts(DB helpers)types/: App-level types (types/comment.ts)
- Server components/pages: create SSR client via
createClient()fromlib/supabase/server - Client components/hooks: create browser client via
getClient()fromlib/supabase/client - Prefer DB helpers in
lib/supabase/repository.tswhen available:DB.searchJargons,DB.countSearchJargonsDB.suggestJargon,DB.suggestTranslation,DB.createComment
- Comments read: query
commentwith joins (profile and translation) rather than a separate view - Type-safety: Prefer types from
lib/supabase/types.ts. Treat this file as generated—do not hand-edit schema definitions here
Auth/session rules (critical):
- Session refresh and route protection live in
lib/supabase/middleware.ts - Do not insert logic between client creation and
supabase.auth.getClaims()in middleware - Middleware currently redirects unauthenticated users from
/profileto/auth/login - To protect additional routes, extend the
pathname.startsWith(...)checks in the middleware
- Language: Korean UI copy; keep tone consistent
- Time: dayjs with
relativeTimeandkolocale - Command palette: via
components/dialogs/SearchDialogProvider.tsx, cmdk withshouldFilter=false; keyboard shortcuts⌘Kand/ - Mobile-first: floating search button on mobile, hidden on desktop
- Pagination: button-driven "더보기" rather than infinite scroll on viewport
- TypeScript strict; explicit component/prop types
- Client vs server: mark client components with
"use client"; prefer server data fetching where possible - Naming: descriptive function/variable names; avoid abbreviations
- Control flow: early returns; shallow nesting
- Comments: add only where non-obvious; explain “why” not “how”
- Formatting: match existing style; avoid unrelated refactors in edits
- Tables:
jargon,translation,category,jargon_category,comment,related_jargon, legacylegacy_fb_user - RPCs used:
search_jargons,count_search_jargons,suggest_jargon,suggest_translation,create_comment
If you need new SQL/RPC:
- The maintainer executes SQL manually in Supabase. Provide exact SQL body and name the function explicitly. Reflect the return shape in TS if used on the client or add a typed wrapper in
repository.ts
app/page.tsx: SSR entry + initial search data via RPC (count + first page)components/home/HomePageClient.tsx: URL param management for sort/category; opens filter dialog; passes props to listcomponents/home/FloatingActionButtons.tsx: Mobile FABs (search, sort, filter)components/jargon/JargonInfiniteList.tsx: Client pagination (useInfiniteQuery) + "더보기"app/jargon/[slug]/page.tsx: Jargon details + initial commentscomponents/comment/CommentThread.tsx: Client comment fetching + tree buildingcomponents/comment/CommentItem.tsx: Nested replies UI, relative timestampscomponents/comment/CommentForm.tsx: Auth gating + insert via RPChooks/useSearch.ts: Debounced search source for cmdk dialoghooks/useUserQuery.ts,hooks/useCurrentUserNameAndImage.ts: Auth state helperscomponents/dialogs/SearchDialogProvider.tsx: Command palette implementationmiddleware.tsandlib/supabase/middleware.ts: Session update and route guard
Add a new protected page under app/:
- Create a server component under
app/your-page/page.tsx - Fetch data with SSR client from
lib/supabase/serveror vialib/supabase/repository - Extend the guard in
lib/supabase/middleware.tsby addingrequest.nextUrl.pathname.startsWith("/your-page")
Query more columns with type-safety:
- Use
getClient()in client orcreateClient()on the server - Prefer repository RPCs when logic belongs in SQL; otherwise
.from("table").select(...) - Align selected fields with
lib/supabase/types.ts; extend app-local types intypes/if needed
Extend search sorting or filters:
- Update the
search_jargonsRPC signature and theDB.searchJargonswrapper to accept newsort_optionor filter params (e.g., categories) - Pass-through from
app/page.tsxto RPC. Keep initial SSR count viaDB.countSearchJargons - Mirror any new result fields in
JargonDataincomponents/jargon/JargonInfiniteList.tsxand update URL params handling inHomePageClient
Add comment features (e.g., soft-delete, edit):
- Prefer server-side enforcement in SQL (e.g., RLS policies, RPCs)
- For writes, use
DB.createCommentor add new RPCs; for reads, extend thecommentselect joins (profile, translation) - Keep tree-building rules: roots newest-first, replies oldest-first
- Do not modify
lib/supabase/types.tsby hand; it’s generated from DB schema - Keep
lib/supabase/middleware.tsclaim-check flow intact; do not insert logic beforegetClaims()and always return the mutatedsupabaseResponse - Avoid introducing heavy state libraries; reuse existing hooks/components
- Keep copy in Korean; avoid mixed language unless a proper translation is provided
- Maintain accessibility: buttons, aria labels, keyboard flows in cmdk
- Validate any user write operations require an authenticated user (client-side gating via hooks; server-side via RLS/RPC)
bun run checkpasses (format + lint + typecheck)- App builds (
bun run build) and loads primary routes:/with and without?q=...,?sort=...,?categories=.../jargon/[slug]with comments- Protected routes (e.g.,
/profile) redirect when unauthenticated
- See
README.mdfor a high-level roadmap and TODOs - Supabase SSR patterns are implemented per official guidance in
lib/supabase/*