Files
searcher/.codex/skills/wallora-searcher/references/architecture.md
T
2026-06-06 00:49:07 +08:00

5.7 KiB

Wallora Searcher Architecture Reference

Surfaces And Roles

The project has three user-facing surfaces:

  • Public API: available to external users. Use JWT login/authorization for protected API access. Keep contracts documented in swagger.yaml.
  • Admin: available only after account/password login. Use NextAuth-backed sessions to persist admin login state and gate admin features.
  • Public website: available to anyone on the public internet. Optimize pages for SEO, metadata, crawlability, and public performance.

Keep these surfaces separate in routing, middleware, authorization helpers, and mental model.

Route Boundaries

Prefer clear route groups as the app grows:

  • Public website: app/(site)/...
  • Admin UI: app/(admin)/admin/...
  • Protected admin UI: app/(admin)/admin/(protected)/...
  • Public API: app/api/...
  • Auth endpoints: app/api/auth/... for NextAuth

If the existing tree does not yet use route groups, introduce them only when it makes the current change clearer.

Authentication And Authorization

  • Public API authorization: validate JWTs explicitly for protected API routes. Define who issues the token before implementing token verification.
  • Current app-user JWTs are issued by /api/v1/auth/login and /api/v1/auth/register, signed with APP_JWT_SECRET or AUTH_SECRET, and validated by server-only helpers before accessing /api/v1/users/me/....
  • Disabled app users should not be able to log in or use existing Bearer tokens because token validation reloads current wg_app_users.status.
  • Admin authorization: use NextAuth account/password login and session checks. Do not rely on public API JWT logic as the admin session source.
  • Only /admin/login is public under the admin surface. All other /admin pages need middleware/proxy protection and server-side auth() checks, preferably via a protected route-group layout.
  • Server code must keep secrets server-only. Never expose service-role Supabase keys, Aliyun OSS secrets, NextAuth secrets, or JWT signing secrets in NEXT_PUBLIC_*.
  • Keep authorization decisions close to the server boundary: route handlers, server actions, middleware, or server-only helpers.

Data Storage

Use Supabase for application data.

  • Prefix project-owned tables, indexes, triggers, and helper functions with wg_ when practical.
  • Enable and design RLS for tables exposed through Supabase APIs.
  • Do not use user-editable metadata claims for authorization decisions.
  • Model admin roles and API consumer permissions in trusted tables or trusted auth metadata.
  • Verify Supabase behavior against current documentation before implementing schema, RLS, or auth-sensitive behavior.
  • Use service role credentials only in server-only code, one-shot scripts, cron workers, or protected internal route handlers.
  • Treat raw gallery rows as admin data. Public photo APIs should return picked rows only.
  • App-facing gallery list/detail endpoints may accept an optional Bearer app-user JWT to add user-specific fields such as isFavorited; anonymous responses must still work.
  • Keep picked state and OSS mirror metadata on wg_gallery_photos; use collections tables to group picked photos into public sets.
  • Admin collection writes should validate that every collection item references a picked photo.
  • Public collection APIs should filter on is_published = true and keep collection photo pagination compatible with infinite scroll.
  • App user favorites should accept picked photos only, and preferences/download preferences should be stored as JSON in wg_user_settings.
  • Keep phone and WeChat identity support as additive fields on wg_app_users; do not split them into separate user tables unless provider-specific complexity requires it later.

Image Storage

Use Aliyun OSS for image files.

  • Store files in OSS buckets; store metadata such as object key, URL, owner, MIME type, size, visibility, and related entity in Supabase.
  • Prefer server-side signed upload or server-mediated upload for private/admin flows.
  • Avoid placing OSS access keys in browser-exposed code.
  • Existing OSS env support accepts OSS_REGION, OSS_ACCESS_KEY_ID, OSS_ACCESS_KEY_SECRET, OSS_BUCKET, and either OSS_PUBLIC_URL or OSS_PUBLIC_BASE_URL.
  • Decide whether each image class is public, signed, or private before generating URLs.

UI System

Use shadcn/ui as the base UI layer.

  • Initialize and inspect shadcn project config before adding components.
  • Use the project package runner: pnpm dlx shadcn@latest ....
  • Prefer existing shadcn components before writing custom controls.
  • Use semantic tokens and component variants instead of raw color overrides.
  • Compose forms, tables, dialogs, sheets, empty states, loading states, and feedback with shadcn primitives where available.

SEO Website Pages

For public website pages:

  • Use server-rendered pages by default.
  • Keep page-level metadata accurate with Next.js metadata APIs.
  • Use semantic HTML, crawlable content, canonical URLs where needed, and fast-loading assets.
  • Avoid hiding important public content behind client-only rendering.

API Documentation

Maintain swagger.yaml for public API contracts.

  • Update it whenever API endpoints, auth requirements, request schemas, response schemas, status codes, or error formats change.
  • Keep operation IDs stable and descriptive.
  • Document JWT requirements per route instead of assuming all routes share the same auth behavior.
  • Treat generated examples as contract examples, not placeholders.

Scheduled Jobs

  • Do not assume Vercel Cron. This project is not planned for Vercel.
  • Prefer a one-shot script that can be called by crontab, PM2, Docker, or another scheduler.
  • Keep scheduled routes protected with a secret when an HTTP trigger is useful.
  • Never rely on setInterval inside a Next.js request/serverless process for durable jobs.