Files
searcher/AGENTS.md
T
2026-06-06 00:49:07 +08:00

6.2 KiB

AGENTS.md — Wallora Searcher

This file contains agent-focused context about the project: build steps, tests, conventions, and preferences that don't belong in the README.

Project Overview

Wallora Searcher is a Next.js 16 App Router project with three distinct surfaces:

  1. Public SEO website — Landing pages for visitors
  2. Admin dashboard — Authenticated admin interface for gallery/photo management
  3. Public API — REST endpoints for external clients

Tech Stack

  • Framework: Next.js 16.2.6 (App Router, Turbopack)
  • Runtime: React 19.2.4, React DOM 19.2.4
  • Language: TypeScript 6.0.3
  • Styling: Tailwind CSS v4, OKLCH color system
  • UI System: shadcn/ui (base-nova style, base primitives)
  • Auth: NextAuth.js v5 beta (Credentials provider)
  • Database: Supabase (PostgreSQL)
  • Package Manager: pnpm (monorepo with pnpm-workspace.yaml)
  • Lint: ESLint 9 + eslint-config-next + tailwind-canonical-classes
  • Python Scripts: Selenium + ChromeDriver for browser automation

Directory Structure

app/
  (admin)/           # Admin route group
    admin/
      (protected)/    # Protected routes (requires auth)
        dashboard/    # Admin dashboard
        gallery/      # Gallery photo picker (瀑布流 masonry)
      login/          # Admin login page
  (site)/            # Public website route group
  api/               # API routes
    admin/
      gallery-photos/ # GET — paginated gallery photos
    auth/[...nextauth]/ # NextAuth handlers
    cron/
      gallery-photos/ # Cron job for sync

components/
  admin/gallery/     # Gallery-specific components
  ui/                # shadcn/ui components

lib/
  auth.ts            # NextAuth configuration
  supabase/
    service-role.ts  # Supabase service role client
  utils.ts           # cn() utility

server/
  admin/gallery-sync.ts # Gallery sync logic
  api/unsplash.ts     # Unsplash API client

scripts/
  sync-gallery-photos.py  # Python script: Selenium Chrome → Unsplash → Supabase
  requirements.txt        # Python deps: selenium, webdriver-manager, supabase, python-dotenv
  .venv/                  # Python virtual environment

types/
  admin/gallery.ts   # GalleryPhoto, GalleryPagination types

Environment Variables

Required in .env.local:

# NextAuth
AUTH_SECRET=<random-string>

# Supabase
NEXT_PUBLIC_SUPABASE_URL=http://your-supabase-url
NEXT_PUBLIC_SUPABASE_ANON_KEY=<anon-key>
SUPABASE_SERVICE_ROLE_KEY=<service-role-key>

# Admin Credentials
ADMIN_EMAIL=admin@example.com
ADMIN_PASSWORD=yourpassword

# Cron (optional)
CRON_SECRET=<random-string>

Scripts

# Development
pnpm dev              # Start dev server at localhost:3000

# Build & Lint
pnpm build            # Production build
pnpm lint             # ESLint check
pnpm lint:fix         # ESLint with auto-fix

# Format
pnpm format           # Prettier format all
pnpm format:check     # Prettier check

# Gallery Sync
pnpm sync:gallery     # Node.js sync script (legacy)

# Python Sync
python scripts/sync-gallery-photos.py --max-pages=10 --topic=wallpapers

Python Sync Script

The Python script controls a real Chrome browser via Selenium to fetch Unsplash data:

# Setup (first time)
cd scripts
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt

# Run
python scripts/sync-gallery-photos.py --max-pages=5 --topic=wallpapers

Features:

  • --max-pages: Required. Pages to fetch (1..N)
  • --topic: Optional. Unsplash topic slug (e.g. wallpapers, 3d-renders, nature)
  • --per-page: Optional. Default 20
  • --headless/--no-headless: Default headless
  • --delay: Base delay between pages (default 3s, +0-2s random)

Admin Authentication

  • Uses NextAuth.js v5 beta with Credentials provider
  • Login page: /admin/login
  • Protected routes: /admin/(protected)/*
  • Route protection via proxy.ts (Next.js 16 middleware convention)
  • Session stored as JWT
  • Masonry Layout: 4 independent columns with greedy shortest-column algorithm
  • Infinite Scroll: IntersectionObserver-based pagination
  • Animations: Entrance fade + translateY + scale, hover scale + shadow, lightbox transitions
  • Lightbox: Click to view full image with metadata overlay
  • API: /api/admin/gallery-photos?page=N&per_page=24

Supabase Tables

  • wg_gallery_photos — Photo data from Unsplash
  • wg_gallery_sync_state — Sync state tracking

Conventions

Routing

  • Use App Router (app/). Never create pages/ unless explicitly requested.
  • Route groups: (admin) for admin, (site) for public.
  • Protected routes nested under (protected).

Components

  • React Server Components by default.
  • Add "use client" only for interactivity (state, effects, browser APIs).
  • shadcn/ui as base. Use npx shadcn@latest add <component> to install.
  • Prefer Tailwind utility classes and CSS variables over custom CSS.

API Design

  • Separate JWT auth (public API) and session auth (admin) as different trust boundaries.
  • Update swagger.yaml when API contracts change.

Styling

  • Use semantic colors (bg-primary, text-muted-foreground).
  • No raw colors like bg-blue-500.
  • Use size-* for equal width/height.
  • Use gap-* instead of space-x-* / space-y-*.

Python Scripts

  • All Python code lives in scripts/.
  • Use virtual environment at scripts/.venv/.
  • Keep .env.local parsing logic consistent with Node.js scripts.

Known Issues / Gotchas

  1. Next.js 16 uses proxy.ts instead of middleware.ts for route interception.
  2. shadcn/ui base-nova style uses @base-ui/react primitives, not Radix.
  3. ESLint has react-hooks/set-state-in-effect disabled (false positives with async data fetching).
  4. .venv/ and node_modules/ should be ignored by ESLint (configured in eslint.config.mjs).
  5. GalleryGrid uses <img> not Next.js <Image> because external Unsplash URLs don't work well with the Image optimizer without domain configuration.

Verification Checklist

After making changes:

  • pnpm lint passes
  • pnpm build succeeds
  • For visual changes: verify at http://localhost:3000
  • For admin changes: verify login/logout flow
  • For API changes: test with curl or browser

Contact