Streamline CLAUDE.md: remove redundancy, fix inaccuracies
All checks were successful
Deploy / deploy (push) Successful in 1m22s
All checks were successful
Deploy / deploy (push) Successful in 1m22s
Remove exhaustive component/test/terraform listings that are easily discoverable. Fix non-existent typecheck script reference. Consolidate deployment info into single table. Add missing Matomo env vars and single-test-file command.
This commit is contained in:
298
CLAUDE.md
298
CLAUDE.md
@@ -5,200 +5,117 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
|
|||||||
## Project Overview
|
## Project Overview
|
||||||
|
|
||||||
Filamenteka is a 3D printing filament inventory management system for tracking Bambu Lab filaments. It consists of:
|
Filamenteka is a 3D printing filament inventory management system for tracking Bambu Lab filaments. It consists of:
|
||||||
- **Frontend**: Next.js app with React, TypeScript, and Tailwind CSS (static export)
|
- **Frontend**: Next.js app with React, TypeScript, and Tailwind CSS (static export to `/out`)
|
||||||
- **Backend**: Node.js API server with PostgreSQL database
|
- **Backend**: Node.js Express API server (`/api/server.js`) with PostgreSQL database
|
||||||
- **Infrastructure**: AWS (CloudFront + S3 for frontend, EC2 for API, RDS for database)
|
- **Infrastructure**: AWS (CloudFront + S3 for frontend, EC2 for API, RDS for database)
|
||||||
|
- **Repository**: `git.demirix.dev/dax/Filamenteka`
|
||||||
|
|
||||||
## Critical Rules
|
## Critical Rules
|
||||||
|
|
||||||
- NEVER mention ANY author in commits. No author tags or attribution
|
- NEVER mention ANY author in commits. No author tags or attribution of any kind
|
||||||
- NEVER mention AI/assistant names anywhere
|
|
||||||
- Keep commit messages clean and professional with NO attribution
|
|
||||||
- Build for AMD64 Linux when deploying (development is on ARM macOS)
|
- Build for AMD64 Linux when deploying (development is on ARM macOS)
|
||||||
- Always run security checks before commits
|
- Always run security checks before commits (Husky pre-commit hook does this automatically)
|
||||||
|
|
||||||
## Common Commands
|
## Common Commands
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Frontend Development
|
# Development
|
||||||
npm run dev # Start Next.js development server (port 3000)
|
npm run dev # Start Next.js dev server (port 3000)
|
||||||
npm run build # Build static export to /out directory
|
npm run build # Build static export to /out
|
||||||
npm run lint # Run ESLint
|
npm run lint # ESLint
|
||||||
npm run typecheck # Run TypeScript type checking
|
npm test # Jest tests
|
||||||
npm test # Run Jest tests
|
npm run test:watch # Jest watch mode
|
||||||
npm run test:watch # Run Jest in watch mode
|
npm test -- --testPathPattern=__tests__/components/ColorCell # Run single test file
|
||||||
|
|
||||||
# API Development (in /api directory)
|
# API Development
|
||||||
cd api && npm run dev # Start API server with nodemon (port 4000)
|
cd api && npm run dev # Start API with nodemon (port 4000)
|
||||||
|
|
||||||
# Security & Quality
|
# Quality Gates
|
||||||
npm run security:check # Check for credential leaks (scripts/security/security-check.js)
|
npm run security:check # Credential leak detection
|
||||||
npm run test:build # Test if build succeeds without creating files
|
npm run test:build # Verify build succeeds without deploying
|
||||||
./scripts/pre-commit.sh # Runs security, build, and test checks (triggered by husky)
|
npx tsc --noEmit # TypeScript type checking
|
||||||
|
|
||||||
# Database Migrations
|
# Database
|
||||||
npm run migrate # Run pending migrations locally
|
npm run migrate # Run pending migrations locally
|
||||||
npm run migrate:clear # Clear migration history (development only)
|
|
||||||
scripts/update-db-via-aws.sh # Run migrations on production RDS via EC2
|
scripts/update-db-via-aws.sh # Run migrations on production RDS via EC2
|
||||||
|
|
||||||
# Deployment
|
# Deployment (auto via CI/CD on push to main, or manual)
|
||||||
scripts/deploy-api-update.sh # Deploy API to EC2 via AWS SSM (recommended)
|
scripts/deploy-api-update.sh # Deploy API to EC2 via AWS SSM
|
||||||
scripts/deploy-frontend.sh # Manual frontend deployment helper
|
scripts/deploy-frontend.sh # Manual frontend deploy to S3/CloudFront
|
||||||
```
|
```
|
||||||
|
|
||||||
## Architecture
|
## Architecture
|
||||||
|
|
||||||
### Frontend Structure (Next.js App Router)
|
### Frontend (Next.js App Router)
|
||||||
- `/app` - Next.js 13+ app directory structure
|
- `/app/page.tsx` — Public filament inventory table (home page)
|
||||||
- `/page.tsx` - Public filament inventory table
|
- `/app/upadaj/` — Admin panel: login, `/dashboard` (filament CRUD), `/colors` (color management), `/requests` (customer color requests)
|
||||||
- `/upadaj` - Admin panel (password protected)
|
- `/src/services/api.ts` — Axios instance with auth interceptors (auto token injection, 401/403 redirect)
|
||||||
- `/page.tsx` - Admin login
|
- `/src/data/bambuLabColors.ts` — Primary color-to-hex mapping with gradient support (used by `ColorCell` component)
|
||||||
- `/dashboard/page.tsx` - Filament CRUD operations
|
- `/src/data/bambuLabColorsComplete.ts` — Extended color database grouped by finish type (used by filters)
|
||||||
- `/colors/page.tsx` - Color management
|
|
||||||
- `/requests/page.tsx` - Customer color requests
|
|
||||||
- `/src` - Source files
|
|
||||||
- `/components` - React components
|
|
||||||
- `/services/api.ts` - Axios instance with auth interceptors
|
|
||||||
- `/data` - Color definitions (bambuLabColors.ts, bambuLabColorsComplete.ts)
|
|
||||||
- `/types` - TypeScript type definitions
|
|
||||||
|
|
||||||
### API Structure
|
### API (`/api/server.js`)
|
||||||
- `/api` - Node.js Express server (runs on EC2, port 80)
|
Single-file Express server running on EC2 (port 80). All routes inline.
|
||||||
- `/server.js` - Main Express server with all routes inline
|
|
||||||
- Database: PostgreSQL on AWS RDS
|
|
||||||
- Endpoints: `/api/login`, `/api/filaments`, `/api/colors`, `/api/sale/bulk`, `/api/color-requests`
|
- Endpoints: `/api/login`, `/api/filaments`, `/api/colors`, `/api/sale/bulk`, `/api/color-requests`
|
||||||
|
- Auth: JWT tokens with 24h expiry, single admin user (password from `ADMIN_PASSWORD` env var)
|
||||||
|
|
||||||
### Key Components
|
### Database (PostgreSQL on RDS)
|
||||||
- `FilamentTableV2` - Main inventory display with sorting/filtering
|
Key schemas and constraints:
|
||||||
- `SaleManager` - Bulk sale management interface
|
|
||||||
- `BulkFilamentPriceEditor` - Bulk price modification interface
|
|
||||||
- `ColorCell` - Smart color rendering with gradient support
|
|
||||||
- `EnhancedFilters` - Advanced filtering system
|
|
||||||
- `ColorRequestForm` - Customer color request form
|
|
||||||
- `ColorRequestModal` - Modal for color requests
|
|
||||||
- `SaleCountdown` - Sale timer display
|
|
||||||
- `MatomoAnalytics` - Analytics tracking
|
|
||||||
- `BackToTop` - Scroll-to-top button
|
|
||||||
- `MaterialBadge`, `ColorSwatch`, `InventoryBadge` - Display components
|
|
||||||
|
|
||||||
### Data Models
|
```
|
||||||
|
filaments: id, tip (material), finish, boja (color), refill, spulna, kolicina, cena, sale_*
|
||||||
#### Filament Schema (PostgreSQL)
|
colors: id, name, hex, cena_refill (default 3499), cena_spulna (default 3999)
|
||||||
```sql
|
color_requests: id, color_name, message, contact_name, contact_phone, status
|
||||||
filaments: {
|
|
||||||
id: UUID,
|
|
||||||
tip: VARCHAR(50), # Material type (PLA, PETG, ABS)
|
|
||||||
finish: VARCHAR(50), # Finish type (Basic, Matte, Silk)
|
|
||||||
boja: VARCHAR(100), # Color name
|
|
||||||
refill: INTEGER, # Refill spool count
|
|
||||||
spulna: INTEGER, # Regular spool count
|
|
||||||
kolicina: INTEGER, # Total quantity (refill + spulna)
|
|
||||||
cena: VARCHAR(50), # Price
|
|
||||||
sale_active: BOOLEAN, # Sale status
|
|
||||||
sale_percentage: INTEGER,# Sale discount
|
|
||||||
sale_end_date: TIMESTAMP # Sale expiry
|
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Color Schema
|
**Critical constraints:**
|
||||||
```sql
|
- `filaments.boja` → FK to `colors.name` (ON UPDATE CASCADE) — colors must exist before filaments reference them
|
||||||
colors: {
|
- `kolicina = refill + spulna` — enforced by check constraint
|
||||||
id: UUID,
|
- Migrations in `/database/migrations/` with sequential numbering (currently up to `020_`)
|
||||||
name: VARCHAR(100), # Color name (must match filament.boja)
|
|
||||||
hex: VARCHAR(7), # Hex color code
|
|
||||||
cena_refill: INTEGER, # Refill price (default: 3499)
|
|
||||||
cena_spulna: INTEGER # Regular price (default: 3999)
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Color Requests Schema
|
## Key Patterns
|
||||||
```sql
|
|
||||||
color_requests: {
|
|
||||||
id: UUID,
|
|
||||||
color_name: VARCHAR(255), # Requested color name
|
|
||||||
message: TEXT, # Customer message
|
|
||||||
contact_name: VARCHAR(255), # Customer name (required)
|
|
||||||
contact_phone: VARCHAR(50), # Customer phone (required)
|
|
||||||
status: VARCHAR(20), # Status: pending, reviewed, fulfilled
|
|
||||||
created_at: TIMESTAMP
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Deployment
|
### Color Management (two-layer system)
|
||||||
|
1. **Database `colors` table**: Defines valid color names + pricing. Must be populated first due to FK constraint.
|
||||||
|
2. **Frontend `bambuLabColors.ts`**: Maps color names → hex codes for UI display. Supports solid (`hex: '#FF0000'`) and gradient (`hex: ['#HEX1', '#HEX2'], isGradient: true`).
|
||||||
|
3. Color names must match exactly between `colors.name`, `filaments.boja`, and `bambuLabColors.ts` keys.
|
||||||
|
4. The `ColorCell` component renders table row backgrounds from these mappings.
|
||||||
|
|
||||||
### Frontend (AWS CloudFront + S3)
|
### Adding New Colors
|
||||||
- **Primary Method**: CloudFront distribution with S3 origin
|
1. Add to database `colors` table (via admin panel at `/upadaj/colors` or migration)
|
||||||
- S3 bucket: `filamenteka-frontend`
|
2. Add hex mapping to `src/data/bambuLabColors.ts`
|
||||||
- CloudFront Function: `index-rewrite` for directory-to-index.html routing
|
3. Optionally add to `src/data/bambuLabColorsComplete.ts` finish groups
|
||||||
- Build output: Static files in `/out` directory (Next.js static export)
|
|
||||||
- Config: `next.config.js` (output: 'export'), `terraform/cloudfront-frontend.tf`
|
|
||||||
- Cache: 24h TTL for static assets, GET/HEAD methods cached
|
|
||||||
- OAC (Origin Access Control): S3 public access blocked, CloudFront-only access
|
|
||||||
- **CI/CD**: Gitea Actions workflow (`.gitea/workflows/deploy.yml`) auto-deploys on push to main
|
|
||||||
|
|
||||||
### API Server (EC2)
|
|
||||||
- Deployment via `scripts/deploy-api-update.sh` (uses AWS SSM to push updates)
|
|
||||||
- Instance ID: `i-03956ecf32292d7d9`
|
|
||||||
- Server IP: `3.71.161.51`
|
|
||||||
- Domain: `api.filamenteka.rs`
|
|
||||||
- Service: `node-api` (systemd)
|
|
||||||
- Deploy script pulls from Gitea main branch and restarts service
|
|
||||||
- IMPORTANT: When deploying API, remember to build for AMD64 Linux (not ARM macOS)
|
|
||||||
|
|
||||||
### Database (RDS PostgreSQL)
|
|
||||||
- Host: `filamenteka.ci7fsdlbzmag.eu-central-1.rds.amazonaws.com`
|
|
||||||
- User: `filamenteka_admin`
|
|
||||||
- Database: `filamenteka`
|
|
||||||
- Migrations in `/database/migrations/`
|
|
||||||
- Schema in `/database/schema.sql`
|
|
||||||
- Use `scripts/update-db-via-aws.sh` for running migrations on production
|
|
||||||
|
|
||||||
## Important Patterns
|
|
||||||
|
|
||||||
### API Communication
|
### API Communication
|
||||||
- All API calls organized in service modules (`src/services/api.ts`)
|
- Service modules in `src/services/api.ts`: `authService`, `colorService`, `filamentService`, `colorRequestService`
|
||||||
- Services: `authService`, `colorService`, `filamentService`, `colorRequestService`
|
|
||||||
- Axios instance with interceptors for automatic auth token injection
|
|
||||||
- Auth token stored in localStorage with 24h expiry
|
- Auth token stored in localStorage with 24h expiry
|
||||||
- Automatic redirect on 401/403 in admin routes (via response interceptor)
|
- Cache busting on filament fetches via timestamp query param
|
||||||
- Cache busting on filament fetches with timestamp query param
|
|
||||||
|
|
||||||
### Color Management
|
## CI/CD (Gitea Actions)
|
||||||
- Frontend color mappings in `src/data/bambuLabColors.ts` and `bambuLabColorsComplete.ts`
|
|
||||||
- Database color definitions in `colors` table with pricing (cena_refill, cena_spulna)
|
|
||||||
- ColorMapping interface supports both solid colors (hex string) and gradients (hex array)
|
|
||||||
- Automatic row coloring via ColorCell component based on filament.boja
|
|
||||||
- Special handling for gradient filaments (e.g., Cotton Candy Cloud)
|
|
||||||
- Foreign key constraint: filaments.boja → colors.name (ON UPDATE CASCADE)
|
|
||||||
|
|
||||||
### State Management
|
`.gitea/workflows/deploy.yml` triggers on push to `main`. Auto-detects changes via `git diff HEAD~1`:
|
||||||
- React hooks for local component state
|
- **Frontend changes** (anything outside `api/`): security check → tests → build → S3 deploy (3-tier cache: HTML no-cache, `_next/` immutable, rest 24h) → CloudFront invalidation
|
||||||
- No global state management library
|
- **API changes** (`api/` files): SSM command to EC2 to pull `server.js` from Gitea and restart `node-api` service
|
||||||
- Data fetching in components with useEffect
|
- Both run if both changed in a single push
|
||||||
- Service layer handles all API interactions
|
|
||||||
|
|
||||||
### Testing
|
## Deployment Details
|
||||||
- Jest + React Testing Library
|
|
||||||
- Tests in `__tests__/` directory
|
| Component | Target | Method |
|
||||||
- Config: `jest.config.js`, `jest.setup.js`
|
|-----------|--------|--------|
|
||||||
- Coverage goal: >80%
|
| Frontend | S3 `filamenteka-frontend` → CloudFront | Static export, OAC-protected |
|
||||||
- Run with `npm test` or `npm run test:watch`
|
| API | EC2 `i-03956ecf32292d7d9` | SSM, systemd `node-api` service |
|
||||||
- Test files include:
|
| Database | RDS `filamenteka.ci7fsdlbzmag.eu-central-1.rds.amazonaws.com` | Migrations via `scripts/update-db-via-aws.sh` |
|
||||||
- `ui-features.test.ts` - UI functionality
|
| DNS | Cloudflare | `api.filamenteka.rs` → EC2 |
|
||||||
- `api-integration.test.ts` - API interactions
|
| IaC | `/terraform/` | VPC, EC2, RDS, ALB, CloudFront, Cloudflare |
|
||||||
- `no-mock-data.test.ts` - Real data validation (ensures no fake/mock data)
|
|
||||||
- `color-management.test.ts` - Color CRUD operations
|
|
||||||
- `data-consistency.test.ts` - Data validation
|
|
||||||
- `components/*.test.tsx` - Component unit tests
|
|
||||||
- `data/*.test.ts` - Data structure validation
|
|
||||||
|
|
||||||
## Environment Variables
|
## Environment Variables
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Frontend (.env.local)
|
# Frontend (.env.local)
|
||||||
NEXT_PUBLIC_API_URL=https://api.filamenteka.rs/api
|
NEXT_PUBLIC_API_URL=https://api.filamenteka.rs/api
|
||||||
|
NEXT_PUBLIC_MATOMO_URL=https://analytics.demirix.dev
|
||||||
|
NEXT_PUBLIC_MATOMO_SITE_ID=7
|
||||||
|
|
||||||
# API Server (.env in /api directory)
|
# API Server (.env in /api)
|
||||||
DATABASE_URL=postgresql://filamenteka_admin:PASSWORD@filamenteka.ci7fsdlbzmag.eu-central-1.rds.amazonaws.com:5432/filamenteka
|
DATABASE_URL=postgresql://filamenteka_admin:PASSWORD@filamenteka.ci7fsdlbzmag.eu-central-1.rds.amazonaws.com:5432/filamenteka
|
||||||
JWT_SECRET=...
|
JWT_SECRET=...
|
||||||
ADMIN_PASSWORD=...
|
ADMIN_PASSWORD=...
|
||||||
@@ -206,75 +123,10 @@ NODE_ENV=production
|
|||||||
PORT=80
|
PORT=80
|
||||||
```
|
```
|
||||||
|
|
||||||
## Security Considerations
|
## Pre-commit Hooks (Husky)
|
||||||
|
|
||||||
- **Authentication**: JWT tokens with 24h expiry (hardcoded admin user for now)
|
`scripts/pre-commit.sh` runs automatically and blocks commits that fail:
|
||||||
- **Password**: Stored in environment variable ADMIN_PASSWORD (bcrypt ready for multi-user)
|
1. Author mention check (blocks attribution)
|
||||||
- **SQL Injection**: Prevented via parameterized queries in all database operations
|
|
||||||
- **Credential Leak Detection**: Pre-commit hook runs `scripts/security/security-check.js`
|
|
||||||
- **CORS**: Currently allows all origins (origin: true) - consider hardening for production
|
|
||||||
- **Auth Interceptors**: Automatic 401/403 handling with redirect to login
|
|
||||||
- **Pre-commit Checks**: Husky runs `scripts/pre-commit.sh` which executes:
|
|
||||||
1. Author mention check (blocks commits with attribution)
|
|
||||||
2. Security check (credential leaks)
|
2. Security check (credential leaks)
|
||||||
3. Build test (ensures code compiles)
|
3. Build test (ensures compilation)
|
||||||
4. Unit tests (Jest with --passWithNoTests)
|
4. Unit tests (`jest --passWithNoTests`)
|
||||||
|
|
||||||
## Development Workflows
|
|
||||||
|
|
||||||
### Adding New Colors
|
|
||||||
1. Add color to database via admin panel (`/upadaj/colors`) OR via migration
|
|
||||||
2. Update frontend color mappings in `src/data/bambuLabColors.ts`:
|
|
||||||
```typescript
|
|
||||||
'Color Name': { hex: '#HEXCODE' } // Solid color
|
|
||||||
'Gradient Name': { hex: ['#HEX1', '#HEX2'], isGradient: true } // Gradient
|
|
||||||
```
|
|
||||||
3. Color names must match exactly between database and filament.boja
|
|
||||||
|
|
||||||
### Database Migrations
|
|
||||||
When modifying the database:
|
|
||||||
1. Create migration file in `/database/migrations/` with sequential numbering (e.g., `019_add_new_feature.sql`)
|
|
||||||
2. Test locally first with `npm run migrate`
|
|
||||||
3. Run migration on production:
|
|
||||||
- Use `scripts/update-db-via-aws.sh` for remote execution via EC2
|
|
||||||
- Or SSH to EC2 and run migration directly
|
|
||||||
4. Update corresponding TypeScript types in `/src/types/`
|
|
||||||
|
|
||||||
Important database constraints:
|
|
||||||
- `filaments.boja` has foreign key to `colors.name` (ON UPDATE CASCADE)
|
|
||||||
- `filaments.kolicina` has check constraint: `kolicina = refill + spulna`
|
|
||||||
- Always update `colors` table first before adding filaments with new colors
|
|
||||||
|
|
||||||
### Deployment Workflow (Gitea Actions CI/CD)
|
|
||||||
Pushing to `main` triggers `.gitea/workflows/deploy.yml` which auto-detects what changed:
|
|
||||||
- **Frontend changes**: Runs security check, tests, builds Next.js, deploys to S3 with cache headers, invalidates CloudFront
|
|
||||||
- **API changes**: Sends SSM command to EC2 to download `server.js` from Gitea and restart the service
|
|
||||||
- **Both**: If a push touches frontend and API files, both deploy steps run
|
|
||||||
|
|
||||||
Manual deployment is still available:
|
|
||||||
1. Frontend: `./scripts/deploy-frontend.sh`
|
|
||||||
2. API: `./scripts/deploy-api-update.sh`
|
|
||||||
3. Verify API: `curl https://api.filamenteka.rs/` should return `{"status":"ok"}`
|
|
||||||
|
|
||||||
## Infrastructure
|
|
||||||
|
|
||||||
### Terraform (IaC)
|
|
||||||
Infrastructure as Code in `/terraform/`:
|
|
||||||
- **VPC**: `vpc.tf` - Network setup with subnets and routing
|
|
||||||
- **EC2**: `ec2-api.tf` - API server instance (i-03956ecf32292d7d9)
|
|
||||||
- **RDS**: `rds.tf` - PostgreSQL database
|
|
||||||
- **ALB**: `alb.tf` - Application Load Balancer
|
|
||||||
- **ECR**: `ecr.tf` - Docker image registry
|
|
||||||
- **CloudFront**: `cloudfront-frontend.tf` - Frontend CDN distribution
|
|
||||||
- **Cloudflare**: `cloudflare-api.tf` - DNS integration for api.filamenteka.rs
|
|
||||||
- **Configuration**: `variables.tf`, `outputs.tf`, `main.tf`
|
|
||||||
|
|
||||||
### Current Stack
|
|
||||||
- **Frontend**: AWS CloudFront + S3 (static Next.js export)
|
|
||||||
- **API**: EC2 instance running Node.js/Express with systemd service
|
|
||||||
- **Database**: AWS RDS PostgreSQL (eu-central-1)
|
|
||||||
- **DNS**: Cloudflare for api.filamenteka.rs
|
|
||||||
- **CI/CD**: Gitea Actions (`.gitea/workflows/deploy.yml`)
|
|
||||||
- **Deployment**: CloudFront + S3 for frontend, SSM for API updates
|
|
||||||
- **Repository**: `git.demirix.dev/dax/Filamenteka`
|
|
||||||
- **CDN**: CloudFront PriceClass_100 (US, Canada, Europe)
|
|
||||||
|
|||||||
Reference in New Issue
Block a user