Conventions
Server vs Client components
- Server Components by default — add
'use client'only when using hooks (useState,useEffect,usePathname,useRouter) or event handlers - Server Components fetch data and pass it as props to Client Components
- Never import data files or call async functions inside Client Components
File locations
'use server'belongs only inapp/actions/— not inlib/lib/files useimport 'server-only'for server-only moduleslib/project-types.tshas noserver-only— safe to import in Client Components
Design tokens
- Always use
var(--mm-*)tokens — never hardcode hex values - No inline styles except for CSS variable references
- Framer Motion animation variants defined at the top of the file, not inline
Naming
- Supabase returns snake_case — always map to camelCase in the data layer before returning
- Never access
.service_type,.created_at, etc. on a typed model
Global UI
- Drawers, modals, toasts → render in
app/layout.tsxroot, never scoped to sub-routes CartDraweris already there — follow that pattern
Path segment counting
/work/[category]/[slug] has 3 non-empty segments. Always:
pathname.split('/').filter(Boolean).length
Resend SDK v6
emails.send() does not throw on API errors — it returns { data, error }. Always destructure and check:
const { data, error } = await emails.send(...);
if (error) throw new Error(error.message);
Static vs dynamic routes
dynamicParams = falseon closed-set detail pages (all valid slugs known at build time)- Already applied to
marketplace/[slug]— apply towork/[category]/[slug]when project data is stable