This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Singcode is a Korean karaoke song management web app (singcode.kr). Users can search for songs by title/singer/number, save songs to folders, track liked songs, and manage their "to-sing" list. The app uses Supabase for auth and database, and an external karaoke open API via the @repo/open-api workspace package.
All commands run from apps/web/:
pnpm dev # Start dev server with Turbopack (http://localhost:3000)
pnpm build # Production build (also runs next-sitemap postbuild)
pnpm lint # ESLint
pnpm format # Prettier format all .ts, .tsx, .md files
pnpm start # Start production serverNo test suite is configured.
This is a pnpm workspace monorepo. The web app lives at apps/web/. Key workspace packages:
@repo/open-api— wrapper around the external karaoke open API (used in API routes)@repo/query— shared TanStack Query setup@repo/eslint-config,@repo/format-config— shared tooling configs
- Next.js 15 (App Router) with React 19
- Supabase (
@supabase/ssr) for auth and database - TanStack Query for server state
- Zustand for client state
- Tailwind CSS v4 + shadcn/ui components in
src/components/ui/ - Axios with a base
/apiinstance insrc/lib/api/client.ts - Framer Motion / GSAP for animations
- API routes (
src/app/api/) act as a BFF layer — client code calls these via Axios, never directly to Supabase or external APIs from the browser. - API route handlers use
src/lib/supabase/server.ts(for Next.js route handlers) to get an authenticated Supabase client, then callsrc/utils/getAuthenticatedUser.tsto extractuserId. - Client-side API functions live in
src/lib/api/(e.g.,likeSong.ts,saveSong.ts). They call internal Next.js API routes via the Axios instance. - TanStack Query hooks live in
src/queries/— they wrap thesrc/lib/api/functions.
Three different Supabase clients for different contexts:
src/lib/supabase/client.ts— browser client (createBrowserClient), usesNEXT_PUBLIC_env varssrc/lib/supabase/server.ts— server/route handler client (createServerClient)src/lib/supabase/api.ts— legacy API routes client (Next.js Pages-stylereq/res)src/lib/supabase/middleware.ts— middleware client (updateSession)
src/auth.tsx is a client-side AuthProvider wrapping the app. It checks auth on every route change via useAuthStore. Public routes (no auth required): /, /popular, /login, /signup, /recent, /tosing, /update-password. All other routes redirect to /login?alert=login.
src/stores/useModalStore.ts— global message dialog state (useopenMessage/closeMessage)src/stores/useSearchHistoryStore.ts— search history persisted tolocalStoragesrc/stores/middleware.ts— shared Zustand middleware- Auth state is in
useAuthStore(referenced but not shown above)
/→ Song search (main feature,src/app/search/HomePage.tsx)/popular→ Popular songs/recent→ Recently added songs/tosing→ User's "to-sing" list/info→ User profile/info/info/like→ Liked songs/info/save→ Saved song folders (supports drag-and-drop via@dnd-kit)/login,/signup,/update-password,/withdrawal→ Auth flows
Song searches go through GET /api/open_songs/[type]/[param] which proxies to @repo/open-api. Search types: title, singer, composer, lyricist, no, release, popular. The brand query param selects the karaoke brand.
POST /api/chat proxies to OpenAI (using the openai package). Client-side in src/lib/api/openAIchat.ts, UI in src/app/search/ChatBot.tsx.
Required in .env / .env.development.local:
NEXT_PUBLIC_SUPABASE_URLNEXT_PUBLIC_SUPABASE_ANON_KEYSUPABASE_URL(server-only, used in legacy API client)SUPABASE_ANON_KEY(server-only)- OpenAI key for chat feature
Format: <type>/<camelCaseName>
| type | usage |
|---|---|
feat |
new feature |
fix |
bug fix |
hotfix |
urgent fix |
chore |
maintenance, docs, config |
release |
release (e.g. release/2.1.0) |
The part after the slash uses camelCase (e.g. feat/scrollText, feat/FooterNavbar, fix/loginAuth).
Branch flow: feat/* → develop → main
Format: <type> : <Korean description> — one space before and after the colon.
| type | usage |
|---|---|
feat |
new feature |
fix |
bug fix |
hotfix |
urgent bug fix |
chore |
version bump, config, format, cleanup |
refactor |
refactoring |
doc |
documentation |
Examples:
feat : MarqueeText 자동 스크롤 텍스트 적용
fix : SongCard css 수정
hotfix : 빌드 에러 수정. thumb 필드 옵셔널 타입 조정.
chore : 버전 2.3.0
refactor : useSearchSong 훅 분리 - 곡 모달 저장 분리
- Path alias
@/maps tosrc/ src/utils/cn.ts—clsx+tailwind-mergeutility for className mergingsrc/utils/isSuccessResponse.ts— type guard for API responsessrc/utils/getErrorMessage.ts— standardized error message extraction- shadcn/ui components are in
src/components/ui/and should not be modified directly src/components/reactBits/— custom animation components (AnimatedContent, SplitText, GradientText, Shuffle)- Global toast notifications use
sonner(<Toaster>in layout) - Global modal dialog uses
useModalStore+<MessageDialog>in layout