5.7 KiB
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/loginand/api/v1/auth/register, signed withAPP_JWT_SECRETorAUTH_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/loginis public under the admin surface. All other/adminpages need middleware/proxy protection and server-sideauth()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 = trueand 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 eitherOSS_PUBLIC_URLorOSS_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
setIntervalinside a Next.js request/serverless process for durable jobs.