first commit

This commit is contained in:
luoyangwei
2026-06-06 00:49:07 +08:00
commit 2b860d201e
134 changed files with 22773 additions and 0 deletions
+207
View File
@@ -0,0 +1,207 @@
# 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`:
```bash
# 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
```bash
# 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:
```bash
# 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
## Gallery Page Features
- **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
- Admin: luoyw1106703846@gmail.com