Skip to content

Latest commit

 

History

History
134 lines (112 loc) · 7.49 KB

File metadata and controls

134 lines (112 loc) · 7.49 KB

AGENTS.md — Torky Store Men's

This file documents the codebase for AI agents (Claude, Codex, Cursor) and human contributors. Keep it in sync when files change in src/.

Project intro

Torky Store Men's (متجر تركي للأحذية الرجالية) is an Arabic-first guest-checkout e-commerce storefront for selling men's shoes in Egypt. No auth this phase; orders are placed as guests and verified manually via Supabase Studio.

Stack

  • Framework: Next.js 15 App Router + TypeScript + React 19
  • Styling: Tailwind v4 (CSS variables, OKLCH), shadcn-style primitives in src/ui
  • State: Zustand (src/stores/cart-store.ts) with persist → localStorage
  • Server data: Supabase JS (@supabase/ssr), TanStack Query for client cache
  • Forms: react-hook-form + Zod (src/lib/validators)
  • Motion: framer-motion + tokens in src/lib/motion.ts
  • Image: sharp (server invoice re-encode + favicon generator)
  • PWA: Serwist (src/app/sw.ts)
  • Lint/format: oxlint + oxfmt
  • Hooks: husky pre-commit (lint+format+type-check), pre-push (build), commit-msg (commitlint)

Folder map

src/
├── app/                          # Next.js App Router
│   ├── layout.tsx                # html lang=ar dir=rtl, Cairo font, providers
│   ├── page.tsx                  # → views/HomeView
│   ├── shoes/[customId]/page.tsx # → views/ShoeDetailView
│   ├── pay/page.tsx              # → views/PayView
│   ├── success/[orderId]/page.tsx
│   ├── privacy/page.tsx
│   ├── terms/page.tsx
│   ├── offline/page.tsx
│   ├── not-found.tsx
│   ├── manifest.ts | robots.ts | sitemap.ts (dynamic Supabase) | sw.ts
│   ├── favicon.ico
│   └── api/
│       ├── orders/route.ts       # POST guest order via place_order RPC
│       └── upload-invoice/route.ts # multipart, magic-bytes verify, sharp re-encode, Supabase storage
├── providers/                    # ThemeProvider, PaletteProvider, OnlineProvider, QueryProvider
├── contexts/                     # (reserved)
├── ui/                           # button, input, label, textarea, badge, separator, sheet, radio-group
├── components/                   # header, footer, skip-link, theme-switcher, color-palette-switcher,
│                                 # offline-indicator, cart-trigger, cart-sheet, qty-stepper,
│                                 # payment-receiver-hint, return-policy-notice, shoe-card
├── views/                        # HomeView, PayView, ShoeDetailView (page-level compositions)
├── hooks/                        # useCart, useShoesList, useShoeByCustomId, useColors, useSizes
├── services/                     # shoes-service (queries, public image URL builder)
├── data/                         # constants object — single source of all Arabic copy + tokens
├── types/                        # IdString, IsoDateString, OptionalString
├── enums/                        # PaymentMethodEnum, OrderStatusEnum, ColorPaletteEnum,
│                                 # ThemeModeEnum, PwaDisplayEnum, RobotsPolicyEnum
├── interfaces/                   # ShoeInterface, OrderInterface, CartLineInterface, ...
├── lib/
│   ├── utils.ts                  # cn, formatEgpHandler, formatDateArHandler, isEgyptPhoneHandler, ...
│   ├── motion.ts                 # motionTokens (duration, ease curves)
│   ├── seo.ts                    # buildMetadataHandler, buildOrganizationLdHandler
│   ├── supabase/
│   │   ├── client.ts             # createBrowserSupabaseClientHandler
│   │   ├── server.ts             # createServerSupabaseClientHandler, createServiceRoleSupabaseClientHandler
│   │   └── types.ts              # generated via Supabase MCP `generate_typescript_types`
│   └── validators/               # orderPayloadSchema (Zod), invoice MIME/size constants
└── stores/
    └── cart-store.ts             # Zustand + persist, addLineHandler, removeLineHandler, setQuantityHandler

Each folder has an index.ts barrel. Import from the barrel, not deep paths, except inside the same folder.

Code conventions (binding)

  • Identifiers: camelCase for consts/vars/object keys.
  • Components: PascalCase. Hooks: use* prefix.
  • Event handlers: camelCase ending in Handler (fileChangeHandler, clickHandler).
  • Pure lib functions: end in Handler (formatEgpHandler, buildMetadataHandler).
  • No hardcoded strings: every user-visible string lives in src/data/index.ts constants object.
  • Enums: *Enum suffix; members SCREAMING_SNAKE_CASE; string values whatever they need to be.
  • Interfaces: *Interface suffix.
  • Files: kebab-case (shoe-card.tsx, use-cart.ts).
  • Object literal keys: alphabetically sorted (oxlint sort-keys: error).
  • Functions: arrow expressions assigned to const, never function declarations.
  • Type imports: import { type Foo } inline.
  • No deep cross-feature imports: go through barrels.

Supabase

  • Project: xuobbsircuaomhsjlsyq in Hawary's Organization, region eu-central-1
  • URL: https://xuobbsircuaomhsjlsyq.supabase.co
  • Tables: colors, sizes, categories, shoes, shoe_categories, shoe_variants, shoe_images, orders, order_items
  • RLS: catalog tables → public read; orders/order_items → no anon access (RPC-only path)
  • RPC: place_order(...) security definer; atomic stock validation + decrement + Arabic snapshots
  • Triggers: trg_variant_stock keeps shoes.in_stock in sync; trg_*_updated_at for timestamps
  • Buckets: shoes (public read), invoices (private, service-role only)
  • Type regeneration: rerun mcp__claude_ai_Supabase__generate_typescript_types after schema changes; paste into src/lib/supabase/types.ts

Commits

  • Conventional commits, types from commitlint.config.js: feat, fix, docs, style, design, refactor, perf, test, build, ci, chore, revert
  • Header ≤ 100 chars
  • No Claude/AI signature, no Co-Authored-By line
  • Body explains "why", not "what"

MCP tools available

  • Supabase MCP: list/create projects, apply migrations, generate types, advisors, storage
  • Context7 MCP: fetch live framework/library docs
  • Impeccable: design + brand context (PRODUCT.md, DESIGN.md)

Environment variables (.env.local)

  • NEXT_PUBLIC_SUPABASE_URL — public, in browser bundle
  • NEXT_PUBLIC_SUPABASE_ANON_KEY — public, in browser bundle
  • SUPABASE_SERVICE_ROLE_KEY — server only; used by /api/upload-invoice and dynamic sitemap fetch
  • NEXT_PUBLIC_SITE_URL — canonical origin for SEO + sitemap

Pages map

Route Static / Dynamic Notes
/ static shoe grid via TanStack Query → Supabase
/shoes/[customId] dynamic client-fetched detail + zoom + variant pickers
/pay static (NOINDEX) RHF + Zod, payment hint zone, invoice upload
/success/[orderId] dynamic (NOINDEX) post-order confirmation
/privacy, /terms static placeholder Arabic structure
/offline static SW fallback
/manifest.webmanifest static PWA manifest
/robots.txt static
/sitemap.xml dynamic, revalidate=3600 queries Supabase shoes
/api/orders route handler POST → place_order RPC
/api/upload-invoice route handler POST multipart

Sync rule

When files added/removed in src/, regenerate the Folder map section above. Until automated, do it by hand on PRs that touch folder structure.