Imported from AndyZHENG0715/verona-gelato (
AGENTS.md). Install upstream withnpx skills add AndyZHENG0715/verona-gelato. Copyright stays with the author.
Verona Gelato - Agent Guide
OVERVIEW
- Bilingual Next.js 15 site for Verona Gelato, Hong Kong gelato business.
- Surfaces: storefront, events, inquiries, admin CMS.
- Stage 1 complete; Stage 2 waits on client feedback.
- Stack: Next.js 15, TypeScript, Tailwind CSS, Prisma, NextAuth, Nodemailer.
- Client-first now: ~30
use clientfiles. - Stage 2 target: Server Components migration + loading/error/revalidate work.
- Planning/workflow lives in
.planning/.
STRUCTURE
.
├── .planning/ (15)
│ ├── PROJECT.md
│ ├── REQUIREMENTS.md
│ ├── ROADMAP.md
│ ├── STATE.md
│ ├── config.json
│ └── codebase/ (7)
├── docs/ (12)
├── prisma/ (5)
│ └── migrations/ (2)
├── public/ (56)
│ └── images/ (56)
│ ├── about/ (2)
│ ├── cups/ (15)
│ ├── events/ (9)
│ ├── flavors/ (21)
│ └── home/ (7)
└── src/ (110)
├── app/ (93)
│ ├── (components)/ (13)
│ ├── admin/ (33)
│ ├── api/ (19)
│ ├── about/ (3)
│ ├── contact/ (3)
│ ├── events/ (9)
│ ├── flavors/ (3)
│ └── shop/ (3)
├── components/ (6)
│ └── admin/ (4)
├── data/ (1)
├── i18n/ (3)
├── lib/ (5)
└── types/ (1)
(components)is a route group, not a URL segment.src/components/is shared/admin; route-scoped UI stays near the route.
WHERE TO LOOK
| Task | Locations | Notes |
|---|---|---|
| Shell / nav / footer | src/app/(components)/Navbar.tsx, Footer.tsx, src/components/ConditionalLayout.tsx |
/admin* skips shell |
| Home hero / sections | src/app/(components)/Hero.tsx, Highlights.tsx, Events.tsx, MadeInHK.tsx |
live homepage data |
| Locale copy | src/i18n/I18nProvider.tsx, src/i18n/locales/*.json |
useI18n() drives EN/ZH-Hant |
| Admin auth | src/lib/auth.ts, src/middleware.ts, src/app/api/auth/[...nextauth]/route.ts |
/admin/login entry |
| DB / seed / schema | prisma/schema.prisma, prisma/seed.ts, src/lib/db.ts |
Prisma singleton |
| Email / inquiries | src/lib/email.ts, src/app/api/inquiries/* |
admin + customer mail |
| Upload / browse images | src/components/admin/ImageUpload.tsx, src/app/api/admin/upload/*, src/app/api/admin/images/* |
public images contract |
| Admin editors | src/components/admin/EventForm.tsx, FlavorForm.tsx |
JSON array fields |
| Shared UI primitives | src/app/(components)/ui/index.tsx |
Button/Card/Section/etc |
| Brand styles / tokens | src/app/globals.css, docs/verona-gelato-design-guide.md |
Verona color system |
| Planning / GSD | .planning/PROJECT.md, REQUIREMENTS.md, ROADMAP.md, STATE.md |
source of truth |
| Stage 2 plan | .planning/CODEBASE_MODERNIZATION_REPORT.md |
server component migration |
| Legacy data | src/data/home.ts |
reference only |
CODE MAP
src/app/layout.tsx—RootLayout,metadatasrc/components/ConditionalLayout.tsx—ConditionalLayoutsrc/components/SessionProvider.tsx— defaultAuthSessionProvidersrc/i18n/I18nProvider.tsx—I18nProvider,useI18nsrc/lib/db.ts—prismasrc/lib/auth.ts—authOptionssrc/lib/email.ts—sendContactEmail,sendEventInquiryEmail,sendWholesaleInquiryEmailsrc/app/(components)/ui/index.tsx—Button,Card,Section,Heading,Containersrc/app/(components)/Navbar.tsx—Navbarsrc/app/(components)/Footer.tsx—Footersrc/app/(components)/Hero.tsx—Herosrc/app/(components)/Events.tsx—Eventssrc/app/(components)/Highlights.tsx—Highlightssrc/app/(components)/MadeInHK.tsx—MadeInHKsrc/app/(components)/FadeIn.tsx—FadeInsrc/app/(components)/LangSwitch.tsx—LangSwitchsrc/app/(components)/PlaceholderImage.tsx—PlaceholderImagesrc/app/(components)/EventInquiryForm.tsx— defaultEventInquiryFormsrc/app/(components)/WholesaleInquiryForm.tsx— defaultWholesaleInquiryFormsrc/components/admin/EventForm.tsx— defaultEventFormsrc/components/admin/FlavorForm.tsx— defaultFlavorFormsrc/components/admin/ImageUpload.tsx— defaultImageUploadsrc/middleware.ts— default auth middleware,config.matchersrc/data/home.ts— deprecated static data
CONVENTIONS
- Keep shell components in
src/app/(components); no URL path from the group. - Reuse
src/app/(components)/ui/index.tsxbefore inventing new button/card variants. src/components/= shared/admin helpers; route-specific UI stays close to the route.- Use
"use client"only for state/effects/handlers/browser APIs. - Current architecture is client-first; Stage 2 pushes static pieces toward Server Components.
- Preserve EN/ZH-Hant copy on user-facing + admin surfaces.
useI18n()+ locale JSONs are the copy source of truth.- Homepage marketing sections prefer
/api/homepage/*;src/data/home.tsis archival. - Admin forms serialize arrays to JSON strings before submit (
highlights,allergens, multi-image picks). ImageUploadpath contract:/public/images/<folder>/+/api/admin/upload+/api/admin/images.ConditionalLayoutcontrols navbar/footer suppression on/admin*.authOptions+ middleware gate admin via credentials; sessionuser.idis injected in callbacks.- Keep
PlaceholderImagefor asset-heavy views; fallback/blur behavior is intentional.
ANTI-PATTERNS
- Modify database schema without discussion.
- Change auth flow without security review.
- Remove i18n support from any user-facing page.
- Deploy without build verification.
- Commit
.env.localor secrets.
COMMANDS
npm run dev # Start dev server (Turbopack)
npm run build # Production build
npm run lint # ESLint
npx prisma studio # Database GUI
NOTES
- No test infrastructure yet; build + lint are the current gates.
src/app/(components)is a route group, not a route.src/data/home.tsis reference only; active homepage content comes from DB/API.ConditionalLayoutis path-based;/admin/loginbypasses shell, other/admin/*routes do not.ImageUploadcan browse or upload; multi-select returns JSON-stringified paths.PlaceholderImageswaps to fallback art on error; broken assets may be masked.Eventsfetch failures are silent;Highlightslogs and keeps fallback.- GSD source of truth lives in
.planning/; keep roadmap/state changes there. - Stage 2 work should bias toward Server Components, route loading/error files, and
revalidate.