sunnymh-manga-site/AGENTS.md
yiekheng 9bd75381a7 Add hello world landing page and Docker deployment config
Simple landing page for initial Portainer GitOps deployment.
Includes Dockerfile, docker-compose.yml with pull_policy: build,
and project documentation.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 22:37:08 +08:00

4.6 KiB
Raw Blame History

This is NOT the Next.js you know

This version has breaking changes — APIs, conventions, and file structure may all differ from your training data. Read the relevant guide in node_modules/next/dist/docs/ before writing any code. Heed deprecation notices.

Manga Website Project Requirements

Tech Stack

Layer Technology
Frontend & Backend Next.js (App Router, TypeScript, Tailwind CSS)
Database PostgreSQL 16
ORM Prisma
Image Storage Cloudflare R2
Containerization Docker + Docker Compose (managed via Portainer)
Reverse Proxy Nginx via aaPanel
Domain manga.04080616.xyz

Infrastructure

  • Server: Proxmox host, Docker VM/LXC running Portainer
  • Reverse proxy: aaPanel Nginx routes manga.04080616.xyzhttp://127.0.0.1:3001
  • SSL: Let's Encrypt via aaPanel
  • DDNS already configured — no Cloudflare Tunnel needed

Port Allocation

Port Service
3001 Next.js app (host) → 3000 (container)
5433 PostgreSQL (host) → 5432 (container)

Ports 3000, 80008002, 8005, 2283, 5432, 5182051821, 9443 are already in use.

Deployment Workflow

  1. Develop on macOS locally
  2. Push code to Gitea (gitea.04080616.xyz/yiekheng/sunnymh-manga-site)
  3. On Proxmox Docker host: git pulldocker build → restart container
  4. Portainer used for container management (GUI)

Image Storage (Cloudflare R2)

  • Images stored in R2 (S3-compatible), not on the Proxmox host
  • Upload flow: backend generates presigned URL → browser uploads directly to R2 → database records image path
  • Format: WebP (2535% smaller than JPEG)
  • Multiple resolutions: thumbnail / reading / original

R2 Directory Structure

/manga/{manga_id}/{chapter_id}/{page_number}.webp
/thumbnails/{manga_id}/cover.webp

Database Schema (Prisma)

model Manga {
  id          Int       @id @default(autoincrement())
  title       String
  description String
  coverUrl    String
  slug        String    @unique
  status      Status    @default(PUBLISHED)
  chapters    Chapter[]
  createdAt   DateTime  @default(now())
  updatedAt   DateTime  @updatedAt
}

model Chapter {
  id        Int     @id @default(autoincrement())
  mangaId   Int
  number    Int
  title     String
  pages     Page[]
  manga     Manga   @relation(fields: [mangaId], references: [id])
}

model Page {
  id        Int     @id @default(autoincrement())
  chapterId Int
  number    Int
  imageUrl  String
  chapter   Chapter @relation(fields: [chapterId], references: [id])
}

enum Status {
  PUBLISHED
  DRAFT
}

Features

Core (build first)

  • Manga listing page with cover images
  • Manga detail page (title, description, chapter list)
  • Chapter reader page (page-by-page image display)
  • Internal search by manga title (PostgreSQL contains query)

SEO

  • Next.js SSR/SSG for all public pages
  • generateMetadata() per page (title, description)
  • Auto-generated /sitemap.xml via app/sitemap.ts
  • Submit sitemap to Google Search Console
  • Phase 1: PostgreSQL contains with insensitive mode (sufficient for < 10k titles)
  • Phase 2 (future): Meilisearch for fuzzy/full-text search if needed

URL Structure

/                          Homepage (manga grid)
/manga/[slug]              Manga detail + chapter list
/manga/[slug]/[chapter]    Chapter reader
/api/search?q=             Search API endpoint
/api/manga                 Manga CRUD (admin)
/api/upload                R2 presigned URL generation

Environment Variables (.env)

DATABASE_URL=postgresql://manga_user:yourpassword@localhost:5433/manga_db

R2_ACCOUNT_ID=your_cloudflare_account_id
R2_ACCESS_KEY=your_r2_access_key
R2_SECRET_KEY=your_r2_secret_key
R2_BUCKET=manga-images
R2_PUBLIC_URL=https://your-r2-public-url.r2.dev

Nginx Reverse Proxy Config (aaPanel)

location / {
    proxy_pass http://127.0.0.1:3001;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection 'upgrade';
    proxy_set_header Host $host;
    proxy_cache_bypass $http_upgrade;
}

Content Source

  • Public domain / free manga only (no copyright issues)
  • Sources: Comic Book Plus, Digital Comic Museum, Internet Archive
  • Initial: manual download and upload
  • Future: automated scraper (Node.js + cheerio) for allowed sources
  1. Set up Prisma schema + connect to PostgreSQL
  2. Build manga listing and reader pages (static UI first)
  3. Wire up database queries via Prisma
  4. Add R2 upload + image serving
  5. Add search API
  6. Add SEO metadata + sitemap
  7. Dockerize and deploy to Proxmox via Gitea