Streamline CLAUDE.md: remove redundancy, fix inaccuracies
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:
DaX
2026-02-16 02:16:37 +01:00
parent bd27f7a9e4
commit 6dda083ee9

298
CLAUDE.md
View File

@@ -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)