chore: initialize production docker infrastructure and project agent guidelines

This commit is contained in:
ngthanhvu
2026-08-09 12:51:16 -04:00
parent 9c8a77f134
commit 79a565f16b
9 changed files with 1294 additions and 0 deletions
+561
View File
@@ -0,0 +1,561 @@
# Distinctive Frontend Design
Create visually distinctive, high-impact frontend interfaces that avoid generic "AI slop" aesthetics. This skill applies the four-vector approach: typography, color/theme, motion, and backgrounds.
## Core Principles
**Avoid distributional convergence**: Reject default choices (Inter/Roboto fonts, purple gradients, minimal animations). Instead, make bold, cohesive design decisions that create memorable interfaces.
**Think in systems**: Use CSS variables, design tokens, and coordinated choices across all four dimensions rather than isolated tweaks.
## 1. Typography - Use Extremes
### Font Weight Strategy
- **Go to extremes**: Use 100-200 (thin) vs 800-900 (black), not safe 400 vs 600
- **Create hierarchy through weight contrast**, not just size
- **Example combinations**:
- Headers: 900 weight, body: 200 weight
- Headers: 100 weight (elegant), body: 500 weight
### Font Pairing
Avoid generic system fonts. Use distinctive pairings:
```css
/* Option 1: Geometric Sans + Monospace */
--font-display: 'Space Grotesk', sans-serif;
--font-body: 'Inter', sans-serif;
--font-mono: 'JetBrains Mono', monospace;
/* Option 2: Serif Display + Sans Body */
--font-display: 'Playfair Display', serif;
--font-body: 'Source Sans 3', sans-serif;
/* Option 3: Condensed + Wide */
--font-display: 'Bebas Neue', cursive;
--font-body: 'DM Sans', sans-serif;
/* Option 4: Variable Font Extremes */
--font-main: 'Recursive', sans-serif;
/* Then use font-weight: 300-1000 range */
```
### Implementation Pattern
```css
:root {
--font-display: 'Space Grotesk', sans-serif;
--font-body: 'Inter', sans-serif;
/* Use extreme weights */
--weight-thin: 100;
--weight-light: 200;
--weight-bold: 800;
--weight-black: 900;
}
h1, h2, h3 {
font-family: var(--font-display);
font-weight: var(--weight-black);
letter-spacing: -0.03em; /* Tight tracking for bold weights */
}
body, p {
font-family: var(--font-body);
font-weight: var(--weight-light);
letter-spacing: 0.01em; /* Slight tracking for readability */
}
```
## 2. Color & Theme - Commit to Cohesion
### Strategy
- **Draw from cultural references**: Movies, art movements, IDE themes, nature
- **Use CSS variables** for systematic color application
- **Avoid**: Safe blues/purples, low-contrast pastels
### Theme Examples
```css
/* Theme 1: Cyberpunk (Blade Runner inspired) */
:root {
--bg-primary: #0a0e27;
--bg-secondary: #1a1f3a;
--accent-1: #ff2e97; /* Hot pink */
--accent-2: #00d9ff; /* Cyan */
--accent-3: #ffd700; /* Gold */
--text-primary: #e4f1ff;
--text-secondary: #8b9dc3;
}
/* Theme 2: Brutalist (Raw concrete) */
:root {
--bg-primary: #f5f5f0;
--bg-secondary: #ffffff;
--accent-1: #ff0000;
--accent-2: #000000;
--text-primary: #1a1a1a;
--border: 3px solid #000000;
}
/* Theme 3: Vaporwave */
:root {
--bg-primary: #1a0033;
--bg-secondary: #2d1b4e;
--accent-1: #ff71ce; /* Pink */
--accent-2: #01cdfe; /* Cyan */
--accent-3: #b967ff; /* Purple */
--accent-4: #05ffa1; /* Mint */
--text-primary: #fffb96;
}
/* Theme 4: Nordic Minimalism */
:root {
--bg-primary: #2e3440;
--bg-secondary: #3b4252;
--accent-1: #88c0d0; /* Frost blue */
--accent-2: #bf616a; /* Aurora red */
--accent-3: #a3be8c; /* Aurora green */
--text-primary: #eceff4;
--text-secondary: #d8dee9;
}
```
### Application Pattern
```css
body {
background: var(--bg-primary);
color: var(--text-primary);
}
.card {
background: var(--bg-secondary);
border: 1px solid var(--accent-1);
}
.cta-button {
background: var(--accent-1);
color: var(--bg-primary);
}
.highlight {
color: var(--accent-2);
}
```
## 3. Motion - Orchestrated Page Load
### Strategy
- **Prioritize page-load choreography** over scattered micro-interactions
- **Use staggered reveals** to guide attention
- **Create entrance sequences** that feel intentional
### Implementation Patterns
```css
/* Base setup: Elements start invisible */
.fade-in {
opacity: 0;
animation: fadeInUp 0.8s cubic-bezier(0.16, 1, 0.3, 1) forwards;
}
/* Stagger delays */
.stagger-1 { animation-delay: 0.1s; }
.stagger-2 { animation-delay: 0.2s; }
.stagger-3 { animation-delay: 0.3s; }
.stagger-4 { animation-delay: 0.4s; }
.stagger-5 { animation-delay: 0.5s; }
/* Smooth easing curve */
@keyframes fadeInUp {
from {
opacity: 0;
transform: translateY(30px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
/* Alternative: Slide from side */
@keyframes slideInRight {
from {
opacity: 0;
transform: translateX(-40px);
}
to {
opacity: 1;
transform: translateX(0);
}
}
/* Scale entrance for hero elements */
@keyframes scaleIn {
from {
opacity: 0;
transform: scale(0.9);
}
to {
opacity: 1;
transform: scale(1);
}
}
```
### React/JavaScript Pattern
```javascript
// Add classes progressively
useEffect(() => {
const elements = document.querySelectorAll('.animate-on-load');
elements.forEach((el, index) => {
el.classList.add('fade-in', `stagger-${index + 1}`);
});
}, []);
// Or use Framer Motion
import { motion } from 'framer-motion';
const container = {
hidden: { opacity: 0 },
show: {
opacity: 1,
transition: {
staggerChildren: 0.1
}
}
};
const item = {
hidden: { opacity: 0, y: 20 },
show: { opacity: 1, y: 0 }
};
<motion.div variants={container} initial="hidden" animate="show">
<motion.h1 variants={item}>Title</motion.h1>
<motion.p variants={item}>Subtitle</motion.p>
<motion.button variants={item}>CTA</motion.button>
</motion.div>
```
## 4. Backgrounds - Atmospheric Depth
### Strategy
- **Layer gradients and patterns** instead of flat colors
- **Create depth through overlays**
- **Use subtle noise/grain** for texture
### Gradient Patterns
```css
/* Radial gradient with multiple stops */
.gradient-bg-1 {
background: radial-gradient(
circle at 20% 50%,
rgba(255, 46, 151, 0.3) 0%,
rgba(0, 217, 255, 0.2) 50%,
rgba(10, 14, 39, 1) 100%
);
}
/* Angular gradient with hard stops */
.gradient-bg-2 {
background: linear-gradient(
135deg,
#667eea 0%,
#764ba2 25%,
#f093fb 50%,
#4facfe 100%
);
}
/* Mesh gradient (layered) */
.gradient-bg-3 {
background:
radial-gradient(at 0% 0%, rgba(255, 113, 206, 0.4) 0, transparent 50%),
radial-gradient(at 100% 0%, rgba(1, 205, 254, 0.4) 0, transparent 50%),
radial-gradient(at 100% 100%, rgba(185, 103, 255, 0.4) 0, transparent 50%),
radial-gradient(at 0% 100%, rgba(5, 255, 161, 0.4) 0, transparent 50%),
#1a0033;
}
/* Noise texture overlay */
.textured-bg {
background: var(--bg-primary);
position: relative;
}
.textured-bg::before {
content: '';
position: absolute;
inset: 0;
background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 400 400' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noiseFilter'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noiseFilter)'/%3E%3C/svg%3E");
opacity: 0.05;
mix-blend-mode: overlay;
}
/* Grid pattern background */
.grid-bg {
background-image:
linear-gradient(rgba(255, 255, 255, 0.05) 1px, transparent 1px),
linear-gradient(90deg, rgba(255, 255, 255, 0.05) 1px, transparent 1px);
background-size: 50px 50px;
}
```
## Workflow: Building a Distinctive Interface
When creating a new frontend interface, follow this sequence:
### 1. Choose Your Aesthetic Reference
Pick a clear inspiration: "Cyberpunk movie UI", "Nordic minimalism", "90s brutalism", "Retro-futurism", etc.
### 2. Set Up Design Tokens
```css
:root {
/* Typography */
--font-display: [distinctive font];
--font-body: [complementary font];
--weight-thin: 100;
--weight-black: 900;
/* Colors (from chosen theme) */
--bg-primary: [dark base];
--bg-secondary: [slightly lighter];
--accent-1: [bold color 1];
--accent-2: [bold color 2];
--text-primary: [high contrast];
--text-secondary: [medium contrast];
/* Motion */
--ease-out: cubic-bezier(0.16, 1, 0.3, 1);
--duration-fast: 0.3s;
--duration-base: 0.6s;
--duration-slow: 0.9s;
/* Spacing */
--space-xs: 0.5rem;
--space-sm: 1rem;
--space-md: 2rem;
--space-lg: 4rem;
--space-xl: 8rem;
}
```
### 3. Apply All Four Dimensions
```html
<!-- Example: Hero section with all four dimensions -->
<div class="hero textured-bg gradient-bg-1">
<h1 class="fade-in stagger-1" style="font-family: var(--font-display); font-weight: var(--weight-black);">
Bold Headline
</h1>
<p class="fade-in stagger-2" style="font-family: var(--font-body); font-weight: var(--weight-light);">
Supporting text with extreme weight contrast
</p>
<button class="fade-in stagger-3 cta-button">
Call to Action
</button>
</div>
```
### 4. Test Against "AI Slop" Checklist
❌ Avoid:
- Inter or Roboto as primary font
- Font weights: 400, 500, 600 (too safe)
- Purple-blue gradient backgrounds
- No page-load animation
- Flat white/gray backgrounds
- Pastel low-contrast colors
✅ Aim for:
- Distinctive font pairing
- Extreme weight contrast (100-200 vs 800-900)
- Cohesive color theme with clear reference
- Orchestrated entrance animation
- Layered/textured backgrounds
- Bold, memorable aesthetic
## Examples by Use Case
### Landing Page
- **Typography**: Display font at 900 weight, body at 200
- **Color**: Cyberpunk or retro-futurism theme
- **Motion**: Staggered hero elements (0.1s delay each)
- **Background**: Mesh gradient + noise texture
### Dashboard
- **Typography**: Monospace for data, sans-serif at 800 for headers
- **Color**: Dark mode with 2-3 accent colors for status
- **Motion**: Slide-in sidebar, fade-in cards
- **Background**: Subtle grid pattern + dark gradient
### Marketing Site
- **Typography**: Serif display (Playfair) + sans body
- **Color**: High-contrast brutalist or vibrant vaporwave
- **Motion**: Scroll-triggered reveals + parallax
- **Background**: Bold gradients with geometric overlays
### Portfolio
- **Typography**: Variable font with weight range 300-900
- **Color**: Minimal with one bold accent
- **Motion**: Project cards stagger on load
- **Background**: Radial gradient + grain texture
## Implementation Tips
1. **Always include Google Fonts or font files** - Don't assume system fonts
2. **Use CSS custom properties** - Makes theming systematic
3. **Test motion on slower devices** - Reduce animation if `prefers-reduced-motion`
4. **Provide theme variations** - Light/dark mode using same token system
5. **Document your aesthetic reference** - Helps maintain consistency
## Quick Start Template
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- Distinctive fonts -->
<link href="https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@300;700;900&family=Inter:wght@200;500&display=swap" rel="stylesheet">
<style>
:root {
/* Typography */
--font-display: 'Space Grotesk', sans-serif;
--font-body: 'Inter', sans-serif;
--weight-light: 200;
--weight-bold: 700;
--weight-black: 900;
/* Cyberpunk theme */
--bg-primary: #0a0e27;
--bg-secondary: #1a1f3a;
--accent-1: #ff2e97;
--accent-2: #00d9ff;
--text-primary: #e4f1ff;
/* Motion */
--ease: cubic-bezier(0.16, 1, 0.3, 1);
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: var(--font-body);
font-weight: var(--weight-light);
background: var(--bg-primary);
color: var(--text-primary);
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
}
/* Layered gradient background */
body::before {
content: '';
position: fixed;
inset: 0;
background: radial-gradient(
circle at 20% 50%,
rgba(255, 46, 151, 0.2) 0%,
rgba(0, 217, 255, 0.1) 50%,
transparent 100%
);
z-index: -1;
}
h1 {
font-family: var(--font-display);
font-weight: var(--weight-black);
font-size: clamp(2rem, 8vw, 5rem);
letter-spacing: -0.03em;
margin-bottom: 1rem;
}
p {
font-size: clamp(1rem, 3vw, 1.25rem);
letter-spacing: 0.01em;
margin-bottom: 2rem;
opacity: 0.9;
}
.cta {
background: var(--accent-1);
color: var(--bg-primary);
font-family: var(--font-display);
font-weight: var(--weight-bold);
padding: 1rem 2rem;
border: none;
border-radius: 0.5rem;
font-size: 1.125rem;
cursor: pointer;
transition: transform 0.2s var(--ease);
}
.cta:hover {
transform: translateY(-2px);
}
/* Staggered animations */
.fade-in {
opacity: 0;
animation: fadeInUp 0.8s var(--ease) forwards;
}
.stagger-1 { animation-delay: 0.1s; }
.stagger-2 { animation-delay: 0.2s; }
.stagger-3 { animation-delay: 0.3s; }
@keyframes fadeInUp {
from {
opacity: 0;
transform: translateY(30px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
@media (prefers-reduced-motion: reduce) {
.fade-in {
animation: none;
opacity: 1;
}
}
</style>
</head>
<body>
<main>
<h1 class="fade-in stagger-1">Distinctive Design</h1>
<p class="fade-in stagger-2">Bold typography, cohesive colors, orchestrated motion.</p>
<button class="cta fade-in stagger-3">Get Started</button>
</main>
</body>
</html>
```
---
## When to Use This Skill
Use this skill when:
- Building landing pages, marketing sites, or portfolios
- Creating dashboards or web applications where aesthetics matter
- The user asks for "modern", "distinctive", or "eye-catching" design
- You want to avoid generic-looking interfaces
- The project needs a strong visual identity
By following these patterns, you'll create interfaces that feel intentional, memorable, and distinctively non-generic.
+46
View File
@@ -0,0 +1,46 @@
# Docker Compose Creator
## Overview
This skill provides automated assistance for docker compose creator tasks within the DevOps Basics domain.
## When to Use
This skill activates automatically when you:
- Mention "docker compose creator" in your request
- Ask about docker compose creator patterns or best practices
- Need help with foundational devops skills covering version control, containerization, basic ci/cd, and infrastructure fundamentals.
## Instructions
1. Provides step-by-step guidance for docker compose creator
2. Follows industry best practices and patterns
3. Generates production-ready code and configurations
4. Validates outputs against common standards
## Examples
**Example: Basic Usage**
Request: "Help me with docker compose creator"
Result: Provides step-by-step guidance and generates appropriate configurations
## Prerequisites
- Relevant development environment configured
- Access to necessary tools and services
- Basic understanding of devops basics concepts
## Output
- Generated configurations and code
- Best practice recommendations
- Validation results
## Error Handling
| Error | Cause | Solution |
|-------|-------|----------|
| Configuration invalid | Missing required fields | Check documentation for required parameters |
| Tool not found | Dependency not installed | Install required tools per prerequisites |
| Permission denied | Insufficient access | Verify credentials and permissions |
## Resources
- Official documentation for related tools
- Best practices guides - Community examples and tutorials
## Related Skills
Part of the **DevOps Basics** skill category.
Tags: devops, git, docker, ci-cd, infrastructure
+314
View File
@@ -0,0 +1,314 @@
---
name: docker
description: Container-based development for isolated, reproducible environments. Use when running npm commands, installing packages, executing code, or managing project dependencies. Trigger phrases include "npm install", "run the build", "start the server", "install package", or any code execution request.
---
# Docker Development Skill
Execute all package installations and code execution inside Docker containers. This keeps the host machine clean and ensures consistent environments across projects.
## Core Principle
**NEVER run `npm`, `node`, `npx`, or project scripts directly on the host machine.**
Instead, use `docker exec` or ensure the container is running the dev server.
## Pre-Flight Check (MANDATORY)
**Before running ANY npm/node command, Claude Code MUST verify the container is running.**
Run this check first:
```bash
docker ps --filter "name=<project-name>" --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"
```
**Expected output:**
```
NAMES STATUS PORTS
<project-name>-dev-1 Up X minutes 0.0.0.0:3000->3000/tcp
```
**If container is NOT running:**
```bash
# Navigate to project root first
cd /path/to/your/project
# Start container
docker-compose --profile dev up dev -d
# Verify it started
docker ps --filter "name=<project-name>"
```
**If container shows "Exited":**
```bash
# Check why it exited
docker logs <project-name>-dev-1 --tail 20
# Remove and restart
docker-compose --profile dev down
docker-compose --profile dev up dev -d
```
## Quick Reference
### Check Container Status
```bash
# List running containers for current project
docker ps --filter "name=<project-name>"
# Check container logs
docker logs <project-name>-dev-1 --tail 50
# Check if dev server is responding
curl -s http://localhost:3000 > /dev/null && echo "Server running" || echo "Server not running"
```
### Start/Stop Containers
```bash
# Start development container (from project root)
docker-compose --profile dev up dev -d
# Stop container
docker-compose --profile dev down
# Restart container
docker-compose --profile dev restart dev
# Rebuild after Dockerfile changes
docker-compose --profile dev up dev -d --build
```
### Execute Commands Inside Container
```bash
# Install a package
docker exec -it <project-name>-dev-1 npm install <package-name>
# Install dev dependency
docker exec -it <project-name>-dev-1 npm install -D <package-name>
# Run tests
docker exec -it <project-name>-dev-1 npm test
# Run type checking
docker exec -it <project-name>-dev-1 npm run typecheck
# Run linting
docker exec -it <project-name>-dev-1 npm run lint
# Run build
docker exec -it <project-name>-dev-1 npm run build
# Open shell inside container
docker exec -it <project-name>-dev-1 /bin/sh
# Run any arbitrary command
docker exec -it <project-name>-dev-1 <command>
```
## When to Use Docker exec
| Operation | Use docker exec? | Reason |
|-----------|------------------|--------|
| `npm install` | ✅ Yes | Packages install in container |
| `npm run dev` | ❌ No | Already running via docker-compose |
| `npm test` | ✅ Yes | Tests run in container environment |
| `npm run build` | ✅ Yes | Build happens in container |
| `git` commands | ❌ No | Git runs on host (manages files) |
| File editing | ❌ No | Volume mount syncs automatically |
| Database migrations | ✅ Yes | Uses container's Node environment |
## Container Architecture
```
┌─────────────────────────────────────────────────────────────┐
│ HOST (macOS/Linux/Windows) │
│ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ Docker Container (<project-name>-dev-1) │ │
│ │ │ │
│ │ Node 20 Alpine │ │
│ │ └── node_modules/ (container-only) │ │
│ │ └── Dev server (port 3000) │ │
│ │ │ │
│ │ Volume Mounts: │ │
│ │ └── .:/app (source code sync) │ │
│ │ └── node_modules:/app/node_modules (persist deps) │ │
│ └─────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ Port 3000 mapped │
│ │ │
│ ▼ │
│ http://localhost:3000 │
└─────────────────────────────────────────────────────────────┘
```
## Volume Mount Behavior
The `docker-compose.yml` mounts the project directory into the container:
```yaml
volumes:
- .:/app # Source code (synced)
- /app/node_modules # Dependencies (container-only)
```
**What this means:**
- Source code changes on host are immediately visible in container
- `node_modules/` in container is separate from any on host
- Hot reload works automatically with most frameworks
## Troubleshooting
### Container Not Running
```bash
# Check if container exists
docker ps -a --filter "name=<project-name>"
# If exited, check why
docker logs <project-name>-dev-1
# Restart
docker-compose --profile dev up dev -d
```
### Port Already in Use
```bash
# Find what's using the port
lsof -i :3000
# Kill the process or change port in docker-compose.yml
```
### Module Not Found Errors
```bash
# Rebuild container with fresh dependencies
docker-compose --profile dev down
docker-compose --profile dev build --no-cache dev
docker-compose --profile dev up dev -d
```
### File Changes Not Reflecting
```bash
# Check volume mounts
docker inspect <project-name>-dev-1 | grep -A 10 "Mounts"
# Restart container
docker-compose --profile dev restart dev
```
## Project Configuration
After installing this skill, update the placeholders for your project:
| Setting | Example Value |
|---------|---------------|
| Container name | `my-app-dev-1` |
| Port | 3000 (or your app's port) |
| Node version | 20 (Alpine) |
| Dev command | `npm run dev -- --host 0.0.0.0` |
### Environment Variables
Required env vars are loaded from `.env` file via docker-compose.
If a command needs a specific env var:
```bash
docker exec -it -e MY_VAR=value <project-name>-dev-1 <command>
```
## Best Practices
1. **Always check container status** before running commands
2. **Use `docker exec`** for all npm/node operations
3. **Let volume mounts** handle file syncing (no manual copying)
4. **Rebuild image** after changing `package.json` or `Dockerfile`
5. **Check logs** if something isn't working
## Integration with Claude Code
When Claude Code needs to:
| Task | Action |
|------|--------|
| Install dependency | `docker exec -it <project-name>-dev-1 npm install <pkg>` |
| Run tests | `docker exec -it <project-name>-dev-1 npm test` |
| Check types | `docker exec -it <project-name>-dev-1 npm run typecheck` |
| Build project | `docker exec -it <project-name>-dev-1 npm run build` |
| Start dev server | Container already runs it via docker-compose |
| Edit files | Edit directly (volume mount syncs) |
| Git operations | Run on host (not in container) |
## Sample docker-compose.yml
```yaml
services:
app:
build:
context: .
dockerfile: Dockerfile
ports:
- "3000:3000"
environment:
- NODE_ENV=production
env_file:
- .env
restart: unless-stopped
dev:
build:
context: .
dockerfile: Dockerfile.dev
ports:
- "3000:3000"
volumes:
- .:/app
- /app/node_modules
environment:
- NODE_ENV=development
env_file:
- .env
profiles:
- dev
```
## Sample Dockerfile.dev
```dockerfile
FROM node:20-alpine
WORKDIR /app
# Install dependencies for native modules
RUN apk add --no-cache python3 make g++
# Copy package files and any scripts needed for postinstall
COPY package*.json ./
COPY scripts/ ./scripts/
# Install all dependencies
RUN npm install
# Copy source code
COPY . .
# Expose port
EXPOSE 3000
# Set environment variables
ENV HOST=0.0.0.0
ENV PORT=3000
ENV NODE_ENV=development
# Start development server
CMD ["npm", "run", "dev", "--", "--host", "0.0.0.0"]
```
+70
View File
@@ -0,0 +1,70 @@
# Database & Drizzle ORM Standards
This guide covers the database structure, schema conventions, and query best practices using **Drizzle ORM** (MySQL) in the CineK (kr-phim) project.
---
## 1. Database Configuration & Schema
- **Database Dialect**: MySQL
- **Schema Location**: `/server/database/schema.ts`
- **Migrations Folder**: `/server/database/migrations`
- **Config file**: `drizzle.config.ts`
### Migration Commands:
- Generate a new migration file: `npm run db:generate`
- Apply migrations to database: `npm run db:migrate`
---
## 2. Core Schemas & Types Reference
The database is structured around four primary tables. Always import types and schema objects from `~/server/database/schema`:
### Users (`users`)
- Used for authentication and roles (admin, user).
- Schema definition:
- `id`: Auto-incrementing primary key.
- `name`: Full name.
- `email`: Unique email address.
- `password`: Hashed password (using bcryptjs).
- `role`: User authorization level (`admin` or `user`).
- `active`: Boolean to enable/disable accounts.
### Movies (`movies`)
- Contains metadata for all imported/scraped movies.
- Key properties:
- `source`: The origin API provider (e.g. `kkphim`, `ophim`, `nguonc`).
- `slug`: Unique slug path for URL routing.
- `categories` & `countries`: Stored as JSON arrays of strings.
- `actors`: JSON array of objects `[ { name, originalName, role, avatar } ]`.
- **Custom Overrides**: Admin can overwrite fields with `customPoster`, `customThumb`, `customContent`, `customEpisodes`, and `customServers`.
### Comments (`comments`) & Comment Votes (`comment_votes`)
- Enables interactive comments under movies with parent-child relationships for nested threads.
- Supports pinning, marking as spoiler, anonymous posting, and like/dislike reactions tracking.
---
## 3. Server Endpoints Integration
When querying the database from server routes (`/server/api/*`):
- Import the database client from a global instance (e.g., `drizzle` or `db` composable).
- Use proper relational joins or index queries to keep performance fast.
- Ensure authentication checks are in place for destructive endpoints (e.g. validating token session via `/api/auth/*` before modifying movies or comments).
Example Query:
```typescript
import { db } from '~/server/database' // check project db import structure
import { movies } from '~/server/database/schema'
import { eq } from 'drizzle-orm'
export default defineEventHandler(async (event) => {
const query = getQuery(event)
const slug = query.slug as string
if (!slug) {
throw createError({ statusCode: 400, message: 'Slug is required' })
}
const result = await db.select().from(movies).where(eq(movies.slug, slug)).limit(1)
return result[0] || null
})
```
+107
View File
@@ -0,0 +1,107 @@
# Frontend Design and Styling Guidelines
This guide defines the design system, styling philosophy, and component design patterns used in the CineK (kr-phim) project. All AI agents MUST read and strictly adhere to these guidelines when modifying or creating any frontend UI.
---
## 1. Core Philosophy: Premium & Dynamic Aesthetics
CineK is a premium movie streaming website. Simple, generic, or plain-looking user interfaces are NOT acceptable. Every UI must feel premium, modern, and interactive:
- **Curated Palettes**: Avoid generic primary colors (e.g. basic `#0000ff` blue or `#ff0000` red). Instead, use the project's tailored palettes (CineK yellow, dark/slate neutrals).
- **Responsive & Alive**: Every interactive element (buttons, cards, inputs, tabs) must have hover/active states with smooth transitions.
- **Glassmorphism & Gradients**: Use smooth, semi-transparent overlays (`bg-white/5` with `backdrop-blur-md`) and linear-gradient background shapes on dark elements to create depth.
- **Typography Hierarchy**: Maintain strict typographical hierarchies using clean sans-serif typography (`Be Vietnam Pro`). Avoid raw default sans-serif when possible.
---
## 2. Global Typography & Styling Variables
We use **Tailwind CSS v4** and customize the theme variables inside `app/assets/css/main.css`:
### Font
- **Primary Font**: `"Be Vietnam Pro"`, ui-sans-serif, system-ui, sans-serif
- Imported globally via Google Fonts API.
### Primary Color Palette (CineK Yellow)
Our brand color is a warm yellow:
- `--color-cinek-50`: `#fefce8`
- `--color-cinek-100`: `#fef9c3`
- `--color-cinek-300`: `#fde047`
- `--color-cinek-400`: `#facc15`
- `--color-cinek-500`: `#eab308` (Primary brand color)
- `--color-cinek-950`: `#422006`
### Theme Backgrounds
- **Dark Mode Background**: `#0E111A` (Body background for the main streaming portal)
- **Admin Light Mode Background**: `#f8fafc` (Body background for light administration views)
---
## 3. Utility Class Design System
A central set of class conventions is defined in `main.css`. Always prefer these predefined styles over ad-hoc Tailwind classes to keep the markup clean and maintain visual consistency.
| Utility Class | Description | Standard Usage |
|---|---|---|
| `.admin-page` | Layout wrapper for admin views | `<div class="admin-page">` |
| `.admin-card` | Container with borders and hover state | `<div class="admin-card">` |
| `.admin-card-gradient` | Container with subtle top highlights | `<div class="admin-card-gradient">` |
| `.admin-input` | Standard styling for input fields (height: 11) | `<input class="admin-input" />` |
| `.admin-input-sm` | Compact input fields for dense tables | `<input class="admin-input-sm" />` |
| `.admin-btn-primary` | Main action buttons (brand blue/yellow) | `<button class="admin-btn-primary">` |
| `.admin-btn-secondary` | Muted/Bordered secondary actions | `<button class="admin-btn-secondary">` |
| `.admin-btn-danger` | Alert/Destructive actions | `<button class="admin-btn-danger">` |
| `.admin-badge` | Visual badges (status, tags) | `<span class="admin-badge">` |
| `.admin-label` | Small uppercase tracker label for inputs | `<label class="admin-label">` |
| `.admin-section-title` | Title for primary view section headings | `<h1 class="admin-section-title">` |
| `.admin-section-subtitle` | Context/Subtitle beneath a section title | `<p class="admin-section-subtitle">` |
| `.admin-num` | Numbers/Metrics (tabular-nums font) | `<span class="admin-num">` |
---
## 4. Dark vs. Light Theme Rules (Admin Layout)
The admin layout uses an `.admin-light` wrapper that forces a crisp enterprise look. Do not hardcode dark utilities (`dark:...`) unless you specifically want dark behavior in both modes.
In `.admin-light` mode, the global styles in `main.css` are overridden:
- Global text colors mapping to `text-slate-400`, `text-zinc-500`, etc., are forced to darker shades (`#475569` or `#334155`) to comply with accessibility standards (contrast ratios).
- Cards become solid white, backgrounds become light gray-blue (`#f8fafc`), and border properties adapt to `#e2e8f0`.
When coding admin components:
- **Never** use light-gray text on a white background. Ensure headings are `#0f172a` (Slate 900) and descriptions are `#334155` (Slate 700).
- Input placeholders must remain readable (`#94a3b8` - Slate 400).
---
## 5. UI Components & Icon Conventions
- **Icons**: Do not write raw `<svg>` tags. Always use the built-in `<AppIcon>` component. This wraps FontAwesome icons securely.
- Usage: `<AppIcon name="film" class="size-5" />`
- Allowed names conform to common Lucide / FontAwesome names (e.g. `home`, `film`, `users`, `settings`, `x`, `log-out`, `menu`).
- **Sliders & Carousels**: Always use the **Swiper** library (`swiper` dependencies are present in `package.json`).
- **Scrollbars**: Apply the `.admin-scrollbar` utility class for sleek custom scrollbars in scrollable panels or tables.
- **Animations**: Use predefined transitions like `.hero-fade-enter-active` or Vue transitions with `name="modal-fade"` / `name="sidebar-fade"` for smooth entrance and exit animations.
---
## 6. Official Anthropic / Claude Code Frontend Design Principles
Adopt the mindset of a design lead at a specialized studio. Avoid generic, templated default designs. Follow these exact rules from the Claude Code `frontend-design` plugin:
### Grounding in the Subject
- State one concrete subject, audience, and the view's single job before coding.
- Match typography, color, and layout to the specific cinematic context of the Korean movie database (CineK).
### Visual & Typography Guidelines
- **Hero/Header**: Make the hero element a "thesis" presenting the most characteristic thing about the movie database. Avoid the templated "big number with a small label + gradient accent" unless it truly fits.
- **Typography Pairing**: Pair display and body fonts deliberately. Do not let text act as a neutral vehicle; make the type treatment a memorable part of the design.
- **Structure**: Numbering, badges, dividing lines, and labels must represent real structure and sequence in the movie database. Do not use numbers (like 01 / 02 / 03) unless ordering carries essential information.
- **Motion**: Use motion deliberately (loading animations, scroll reveals, hover interactions). Avoid cluttered animations that scream "AI-generated". Less is more.
### Process: The Two-Pass Workflow
1. **Pass 1: Brainstorming**: First define a token system.
- **Color**: 46 named hex values.
- **Type**: Choose faces for the different typography roles.
- **Layout**: Draft a layout concept with one-sentence descriptions.
- **Signature**: Define the single unique element this view will be remembered by.
2. **Pass 2: Critique & Build**: Review the plan against generic templates. If it looks like a generic SaaS dashboard, revise it. Once validated, build the code exactly following the plan.
### Restraint & Copywriting
- **Restraint**: Spend boldness in one place (the signature element). Keep everything else clean and disciplined.
- **Copywriting**: Words are design material. Write from the user's side of the screen using active voice.
- E.g., "Save changes," not "Submit".
- Empty states should be invitations to act, and errors should explain what went wrong and how to fix it without being vague.
+96
View File
@@ -0,0 +1,96 @@
# Nuxt & Vue Coding Standards
This guide outlines code style, architectural conventions, and implementation practices for Nuxt 4 and Vue 3 in the CineK (kr-phim) project.
---
## 1. Vue 3 & Composition API
- **Single File Components (SFC)**: Always use the `<script setup lang="ts">` syntax. Do not use options API or the traditional setup function.
- **Language**: TypeScript is mandatory. Ensure all refs, computed properties, props, and emit interfaces are fully typed.
- **Imports**:
- **Do NOT** manually import core Vue/Nuxt APIs (e.g., `ref`, `computed`, `watch`, `onMounted`, `useRoute`, `useRouter`, `useFetch`, `useRuntimeConfig`). Nuxt auto-imports these.
- Keep custom component/composable imports clean.
### Component Structure Example:
```vue
<script setup lang="ts">
// Props definition
interface Props {
movieId: number
active?: boolean
}
const props = withDefaults(defineProps<Props>(), {
active: false
})
// Emits definition
const emit = defineEmits<{
(e: 'update', value: boolean): void
}>()
// Reactivity
const localActive = ref(props.active)
// Computed
const statusText = computed(() => localActive.value ? 'Active' : 'Inactive')
// Methods
function toggle() {
localActive.value = !localActive.value
emit('update', localActive.value)
}
</script>
<template>
<div class="admin-card p-4">
<span class="admin-label">{{ statusText }}</span>
<button class="admin-btn-primary mt-2" @click="toggle">
Toggle Status
</button>
</div>
</template>
```
---
## 2. Nuxt 4 Directory Structure & Organization
All code must align with the Nuxt 4 structure under the `/app` folder:
- **`app/pages/`**: File-system based routing. Keep files structured logically (e.g., `app/pages/admin/phim/index.vue`).
- **`app/components/`**: Place reusable components here. Nuxt auto-imports all components inside this folder. Use PascalCase or kebab-case when using them in templates (e.g., `<AppHeader />`).
- **`app/composables/`**: Store custom reactive functions here (e.g. `useAuth.ts`).
- **`app/layouts/`**: Core layouts (e.g., `admin.vue`).
- **`app/utils/`**: Helper utility functions.
- **`server/`**: API endpoints, middleware, and database operations.
---
## 3. Data Fetching Guidelines
Nuxt 4 provides specific wrappers for network requests. Use them properly to maintain SSR compatibility:
- **`useFetch`**: Use for fetching data during initial page load/rendering. Supports automatic refresh and refetching.
```typescript
const { data: movies, pending, error } = await useFetch('/api/movies', {
query: { limit: 10 }
})
```
- **`$fetch`**: Use for event-driven requests, client-side actions, form submissions, and mutation events.
```typescript
async function handleSubmit() {
await $fetch('/api/movies', {
method: 'POST',
body: { name: 'New Movie' }
})
}
```
- **Request Headers**: When fetching data inside server-side calls that require authentication, forward cookies appropriately:
```typescript
const { data: user } = await useFetch('/api/auth/me', {
headers: useRequestHeaders(['cookie']),
})
```
---
## 4. State Management
- Prefer simple composables with `ref` or `reactive` for shared local/global state.
- Keep state local to views unless shared across layouts.