Files
gb-site/CLAUDE.md
Ivan Liashkevich 8a380499e7
All checks were successful
ci/woodpecker/push/deploy Pipeline was successful
Add R2 image display in homepage with CDN support
2026-02-10 03:10:57 +02:00

197 lines
7.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# GoodBrick Site
Сайт производителя фасадной плитки GoodBrick с каталогом продукции.
## Stack
- **Frontend:** Next.js 16 + shadcn/ui + Tailwind CSS 4 (TypeScript)
- **Backend:** .NET 9 Web API (C#)
- **Database:** PostgreSQL 16
- **Proxy:** Caddy 2 (auto-SSL)
- **CI/CD:** Woodpecker CI (Gitea OAuth)
- **Git:** Gitea (self-hosted)
## Project Structure
```
GBSite/
├── frontend/ # Next.js app
│ ├── src/app/ # App Router pages
│ ├── src/lib/ # Utilities
│ ├── Dockerfile # Multi-stage: node:20-alpine
│ └── package.json
├── backend/ # .NET 9 Web API
│ ├── src/GBSite.Api/ # Main API project
│ │ ├── Controllers/
│ │ └── Program.cs
│ ├── GBSite.Api.sln
│ └── Dockerfile # Multi-stage: dotnet sdk → aspnet runtime
├── deploy/
│ ├── docker-compose.prod.yml
│ ├── docker-compose.dev.yml
│ └── docker-compose.local.yml # Local backend (Docker mode)
├── scripts/
│ ├── local-tunnel.ps1 # SSH tunnel to dev DB
│ ├── local-backend-docker.ps1 # Start Docker backend
│ ├── local-backend-dotnet.ps1 # Start native backend
│ └── local-frontend.ps1 # Start frontend dev server
├── .woodpecker/
│ └── deploy.yml # CI/CD pipeline
└── CLAUDE.md # This file
```
## Environments
| Env | Frontend URL | API URL | DB |
|-----|-------------|---------|-----|
| **Prod** | https://new.goodbrick.com.ua | https://new.goodbrick.com.ua/api/* | prod_db |
| **Dev** | https://dev.goodbrick.com.ua | https://dev.goodbrick.com.ua/api/* | dev_db |
| **Local** | http://localhost:3000 | http://localhost:5000/api/* | dev_db (via SSH tunnel) |
## Docker Containers (Server)
| Container | Internal Port | Host Port | Network |
|-----------|--------------|-----------|---------|
| gb-prod-frontend | 3000 | 127.0.0.1:3100 | app-network |
| gb-prod-backend | 5000 | 127.0.0.1:5100 | app-network |
| gb-dev-frontend | 3000 | 127.0.0.1:3200 | app-network |
| gb-dev-backend | 5000 | 127.0.0.1:5200 | app-network |
## Routing (Caddy)
Path-based routing — один домен для фронта и API:
- `domain.com/*` → frontend container (port 3000)
- `domain.com/api/*` → backend container (port 5000)
Backend получает запросы с prefix `/api/` (Caddy использует `handle`, не `handle_path`).
## Local Development
### Quick Start (3 терминала)
**Terminal 1 — SSH Tunnel (всегда нужен):**
```powershell
.\scripts\local-tunnel.ps1
```
**Terminal 2 — Backend (выбрать один):**
```powershell
# Работа с фронтом — бэкенд в Docker:
.\scripts\local-backend-docker.ps1
# Работа с бэком — dotnet run с hot-reload:
.\scripts\local-backend-dotnet.ps1
```
**Terminal 3 — Frontend:**
```powershell
.\scripts\local-frontend.ps1
```
### Как это работает
- **SSH Tunnel:** `localhost:5433` → сервер `31.131.18.254:5432` (dev_db)
- **Backend:** слушает на `localhost:5000`, подключается к БД через туннель
- **Frontend:** `npm run dev` на `:3000`, Next.js rewrites проксируют `/api/*``localhost:5000`
- **Переключение режимов:** Ctrl+C в терминале с бэком, запустить другой скрипт. Фронт перезапускать не нужно.
### Конфигурация
- `backend/src/GBSite.Api/appsettings.Local.json` — connection string к dev_db (gitignored)
- `.NET User Secrets` — R2 credentials и другие секреты (хранятся вне репо)
- Управление: `dotnet user-secrets set "R2:AccountId" "value"` (из папки `backend/src/GBSite.Api`)
- Просмотр: `dotnet user-secrets list`
- User secrets имеют приоритет выше appsettings*.json
- `frontend/.env.local``LOCAL_API_URL` и `INTERNAL_API_URL` для локального проксирования
- `deploy/docker-compose.local.yml` — Docker backend с `host.docker.internal:5433`
### URLs
- Frontend: http://localhost:3000
- Backend API: http://localhost:5000/api/health
- DB: localhost:5433 (через SSH tunnel к dev_db)
## Development (manual)
### Frontend
```bash
cd frontend && npm install && npm run dev
```
### Backend
```bash
cd backend && dotnet run --project src/GBSite.Api
```
### Build locally
```bash
cd frontend && npm run build
cd backend && dotnet build
```
## API Conventions
- All API routes start with `/api/`
- Controllers use attribute routing: `[Route("api/[controller]")]`
- Health check: `GET /api/health` — returns `{ status, database, environment }`
- Health ping: `GET /api/health/ping` — returns `{ status: "pong" }`
- Upload: `POST /api/upload` — multipart form, fields: `file` (required), `path` (optional folder prefix)
## Frontend Conventions
- App Router (not Pages Router)
- `src/app/` — pages and API routes
- `src/lib/` — shared utilities
- `src/components/` — React components (create when needed)
- shadcn/ui components via `npx shadcn@latest add <component>`
- Server-side calls to backend use `INTERNAL_API_URL` env var
- Client-side calls use relative paths (`/api/...`) — Caddy proxies them on server, Next.js rewrites locally
## Git & CI/CD
- **Repo:** https://git.goodbrick.com.ua/admin/gb-site
- **Branches:** `main` → prod deploy, `dev` → dev deploy
- **CI:** Woodpecker auto-deploys on push (SSH to server, git pull, docker compose build & up)
- **Commit style:** conventional, short descriptions in English
## Server
- **Host:** 31.131.18.254
- **SSH:** `ssh deploy@31.131.18.254` (key-based)
- **App location:** `/srv/apps/gb-site` (main), `/srv/apps/gb-site-dev` (dev worktree)
- **Caddy config:** `/srv/proxy/Caddyfile`
- **All services docs:** see SERVER.md
## Database
PostgreSQL доступен только внутри Docker network (container name: `postgres`).
Connection string format:
```
Host=postgres;Port=5432;Database={db};Username={user};Password={pass}
```
Configured via env var `ConnectionStrings__Default` in docker-compose files.
Locally via `appsettings.Local.json` with SSH tunnel (`localhost:5433`).
## CDN & Image Storage
- **Storage:** Cloudflare R2 (S3-compatible)
- **CDN domain:** https://cdn.goodbrick.com.ua
- **Bucket:** goodbrick
- **Frontend:** `NEXT_PUBLIC_CDN_URL` env var, `cdnUrl()` helper in `src/lib/cdn.ts`
- **Backend:** `R2__*` env vars (server), .NET User Secrets (local), `R2StorageService` for uploads
- **Upload endpoint:** `POST /api/upload` — multipart/form-data, max 10MB, images only (jpeg/png/webp/avif)
### Folder Convention
- `products/<slug>/main.jpg` — product photos
- `catalog/<slug>/cover.jpg` — collection covers
- `site/<name>.jpg` — site-wide images (hero, about, etc.)
## Key Rules
- Never commit `.env` files or secrets — on server: docker-compose env vars, locally: .NET User Secrets
- Frontend standalone output (`output: "standalone"` in next.config.ts) — required for Docker
- Backend listens on port 5000 (`ASPNETCORE_URLS=http://+:5000`)
- All containers must be in `app-network` (external Docker network)
- `appsettings.Local.json` is gitignored — local dev overrides only