chore: initialize Vite + React + Tailwind project
This commit is contained in:
151
docs/plans/2026-03-11-birthday-roast-gallery-design.md
Normal file
151
docs/plans/2026-03-11-birthday-roast-gallery-design.md
Normal file
@@ -0,0 +1,151 @@
|
||||
# Birthday Roast Gallery - Design Document
|
||||
|
||||
**Date:** 2026-03-11
|
||||
**Project:** Birthday meme website for Linh
|
||||
**Domain:** cmsn-b-linh.duylai.duckdns.org
|
||||
|
||||
## Overview
|
||||
|
||||
A static birthday roast gallery website featuring embarrassing photos with funny Vietnamese captions. Built with Vite + React + Tailwind, containerized with Nginx, and deployed to Kubernetes.
|
||||
|
||||
## Architecture
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────┐
|
||||
│ Build Stage │
|
||||
│ Node.js image → npm install → Vite build → dist/ │
|
||||
└─────────────────────────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────┐
|
||||
│ Runtime Stage │
|
||||
│ Nginx:alpine → copy dist/ → serve on port 80 │
|
||||
└─────────────────────────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────┐
|
||||
│ Kubernetes │
|
||||
│ Deployment → Service → Ingress (Traefik) │
|
||||
│ cmsn-b-linh.duylai.duckdns.org │
|
||||
└─────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## Tech Stack
|
||||
|
||||
| Layer | Technology |
|
||||
|-------|------------|
|
||||
| Frontend | Vite + React 18 |
|
||||
| Styling | Tailwind CSS |
|
||||
| Animation | canvas-confetti |
|
||||
| Container | Multi-stage Dockerfile → nginx:alpine |
|
||||
| Orchestration | Kubernetes with Traefik ingress |
|
||||
|
||||
## Frontend Components
|
||||
|
||||
```
|
||||
App.jsx
|
||||
├── BirthdayBanner.jsx # Hero with name + roast message + confetti
|
||||
└── RoastGallery.jsx # Grid of photos with captions
|
||||
└── RoastCard.jsx # Individual photo + caption
|
||||
```
|
||||
|
||||
### BirthdayBanner
|
||||
- Large "Happy Birthday [Name]!" heading
|
||||
- Roast subtitle message
|
||||
- Confetti animation on page load
|
||||
- Click-to-trigger more confetti
|
||||
|
||||
### RoastGallery
|
||||
- Responsive CSS grid (2-3 cols mobile, 4-5 cols desktop)
|
||||
- Cards with hover effects
|
||||
|
||||
### RoastCard
|
||||
- Image with aspect ratio
|
||||
- Caption below or overlay
|
||||
- Hover animation (scale/shadow)
|
||||
|
||||
## Static Assets
|
||||
|
||||
Images stored in `public/images/` with captions configured in `public/roasts.json`:
|
||||
|
||||
```json
|
||||
[
|
||||
{ "image": "roast-1.jpg", "caption": "Khoảnh khắc huyền thoại 😂" },
|
||||
{ "image": "roast-2.jpg", "caption": "Gương mặt khi quên đóng bài tập" }
|
||||
]
|
||||
```
|
||||
|
||||
- UTF-8 encoding for Vietnamese captions
|
||||
- Add photos: drop file → add JSON entry → rebuild
|
||||
|
||||
## Container Setup
|
||||
|
||||
### Dockerfile (multi-stage)
|
||||
|
||||
```dockerfile
|
||||
# Build stage
|
||||
FROM node:20-alpine AS builder
|
||||
WORKDIR /app
|
||||
COPY package*.json ./
|
||||
RUN npm ci
|
||||
COPY . .
|
||||
RUN npm run build
|
||||
|
||||
# Runtime stage
|
||||
FROM nginx:alpine
|
||||
COPY --from=builder /app/dist /usr/share/nginx/html
|
||||
COPY nginx.conf /etc/nginx/conf.d/default.conf
|
||||
EXPOSE 80
|
||||
```
|
||||
|
||||
### nginx.conf
|
||||
- Static file serving
|
||||
- Gzip compression
|
||||
- SPA fallback
|
||||
|
||||
## Kubernetes Deployment
|
||||
|
||||
```
|
||||
k8s/
|
||||
├── deployment.yaml # Nginx pod, 1-2 replicas
|
||||
├── service.yaml # ClusterIP on port 80
|
||||
└── ingress.yaml # Traefik ingress for cmsn-b-linh.duylai.duckdns.org
|
||||
```
|
||||
|
||||
### Deployment
|
||||
- Image: registry/cmsn-b-linh:latest
|
||||
- Replicas: 1
|
||||
- Resources: minimal (50m CPU, 64Mi RAM)
|
||||
|
||||
### Ingress (Traefik)
|
||||
- Host: cmsn-b-linh.duylai.duckdns.org
|
||||
- Traefik-compatible annotations
|
||||
- Optional: TLS via cert-manager
|
||||
|
||||
## File Structure
|
||||
|
||||
```
|
||||
cmsn/
|
||||
├── src/
|
||||
│ ├── App.jsx
|
||||
│ ├── main.jsx
|
||||
│ ├── components/
|
||||
│ │ ├── BirthdayBanner.jsx
|
||||
│ │ ├── RoastGallery.jsx
|
||||
│ │ └── RoastCard.jsx
|
||||
│ └── index.css
|
||||
├── public/
|
||||
│ ├── images/ # Add photos here
|
||||
│ └── roasts.json # Caption config
|
||||
├── index.html
|
||||
├── package.json
|
||||
├── vite.config.js
|
||||
├── tailwind.config.js
|
||||
├── postcss.config.js
|
||||
├── Dockerfile
|
||||
├── nginx.conf
|
||||
└── k8s/
|
||||
├── deployment.yaml
|
||||
├── service.yaml
|
||||
└── ingress.yaml
|
||||
```
|
||||
Reference in New Issue
Block a user