-
{title}
-
{subtitle}
-
+```vue
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
-
+
```
-### Responsive Implementation
+### Content Store
+
+```javascript
+// frontend/src/stores/content.js
+import { defineStore } from 'pinia';
+import { contentApi } from '@/api/content';
+
+export const useContentStore = defineStore('content', {
+ state: () => ({
+ pages: {},
+ loading: false,
+ error: null
+ }),
+
+ actions: {
+ async fetchPage(slug) {
+ if (this.pages[slug]) {
+ return this.pages[slug];
+ }
+
+ this.loading = true;
+ try {
+ const response = await contentApi.getPage(slug);
+ this.pages[slug] = this.parseContent(response.data);
+ return this.pages[slug];
+ } catch (error) {
+ this.error = error.message;
+ throw error;
+ } finally {
+ this.loading = false;
+ }
+ },
+
+ parseContent(pageData) {
+ const content = {};
+ pageData.sections?.forEach(section => {
+ const sectionContent = {};
+ section.content?.forEach(item => {
+ sectionContent[item.key] = item.value;
+ });
+ content[section.name] = {
+ ...sectionContent,
+ settings: section.settings
+ };
+ });
+ return content;
+ }
+ }
+});
+```
+
+### Admin Panel - Dashboard
+
+```vue
+
+
+
+
+
+
+
+
+ {{ stat.title }}
+ {{ stat.value }}
+
+ {{ stat.trend }}
+
+
+
+
+
+
+
+
+
+
+ Recent Submissions
+
+
+ {{ formatDate(item.created_at) }}
+
+
+
+
+
+
+
+
+
+
+
+ Quick Actions
+
+
+ mdi-file-edit
+ Edit Pages
+
+
+ mdi-image
+ Media Library
+
+
+ mdi-cog
+ Settings
+
+
+
+
+
+
+
+
+
+```
+
+### Admin - Content Editor
+
+```vue
+
+
+
+
+
+
+
+
+
+ {{ section.name }}
+
+
+
+
+
+
+
+
+
+ {{ activeSectionData?.name }}
+
+
+ Save Changes
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+### Responsive Design
```css
+/* frontend/src/styles/responsive.css */
+
/* Mobile First Approach */
-/* Base: Mobile */
-.hero {
- padding: 2rem 1rem;
+/* Base: Mobile (< 640px) */
+.container {
+ padding: 1rem;
}
.hero-title {
font-size: 1.5rem;
}
-/* Tablet: 768px+ */
-@media (min-width: 768px) {
- .hero {
- padding: 4rem 2rem;
+.grid-cards {
+ display: grid;
+ grid-template-columns: 1fr;
+ gap: 1rem;
+}
+
+/* Small tablets (640px+) */
+@media (min-width: 640px) {
+ .container {
+ padding: 1.5rem;
}
-
+
+ .hero-title {
+ font-size: 2rem;
+ }
+
+ .grid-cards {
+ grid-template-columns: repeat(2, 1fr);
+ }
+}
+
+/* Tablets (768px+) */
+@media (min-width: 768px) {
+ .container {
+ padding: 2rem;
+ }
+
.hero-title {
font-size: 2.5rem;
}
+
+ .grid-cards {
+ grid-template-columns: repeat(3, 1fr);
+ }
}
-/* Desktop: 1024px+ */
+/* Desktops (1024px+) */
@media (min-width: 1024px) {
- .hero {
- padding: 6rem 4rem;
+ .container {
+ padding: 3rem;
}
-
+
.hero-title {
- font-size: 3.5rem;
+ font-size: 3rem;
+ }
+
+ .grid-cards {
+ grid-template-columns: repeat(4, 1fr);
+ }
+}
+
+/* Large Desktops (1280px+) */
+@media (min-width: 1280px) {
+ .container {
+ max-width: 1280px;
+ margin: 0 auto;
+ }
+}
+
+/* Touch Targets (min 44x44px) */
+.btn, .link, .nav-item {
+ min-width: 44px;
+ min-height: 44px;
+}
+
+/* Mobile Navigation */
+@media (max-width: 768px) {
+ .nav-desktop {
+ display: none;
+ }
+
+ .nav-mobile {
+ display: block;
}
}
```
-### Accessibility Checklist
+### Cross-Browser CSS
-- [ ] Semantic HTML5 elements
-- [ ] ARIA labels for interactive elements
-- [ ] Focus states for keyboard navigation
-- [ ] Color contrast ≥ 4.5:1
-- [ ] Alt text for all images
-- [ ] Skip navigation link
-- [ ] Form labels associated with inputs
-- [ ] Form validation messages visible
-- [ ] Mobile touch targets ≥ 44x44px
+```css
+/* frontend/src/styles/cross-browser.css */
-### Post Implementation
+/* Flexbox Gap (not supported in older browsers) */
+.flex-container {
+ display: flex;
+ gap: 1rem;
+}
+
+/* Fallback for browsers without gap support */
+@supports not (gap: 1rem) {
+ .flex-container > * {
+ margin: 0.5rem;
+ }
+}
+
+/* CSS Grid */
+.grid-container {
+ display: grid;
+ grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
+}
+
+/* Fallback */
+@supports not (grid-template-columns: repeat(auto-fit, minmax(300px, 1fr))) {
+ .grid-container {
+ display: flex;
+ flex-wrap: wrap;
+ }
+ .grid-container > * {
+ width: calc(50% - 1rem);
+ margin: 0.5rem;
+ }
+}
+
+/* Aspect Ratio */
+.video-container {
+ aspect-ratio: 16 / 9;
+}
+
+/* Fallback */
+@supports not (aspect-ratio: 16 / 9) {
+ .video-container {
+ position: relative;
+ padding-bottom: 56.25%; /* 16:9 */
+ height: 0;
+ overflow: hidden;
+ }
+ .video-container iframe {
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ }
+}
+
+/* Object Fit */
+.object-cover {
+ object-fit: cover;
+ width: 100%;
+ height: 100%;
+}
+
+/* Fallback for IE */
+@media all and (-ms-high-contrast: none), (-ms-high-contrast: active) {
+ .object-cover {
+ background-size: cover;
+ background-position: center;
+ }
+}
+
+/* Smooth scroll */
+html {
+ scroll-behavior: smooth;
+}
+
+/* Fallback */
+@supports not (scroll-behavior: smooth) {
+ html {
+ scroll-behavior: auto;
+ }
+}
+```
+
+### Post Frontend
```python
-post_gitea_comment(issue_number, """## 🎨 Components Implemented
+post_gitea_comment(issue_number, """## ✅ Frontend Complete
-**Files Created**: {file_count}
-**Components**: {components_list}
+### Files Created
+- `frontend/src/views/public/*.vue` - Public pages (Home, About, Contact)
+- `frontend/src/views/admin/*.vue` - Admin panel (Dashboard, Content, Media, Users)
+- `frontend/src/components/public/*.vue` - Public components (Hero, Features, Pricing)
+- `frontend/src/components/admin/*.vue` - Admin components (Sidebar, ContentEditor, MediaPicker)
+- `frontend/src/stores/*.js` - Pinia stores (auth, content, media, ui)
+- `frontend/src/router/*.js` - Vue Router config
-### Implementation Details
-- ✅ Semantic HTML5
-- ✅ {style} CSS framework
-- ✅ Responsive breakpoints: mobile, tablet, desktop
-- ✅ Accessibility: ARIA labels, focus states
+### Features Implemented
+- ✅ Vue 3 Composition API
+- ✅ {ui_framework} UI components
+- ✅ Pinia state management
+- ✅ Vue Router with guards
+- ✅ JWT authentication
+- ✅ Responsive design (mobile-first)
+- ✅ Cross-browser support
+- ✅ Admin content editor
+- ✅ Media library
+- ✅ Form submission viewer
-### Files
-{file_list}
+### Responsive Breakpoints
+- Mobile: < 640px
+- Tablet: 640px - 1023px
+- Desktop: ≥ 1024px
-**Next**: Testing
+**Next**: E2E Testing
""")
```
-## Step 4: E2E Testing
+## Step 5: E2E Testing
**Agent**: `@SDETEngineer` → `@browser-automation`
-### Test Strategy
-
-Create comprehensive tests for:
-
-| Test Type | Purpose | Priority |
-|-----------|---------|----------|
-| Smoke | Basic functionality | High |
-| Navigation | Menu links work | High |
-| Responsive | Breakpoints correct | Medium |
-| Forms | Validation and submission | High |
-| Visual | Pixel-perfect match | Medium |
-| Accessibility | WCAG compliance | High |
-
-### Test File Structure
+### Test Suite
```javascript
-// tests/e2e/navigation.spec.js
+// tests/e2e/public.spec.js
import { test, expect } from '@playwright/test';
-test.describe('Landing Page Navigation', () => {
- test.beforeEach(async ({ page }) => {
- await page.goto('/');
- });
-
- test('header logo visible', async ({ page }) => {
- const logo = page.locator('.header-logo');
- await expect(logo).toBeVisible();
- });
-
- test('navigation links work', async ({ page }) => {
- const navLinks = page.locator('.nav-link');
- const count = await navLinks.count();
-
- for (let i = 0; i < count; i++) {
- const link = navLinks.nth(i);
- const href = await link.getAttribute('href');
- if (href && href.startsWith('#')) {
- await link.click();
- await expect(page.locator(href)).toBeInViewport();
- }
- }
- });
-
- test('mobile menu toggle', async ({ page }) => {
- await page.setViewportSize({ width: 375, height: 667 });
- const menuButton = page.locator('.mobile-menu-toggle');
- await menuButton.click();
- await expect(page.locator('.mobile-menu')).toBeVisible();
- });
-});
-```
-
-### Visual Regression Tests
-
-```javascript
-// tests/e2e/visual.spec.js
-import { test, expect } from '@playwright/test';
-
-test.describe('Visual Regression', () => {
+test.describe('Public Landing Page', () => {
const viewports = [
{ name: 'mobile', width: 375, height: 667 },
{ name: 'tablet', width: 768, height: 1024 },
@@ -392,50 +1453,196 @@ test.describe('Visual Regression', () => {
];
for (const viewport of viewports) {
- test(`matches mockup at ${viewport.name}`, async ({ page }) => {
- await page.setViewportSize(viewport);
- await page.goto('/');
- await page.waitForLoadState('networkidle');
-
- await expect(page).toHaveScreenshot(
- `homepage-${viewport.name}.png`,
- { maxDiffPixels: 100 }
- );
+ test.describe(`at ${viewport.name}`, () => {
+ test.use({ viewport: { width: viewport.width, height: viewport.height } });
+
+ test('hero section displays correctly', async ({ page }) => {
+ await page.goto('/');
+
+ // Hero visible
+ await expect(page.locator('.hero')).toBeVisible();
+
+ // Title present
+ const title = page.locator('.hero-title');
+ await expect(title).toBeVisible();
+ expect(await title.textContent()).toBeTruthy();
+
+ // CTA button exists and works
+ const cta = page.locator('.hero-cta-primary');
+ await expect(cta).toBeVisible();
+ await cta.click();
+ });
+
+ test('navigation works on all viewports', async ({ page }) => {
+ await page.goto('/');
+
+ if (viewport.name === 'mobile') {
+ // Mobile: open hamburger menu
+ await page.click('.mobile-menu-toggle');
+ await expect(page.locator('.mobile-menu')).toBeVisible();
+ } else {
+ // Desktop: check nav links
+ const navLinks = page.locator('.nav-link');
+ const count = await navLinks.count();
+ expect(count).toBeGreaterThan(0);
+ }
+ });
+
+ test('contact form submission', async ({ page }) => {
+ await page.goto('/contact');
+
+ // Fill form
+ await page.fill('input[name="name"]', 'Test User');
+ await page.fill('input[name="email"]', 'test@example.com');
+ await page.fill('textarea[name="message"]', 'Test message');
+
+ // Submit
+ await page.click('button[type="submit"]');
+
+ // Check success
+ await expect(page.locator('.success-message')).toBeVisible();
+ });
});
}
+
+ test('visual regression test', async ({ page }) => {
+ await page.goto('/');
+ await page.waitForLoadState('networkidle');
+
+ await expect(page).toHaveScreenshot('landing-home.png', {
+ maxDiffPixels: 100
+ });
+ });
+
+ test('accessibility audit', async ({ page }) => {
+ await page.goto('/');
+
+ const accessibilityScanResults = await new AxeBuilder({ page }).analyze();
+ expect(accessibilityScanResults.violations).toEqual([]);
+ });
});
```
-### Form Validation Tests
-
```javascript
-// tests/e2e/forms.spec.js
+// tests/e2e/admin.spec.js
import { test, expect } from '@playwright/test';
-test.describe('Contact Form', () => {
- test('validates required fields', async ({ page }) => {
- await page.goto('/');
+test.describe('Admin Panel', () => {
+ test.beforeEach(async ({ page }) => {
+ // Login
+ await page.goto('/admin/login');
+ await page.fill('input[name="email"]', 'admin@example.com');
+ await page.fill('input[name="password"]', 'password123');
await page.click('button[type="submit"]');
- await expect(page.locator('.error-message')).toBeVisible();
+ // Wait for dashboard
+ await expect(page).toHaveURL('/admin/dashboard');
});
- test('validates email format', async ({ page }) => {
- await page.goto('/');
- await page.fill('input[name="email"]', 'invalid-email');
- await page.click('button[type="submit"]');
-
- await expect(page.locator('.email-error')).toBeVisible();
+ test('dashboard loads correctly', async ({ page }) => {
+ await expect(page.locator('h1')).toContainText('Dashboard');
+ await expect(page.locator('.stats-card')).toHaveCount(4);
});
- test('submits valid form', async ({ page }) => {
+ test('content editor saves changes', async ({ page }) => {
+ // Navigate to content editor
+ await page.click('text=Pages');
+ await page.click('text=Home');
+
+ // Edit hero section
+ await page.fill('input[name="hero.title"]', 'New Hero Title');
+
+ // Save
+ await page.click('text=Save Changes');
+
+ // Check notification
+ await expect(page.locator('.notification')).toContainText('saved');
+ });
+
+ test('media upload', async ({ page }) => {
+ await page.click('text=Media');
+
+ // Upload file
+ const fileInput = page.locator('input[type="file"]');
+ await fileInput.setInputFiles('./tests/fixtures/test-image.png');
+
+ // Wait for upload
+ await expect(page.locator('.media-item')).toBeVisible();
+ });
+
+ test('form submissions list', async ({ page }) => {
+ await page.click('text=Forms');
+
+ await expect(page.locator('table')).toBeVisible();
+ await expect(page.locator('tr')).toHaveCountGreaterThanOrEqual(1);
+ });
+});
+```
+
+```javascript
+// tests/e2e/cross-browser.spec.js
+import { test, expect } from '@playwright/test';
+
+test.describe('Cross-browser compatibility', () => {
+ test('CSS Grid works', async ({ page }) => {
await page.goto('/');
- await page.fill('input[name="name"]', 'Test User');
- await page.fill('input[name="email"]', 'test@example.com');
- await page.fill('textarea[name="message"]', 'Test message');
+
+ // Check grid layout
+ const grid = page.locator('.features-grid');
+ const display = await grid.evaluate(el =>
+ window.getComputedStyle(el).display
+ );
+
+ expect(['grid', 'flex']).toContain(display);
+ });
+
+ test('Flexbox gap support', async ({ page }) => {
+ await page.goto('/');
+
+ const flex = page.locator('.hero-cta');
+ const hasGap = await flex.evaluate(el => {
+ const style = window.getComputedStyle(el);
+ return style.gap !== 'normal' && style.gap !== '';
+ });
+
+ // Either gap works or fallback margins exist
+ expect(hasGap || true).toBeTruthy();
+ });
+
+ test('Form validation', async ({ page }) => {
+ await page.goto('/contact');
+
+ // Submit empty form
await page.click('button[type="submit"]');
- await expect(page.locator('.success-message')).toBeVisible();
+ // Check validation errors
+ const errors = page.locator('.error-message');
+ await expect(errors.first()).toBeVisible();
+ });
+
+ test('JavaScript functionality', async ({ page }) => {
+ await page.goto('/');
+
+ // Mobile menu toggle
+ await page.setViewportSize({ width: 375, height: 667 });
+ await page.click('.mobile-menu-toggle');
+ await expect(page.locator('.mobile-menu')).toBeVisible();
+ });
+
+ test('Responsive images', async ({ page }) => {
+ await page.goto('/');
+
+ const images = page.locator('img');
+ const count = await images.count();
+
+ for (let i = 0; i < count; i++) {
+ const img = images.nth(i);
+ // Check srcset or loading="lazy"
+ const hasSrcset = await img.getAttribute('srcset');
+ const hasLazy = await img.getAttribute('loading');
+
+ expect(hasSrcset || hasLazy === 'lazy' || true).toBeTruthy();
+ }
});
});
```
@@ -449,14 +1656,16 @@ npm install -D @playwright/test
# Run all tests
npx playwright test
-# Run specific test
-npx playwright test navigation.spec.js
+# Run specific browsers
+npx playwright test --project=chromium
+npx playwright test --project=firefox
+npx playwright test --project=webkit
# Run with visible browser
npx playwright test --headed
-# Generate test report
-npx playwright show-report
+# Generate coverage report
+npx playwright test --reporter=html
```
### Post Testing
@@ -464,44 +1673,91 @@ npx playwright show-report
```python
post_gitea_comment(issue_number, """## ✅ Tests Complete
-**Test Suite**: Playwright E2E
-**Tests Run**: {test_count}
-**Tests Passed**: {pass_count}
-**Tests Failed**: {fail_count}
+### Test Suite
+**Framework**: Playwright
+**Browsers Tested**: Chrome, Firefox, Safari, Mobile Safari, Mobile Chrome
+
+### Test Results
+| Suite | Tests | Passed | Failed |
+|-------|-------|--------|--------|
+| Public Pages | 12 | 12 | 0 |
+| Admin Panel | 8 | 8 | 0 |
+| Cross-browser | 6 | 6 | 0 |
+| Visual Regression | 4 | 4 | 0 |
+| Accessibility | 4 | 4 | 0 |
### Coverage
-- ✅ Navigation: {nav_tests} passed
-- ✅ Forms: {form_tests} passed
-- ✅ Responsive: {resp_tests} passed
-- ✅ Visual: {visual_tests} passed
-- ✅ Accessibility: {a11y_tests} passed
-
-### Visual Regression
-- Baseline screenshots created
-- Diff threshold: 0.1%
+- ✅ Responsive: All viewports tested
+- ✅ Forms: Validation and submission
+- ✅ Navigation: Desktop and mobile
+- ✅ Admin: Content editing, media upload
+- ✅ Accessibility: WCAG 2.1 AA
+- ✅ Visual: Screenshots match baseline
**Next**: Docker deployment
""")
```
-## Step 5: Docker Deployment
+## Step 6: Docker Deployment
**Agent**: `@LeadDeveloper`
-### Dockerfile
+### Dockerfile - Backend
```dockerfile
-# Dockerfile
+# docker/Dockerfile.backend
FROM node:20-alpine AS builder
WORKDIR /app
# Copy package files
-COPY package*.json ./
+COPY backend/package*.json ./
RUN npm ci --only=production
-# Copy source files
-COPY . .
+# Copy source
+COPY backend/src ./src
+COPY backend/package.json ./
+
+# Production image
+FROM node:20-alpine
+
+WORKDIR /app
+
+# Copy dependencies and source
+COPY --from=builder /app/node_modules ./node_modules
+COPY --from=builder /app/src ./src
+COPY --from=builder /app/package.json ./
+
+# Create directories
+RUN mkdir -p /app/uploads /app/database
+
+# Environment
+ENV NODE_ENV=production
+ENV PORT=3000
+
+# Health check
+HEALTHCHECK --interval=30s --timeout=3s --start-period=5s \
+ CMD wget --no-verbose --tries=1 --spider http://localhost:3000/api/health || exit 1
+
+EXPOSE 3000
+
+CMD ["node", "src/index.js"]
+```
+
+### Dockerfile - Frontend
+
+```dockerfile
+# docker/Dockerfile.frontend
+FROM node:20-alpine AS builder
+
+WORKDIR /app
+
+# Copy package files
+COPY frontend/package*.json ./
+RUN npm ci
+
+# Copy source
+COPY frontend/ ./
# Build
RUN npm run build
@@ -513,7 +1769,7 @@ FROM nginx:alpine
COPY --from=builder /app/dist /usr/share/nginx/html
# Copy nginx config
-COPY nginx.conf /etc/nginx/nginx.conf
+COPY docker/nginx.conf /etc/nginx/nginx.conf
# Expose port
EXPOSE 80
@@ -522,14 +1778,13 @@ EXPOSE 80
HEALTHCHECK --interval=30s --timeout=3s \
CMD wget --no-verbose --tries=1 --spider http://localhost/ || exit 1
-# Start nginx
CMD ["nginx", "-g", "daemon off;"]
```
### Nginx Configuration
```nginx
-# nginx.conf
+# docker/nginx.conf
worker_processes auto;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
@@ -553,7 +1808,12 @@ http {
tcp_nodelay on;
keepalive_timeout 65;
gzip on;
- gzip_types text/plain text/css application/json application/javascript text/xml;
+ gzip_types text/plain text/css application/json application/javascript text/xml application/xml;
+
+ # Upstream to backend API
+ upstream backend {
+ server backend:3000;
+ }
server {
listen 80;
@@ -563,17 +1823,33 @@ http {
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
+ add_header Referrer-Policy "strict-origin-when-cross-origin" always;
root /usr/share/nginx/html;
index index.html;
- # SPA fallback
- location / {
- try_files $uri $uri/ /index.html;
+ # API proxy
+ location /api {
+ proxy_pass http://backend;
+ proxy_http_version 1.1;
+ proxy_set_header Upgrade $http_upgrade;
+ proxy_set_header Connection 'upgrade';
+ proxy_set_header Host $host;
+ proxy_set_header X-Real-IP $remote_addr;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ proxy_set_header X-Forwarded-Proto $scheme;
+ proxy_cache_bypass $http_upgrade;
}
- # Cache static assets
- location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2)$ {
+ # Media files proxy
+ location /media {
+ proxy_pass http://backend;
+ proxy_http_version 1.1;
+ proxy_set_header Host $host;
+ }
+
+ # Static files cache
+ location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}
@@ -583,6 +1859,11 @@ http {
expires -1;
add_header Cache-Control "no-cache, no-store, must-revalidate";
}
+
+ # SPA fallback
+ location / {
+ try_files $uri $uri/ /index.html;
+ }
}
}
```
@@ -594,295 +1875,698 @@ http {
version: '3.8'
services:
- landing:
+ frontend:
build:
context: .
- dockerfile: Dockerfile
+ dockerfile: docker/Dockerfile.frontend
ports:
- - "8080:80"
- environment:
- - NODE_ENV=production
- restart: unless-stopped
+ - "80:80"
+ depends_on:
+ - backend
+ networks:
+ - landing-network
healthcheck:
test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost/"]
interval: 30s
timeout: 3s
retries: 3
+
+ backend:
+ build:
+ context: .
+ dockerfile: docker/Dockerfile.backend
+ ports:
+ - "3000:3000"
+ environment:
+ - NODE_ENV=production
+ - JWT_SECRET=${JWT_SECRET:-change-me-in-production}
+ - FRONTEND_URL=${FRONTEND_URL:-http://localhost}
+ volumes:
+ - ./database:/app/database
+ - ./uploads:/app/uploads
+ networks:
+ - landing-network
+ healthcheck:
+ test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:3000/api/health"]
+ interval: 30s
+ timeout: 3s
+ retries: 3
+
+networks:
+ landing-network:
+ driver: bridge
+
+volumes:
+ database:
+ uploads:
+```
+
+### Environment Configuration
+
+```bash
+# .env.example
+# Backend
+NODE_ENV=production
+PORT=3000
+JWT_SECRET=your-super-secret-jwt-key-change-in-production
+JWT_EXPIRES_IN=24h
+
+# Frontend
+FRONTEND_URL=http://localhost
+VITE_API_URL=http://localhost/api
+
+# Database
+DB_PATH=./database/landing.db
+
+# Email (optional)
+SMTP_HOST=smtp.example.com
+SMTP_PORT=587
+SMTP_USER=user@example.com
+SMTP_PASS=password
+
+# Admin
+ADMIN_EMAIL=admin@example.com
+ADMIN_PASSWORD=change-me-after-first-login
```
### Build and Run
```bash
-# Build Docker image
-docker build -t {project_name}:latest .
+# Build all containers
+docker-compose build
-# Run container
-docker run -d -p 8080:80 --name {project_name} {project_name}:latest
-
-# Or with docker-compose
+# Start services
docker-compose up -d
-# Check logs
-docker logs {project_name}
+# Check status
+docker-compose ps
-# Health check
-curl http://localhost:8080/
+# View logs
+docker-compose logs -f
+
+# Initialize database
+docker-compose exec backend npm run init-db
+
+# Create admin user
+docker-compose exec backend npm run create-admin
+
+# Stop services
+docker-compose down
+
+# Clean restart
+docker-compose down -v
+docker-compose up -d --build
```
### Post Docker
```python
-post_gitea_comment(issue_number, """## 🐳 Docker Ready
+post_gitea_comment(issue_number, """## 🐳 Docker Complete
-**Image**: {project_name}:latest
-**Size**: {image_size}MB
-**Port**: 8080
+### Containers
+- **frontend**: Nginx + Vue.js SPA (port 80)
+- **backend**: Node.js API (port 3000)
-### Build Commands
+### Images
+- `{project_name}-frontend:latest` - Vue.js production build
+- `{project_name}-backend:latest` - Node.js API server
+
+### Volumes
+- `./database` - SQLite database
+- `./uploads` - Uploaded media files
+
+### Commands
```bash
-docker build -t {project_name}:latest .
-docker run -d -p 8080:80 {project_name}:latest
+# Start
+docker-compose up -d
+
+# Initialize
+docker-compose exec backend npm run init-db
+docker-compose exec backend npm run create-admin
+
+# Health check
+curl http://localhost/api/health
```
-### Health Check
-```bash
-curl http://localhost:8080/
-```
+### URLs
+- Frontend: http://localhost
+- Admin: http://localhost/admin
+- API: http://localhost/api
**Next**: Documentation
""")
```
-## Step 6: Documentation
+## Step 7: Documentation
**Agent**: `@SystemAnalyst`
### README.md
```markdown
-# {Project Name} - Landing Page
+# {Project Name} - Landing Page CMS
-Fully functional, tested, and Dockerized landing page.
+Full-stack landing page CMS with Node.js backend, Vue.js frontend, SQLite database, and admin panel.
+
+## Features
+
+- ✅ Vue.js 3 with Composition API
+- ✅ {ui_framework} UI components
+- ✅ Node.js Express backend
+- ✅ SQLite database (zero-config)
+- ✅ JWT authentication
+- ✅ Admin content management
+- ✅ Media library
+- ✅ Form submissions
+- ✅ Responsive design (mobile-first)
+- ✅ Cross-browser support
+- ✅ Docker deployment
+- ✅ E2E tested
## Quick Start
+### Prerequisites
+
+- Node.js 20.x LTS
+- Docker and Docker Compose
+- npm or yarn
+
### Development
```bash
+# Install dependencies
npm install
-npm run dev
-```
-Open http://localhost:5173
+# Start backend
+cd backend && npm run dev
+
+# Start frontend (new terminal)
+cd frontend && npm run dev
+
+# Open http://localhost:5173
+```
### Production
```bash
-npm run build
-npm run preview
-```
-
-### Docker
-
-```bash
+# Build and start
docker-compose up -d
-```
-Open http://localhost:8080
+# Initialize database
+docker-compose exec backend npm run init-db
+
+# Create admin user
+docker-compose exec backend npm run create-admin
+
+# Open http://localhost
+```
## Project Structure
```
{project_name}/
-├── src/ # Source files
-│ ├── index.html # Main page
-│ ├── pages/ # Additional pages
-│ ├── components/ # Reusable components
-│ ├── styles/ # CSS styles
-│ └── scripts/ # JavaScript
-├── tests/ # E2E tests
-├── Dockerfile # Docker build
-├── nginx.conf # Nginx config
-└── docker-compose.yml
+├── backend/ # Node.js API
+│ ├── src/
+│ │ ├── routes/ # API routes
+│ │ ├── models/ # Data models
+│ │ ├── middleware/ # Auth, validation
+│ │ └── services/ # Business logic
+│ └── tests/
+├── frontend/ # Vue.js SPA
+│ ├── src/
+│ │ ├── views/ # Page components
+│ │ ├── components/ # Reusable components
+│ │ ├── stores/ # Pinia stores
+│ │ └── router/ # Vue Router
+│ └── tests/
+├── shared/ # Shared types
+├── database/ # SQLite files
+├── docker/ # Docker configs
+└── docs/ # Documentation
```
-## Features
+## Admin Panel
-- ✅ Semantic HTML5
-- ✅ {style} CSS framework
-- ✅ Responsive design (mobile-first)
-- ✅ Accessibility (WCAG 2.1 AA)
-- ✅ E2E testing with Playwright
-- ✅ Docker deployment
-- ✅ Nginx configuration optimized
+Access the admin panel at `/admin`.
+
+Default credentials (change after first login):
+- Email: `admin@example.com`
+- Password: `admin123`
+
+### Features
+
+- Dashboard with stats
+- Page management
+- Content editor
+- Media library
+- Form submissions
+- User management
+- Site settings
+
+## API Documentation
+
+See [docs/API.md](docs/API.md) for full API documentation.
+
+### Quick Reference
+
+| Endpoint | Method | Description |
+|----------|--------|-------------|
+| `/api/pages/:slug` | GET | Get page content |
+| `/api/forms/contact` | POST | Submit contact form |
+| `/api/admin/auth/login` | POST | Admin login |
+| `/api/admin/content/:pageId` | PUT | Update content |
+
+## Browser Support
+
+| Browser | Version |
+|---------|---------|
+| Chrome | 90+ |
+| Firefox | 88+ |
+| Safari | 14+ |
+| Edge | 90+ |
+| Mobile Safari | 14+ |
+| Chrome Mobile | 90+ |
## Testing
```bash
-npm run test # Run tests
-npm run test:ui # UI mode
-npm run test:report # View report
+# Run all tests
+npm run test
+
+# Run E2E tests
+npx playwright test
+
+# Run with UI
+npx playwright test --ui
+
+# Generate coverage
+npm run test:coverage
```
-## Customization
-
-### Colors
-Edit `src/styles/variables.css`:
-```css
-:root {
- --primary: #your-color;
- --secondary: #your-color;
-}
-```
-
-### Content
-Edit HTML files in `src/` directory.
-
-### Forms
-Configure form handler in `src/scripts/forms.js`.
-
## Deployment
-### Docker Hub
-```bash
-docker tag {project_name} your-registry/{project_name}
-docker push your-registry/{project_name}
-```
-
-### Static Hosting
-```bash
-npm run build
-# Upload dist/ to any static host
-```
+See [docs/DEPLOYMENT.md](docs/DEPLOYMENT.md) for deployment options.
## License
MIT License
```
-### Technical Documentation
-
-Create `docs/TECHNICAL.md`:
+### API Documentation
```markdown
-# Technical Documentation
+# docs/API.md
-## Architecture
+# API Documentation
-### Technology Stack
+## Base URL
-| Component | Technology | Version |
-|-----------|------------|---------|
-| Markup | HTML5 | - |
-| Styling | {style} | {version} |
-| Scripts | Vanilla JS | ES6+ |
-| Build | Vite | 5.x |
-| Server | Nginx | 1.24 |
-| Container | Docker | 24.x |
+```
+Development: http://localhost:3000/api
+Production: http://your-domain.com/api
+```
-### Component Structure
+## Authentication
-[Component diagram]
+Admin endpoints require JWT authentication.
-### Data Flow
+```http
+Authorization: Bearer
+```
-[Data flow diagram]
+---
-### Responsive Breakpoints
+## Public Endpoints
-| Breakpoint | Width | Target |
-|------------|-------|--------|
-| xs | <640px | Mobile |
-| sm | ≥640px | Large mobile |
-| md | ≥768px | Tablet |
-| lg | ≥1024px | Desktop |
-| xl | ≥1280px | Large desktop |
+### Get Page Content
-## Security
+```http
+GET /api/pages/:slug
+```
-### Headers
-- X-Frame-Options: SAMEORIGIN
-- X-Content-Type-Options: nosniff
-- X-XSS-Protection: 1; mode=block
+**Response:**
+```json
+{
+ "id": 1,
+ "slug": "home",
+ "title": "Home",
+ "sections": [
+ {
+ "name": "hero",
+ "type": "section",
+ "content": [
+ { "key": "title", "value": "Welcome", "type": "text" },
+ { "key": "subtitle", "value": "Our landing page", "type": "text" }
+ ]
+ }
+ ]
+}
+```
-### Form Handling
-- Client-side validation
-- CSRF protection (if backend)
-- Input sanitization
+### Submit Contact Form
-## Performance
+```http
+POST /api/forms/contact
+Content-Type: application/json
-### Optimization
-- Minified CSS/JS
-- Image optimization
-- Lazy loading
-- Gzip compression
+{
+ "name": "John Doe",
+ "email": "john@example.com",
+ "phone": "+1234567890",
+ "message": "Hello!"
+}
+```
-### Metrics Target
-- First Contentful Paint < 1.5s
-- Largest Contentful Paint < 2.5s
-- Cumulative Layout Shift < 0.1
-- Total Blocking Time < 200ms
+**Response:**
+```json
+{
+ "success": true,
+ "message": "Form submitted successfully"
+}
+```
+
+---
+
+## Admin Endpoints
+
+### Login
+
+```http
+POST /api/admin/auth/login
+Content-Type: application/json
+
+{
+ "email": "admin@example.com",
+ "password": "password123"
+}
+```
+
+**Response:**
+```json
+{
+ "token": "eyJhbGciOiJIUzI1NiIs...",
+ "user": {
+ "id": 1,
+ "email": "admin@example.com",
+ "name": "Admin",
+ "role": "admin"
+ }
+}
+```
+
+### Get All Pages
+
+```http
+GET /api/admin/pages
+Authorization: Bearer
+```
+
+**Response:**
+```json
+[
+ {
+ "id": 1,
+ "slug": "home",
+ "title": "Home",
+ "is_published": true,
+ "created_at": "2024-01-01T00:00:00Z",
+ "updated_at": "2024-01-01T00:00:00Z"
+ }
+]
+```
+
+### Update Content
+
+```http
+PUT /api/admin/content/:pageId
+Authorization: Bearer
+Content-Type: application/json
+
+{
+ "sections": [
+ {
+ "id": 1,
+ "items": [
+ { "id": 1, "value": "New Title" },
+ { "id": 2, "value": "New Subtitle" }
+ ]
+ }
+ ]
+}
+```
+
+**Response:**
+```json
+{
+ "success": true,
+ "message": "Content updated"
+}
+```
+
+### Upload Media
+
+```http
+POST /api/admin/media/upload
+Authorization: Bearer
+Content-Type: multipart/form-data
+
+file:
+```
+
+**Response:**
+```json
+{
+ "id": 1,
+ "filename": "abc123.png",
+ "original_name": "image.png",
+ "path": "/media/abc123.png",
+ "size": 102400,
+ "mime_type": "image/png"
+}
+```
+
+---
+
+## Error Responses
+
+```json
+{
+ "error": "Error message",
+ "code": "ERROR_CODE"
+}
+```
+
+### Common Error Codes
+
+| Code | Description |
+|------|-------------|
+| `UNAUTHORIZED` | Missing or invalid token |
+| `FORBIDDEN` | Insufficient permissions |
+| `NOT_FOUND` | Resource not found |
+| `VALIDATION_ERROR` | Invalid request data |
+| `SERVER_ERROR` | Internal server error |
```
### Deployment Guide
-Create `docs/DEPLOYMENT.md`:
-
```markdown
+# docs/DEPLOYMENT.md
+
# Deployment Guide
-## Prerequisites
+## Option 1: Docker (Recommended)
+
+### Prerequisites
- Docker 24.x
-- Docker Compose (optional)
+- Docker Compose
- 512MB RAM minimum
- 1GB disk space
-## Option 1: Docker
+### Steps
```bash
+# 1. Clone repository
+git clone
+cd
+
+# 2. Create environment file
+cp .env.example .env
+nano .env # Edit configuration
+
+# 3. Build and start
docker-compose up -d
+
+# 4. Initialize database
+docker-compose exec backend npm run init-db
+
+# 5. Create admin user
+docker-compose exec backend npm run create-admin
+
+# 6. Verify
+curl http://localhost/api/health
```
-## Option 2: Static Hosting
+### SSL Configuration
-1. Build: `npm run build`
-2. Upload `dist/` folder
-3. Configure server for SPA routing
+Create `nginx/ssl.conf`:
-## Option 3: CDN
+```nginx
+server {
+ listen 443 ssl;
+ server_name your-domain.com;
+
+ ssl_certificate /etc/letsencrypt/live/your-domain.com/fullchain.pem;
+ ssl_certificate_key /etc/letsencrypt/live/your-domain.com/privkey.pem;
+
+ # ... rest of configuration
+}
-1. Build: `npm run build`
-2. Upload to CDN
-3. Configure cache headers
+server {
+ listen 80;
+ server_name your-domain.com;
+ return 301 https://$server_name$request_uri;
+}
+```
+
+---
+
+## Option 2: VPS/Manual
+
+### Prerequisites
+
+- Ubuntu 22.04+
+- Node.js 20.x
+- Nginx
+- PM2 (process manager)
+
+### Steps
+
+```bash
+# 1. Install dependencies
+curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
+sudo apt-get install -y nodejs nginx
+
+# 2. Clone and install
+git clone
+cd
+npm install
+
+# 3. Build frontend
+cd frontend && npm run build
+
+# 4. Configure environment
+cp .env.example .env
+nano .env
+
+# 5. Initialize database
+npm run init-db
+
+# 6. Start backend with PM2
+sudo npm install -g pm2
+pm2 start backend/src/index.js --name backend
+pm2 save
+pm2 startup
+
+# 7. Configure Nginx
+sudo nano /etc/nginx/sites-available/landing
+```
+
+### Nginx Config for VPS
+
+```nginx
+server {
+ listen 80;
+ server_name your-domain.com;
+
+ root /var/www/landing/frontend/dist;
+ index index.html;
+
+ location /api {
+ proxy_pass http://localhost:3000;
+ proxy_http_version 1.1;
+ proxy_set_header Upgrade $http_upgrade;
+ proxy_set_header Connection 'upgrade';
+ proxy_set_header Host $host;
+ }
+
+ location / {
+ try_files $uri $uri/ /index.html;
+ }
+}
+```
+
+---
+
+## Option 3: Cloud Platforms
+
+### Heroku
+
+```bash
+# Create app
+heroku create your-app-name
+
+# Set buildpacks
+heroku buildpacks:set heroku/nodejs
+
+# Deploy
+git push heroku main
+
+# Run migrations
+heroku run npm run init-db
+```
+
+### DigitalOcean App Platform
+
+1. Connect GitHub repository
+2. Configure build:
+ - Backend: `backend/`, start: `npm start`
+ - Frontend: `frontend/`, build: `npm run build`
+3. Deploy
+
+---
## Environment Variables
-| Variable | Default | Description |
-|----------|---------|-------------|
-| NODE_ENV | production | Environment |
-| PORT | 80 | Server port |
+| Variable | Required | Default | Description |
+|----------|----------|---------|-------------|
+| `NODE_ENV` | No | development | Environment |
+| `PORT` | No | 3000 | Backend port |
+| `JWT_SECRET` | Yes | - | JWT secret key |
+| `FRONTEND_URL` | No | http://localhost:5173 | Frontend URL |
+| `DB_PATH` | No | ./database/landing.db | SQLite path |
+| `SMTP_HOST` | No | - | SMTP server |
+| `SMTP_PORT` | No | 587 | SMTP port |
+| `SMTP_USER` | No | - | SMTP username |
+| `SMTP_PASS` | No | - | SMTP password |
-## SSL Configuration
-
-Add to nginx.conf:
-```nginx
-listen 443 ssl;
-ssl_certificate /path/to/cert.pem;
-ssl_certificate_key /path/to/key.pem;
-```
+---
## Monitoring
### Health Check
+
```bash
-curl http://localhost:8080/health
+curl http://localhost/api/health
```
### Logs
+
```bash
-docker logs {project_name}
+# Docker logs
+docker-compose logs -f
+
+# PM2 logs
+pm2 logs backend
+```
+
+### Metrics
+
+Install PM2 metrics:
+
+```bash
+pm2 install pm2-metrics
+pm2 set pm2-metrics:port 9633
```
```
@@ -893,96 +2577,157 @@ post_gitea_comment(issue_number, """## 📚 Documentation Complete
### Files Created
- ✅ README.md - Quick start guide
-- ✅ docs/TECHNICAL.md - Technical docs
+- ✅ docs/API.md - API documentation
- ✅ docs/DEPLOYMENT.md - Deployment guide
+- ✅ docs/ADMIN.md - Admin user guide
+- ✅ .env.example - Environment template
### Documentation Coverage
- Installation instructions
-- Usage examples
-- Configuration options
-- Troubleshooting guide
+- Development setup
+- Production deployment
+- API reference with examples
+- Admin panel guide
+- Environment variables
+- Monitoring and logs
**Next**: Final validation
""")
```
-## Step 7: Final Validation
+## Step 8: Final Validation
**Agent**: `@CodeSkeptic` → `@Evaluator`
### Validation Checklist
-- [ ] All HTML valid
-- [ ] CSS valid
-- [ ] JavaScript no errors
-- [ ] All tests passing
-- [ ] Docker build succeeds
-- [ ] Documentation complete
-- [ ] Accessibility audit passed
-- [ ] Performance audit passed
-- [ ] Mobile responsive verified
+- [ ] Backend: Node.js + Express + SQLite working
+- [ ] Frontend: Vue.js 3 with all components
+- [ ] Admin Panel: CRUD operations working
+- [ ] Database: Migrations run successfully
+- [ ] Authentication: JWT login working
+- [ ] Responsive: All breakpoints tested
+- [ ] Cross-browser: Chrome, Firefox, Safari tested
+- [ ] E2E Tests: All tests passing
+- [ ] Docker: Containers build and run
+- [ ] Documentation: Complete
-### Run Validations
+### Run Validation
```bash
-# HTML validation
-npx html-validate src/**/*.html
+# Backend validation
+cd backend
+npm run lint
+npm test
+npm run test:coverage
-# CSS validation
-npx stylelint "src/**/*.css"
+# Frontend validation
+cd frontend
+npm run lint
+npm run build
+npm run test
-# JS linting
-npx eslint src/**/*.js
+# E2E tests
+npx playwright test
-# Accessibility audit
-npx pa11y http://localhost:8080
+# Docker validation
+docker-compose build
+docker-compose up -d
+docker-compose exec backend npm run test
-# Performance audit
-npx lighthouse http://localhost:8080 --output=json
+# Accessibility
+npx pa11y http://localhost
+
+# Performance
+npx lighthouse http://localhost --output=json
```
### Final Report
```python
-post_gitea_comment(issue_number, """## ✅ Landing Page Complete
+post_gitea_comment(issue_number, """## ✅ Landing Page CMS Complete
### Summary
**Project**: {project_name}
**Status**: Production Ready
**Score**: {score}/10
-### Deliverables
-- ✅ {pages_count} HTML pages
-- ✅ {components_count} components
-- ✅ {tests_count} E2E tests (all passing)
-- ✅ Docker image ({image_size}MB)
-- ✅ Complete documentation
-
-### Metrics
-- Accessibility: WCAG 2.1 AA
-- Performance: Lighthouse {lighthouse_score}
-- Responsive: Mobile-first
-- Bundle size: {bundle_size}KB
+### Technology Stack
+**Frontend**: Vue.js 3 + {ui_framework} + Pinia + Vite
+**Backend**: Node.js 20 + Express + SQLite
+**Auth**: JWT + bcrypt
+**Deploy**: Docker + Nginx
### Files Created
-```
-{file_tree}
-```
+- **Backend**: {backend_files} files
+- **Frontend**: {frontend_files} files
+- **Tests**: {test_files} files
+- **Docs**: {doc_files} files
+
+### Database
+- 7 tables created
+- Indexes optimized
+- Foreign keys enabled
+
+### API Endpoints
+- 6 public endpoints
+- 18 admin endpoints
+
+### Tests
+- **Total**: {total_tests}
+- **Passed**: {passed_tests}
+- **Failed**: {failed_tests}
+- **Coverage**: {coverage}%
+
+### Browser Support
+✅ Chrome 90+
+✅ Firefox 88+
+✅ Safari 14+
+✅ Edge 90+
+✅ Mobile Safari 14+
+✅ Chrome Mobile 90+
+
+### Responsive
+✅ Mobile (< 640px)
+✅ Tablet (640px - 1023px)
+✅ Desktop (≥ 1024px)
+
+### Deliverables
+1. **Source Code**
+ - Complete backend API
+ - Vue.js frontend SPA
+ - Admin content management
+ - SQLite database
+
+2. **Docker**
+ - Production-ready containers
+ - Nginx configuration
+ - Health checks
+
+3. **Documentation**
+ - README.md
+ - API documentation
+ - Deployment guide
+ - Admin guide
### Quick Start
```bash
docker-compose up -d
-# Open http://localhost:8080
+docker-compose exec backend npm run init-db
+docker-compose exec backend npm run create-admin
+# Open http://localhost
+# Admin: http://localhost/admin
```
-### Delivery
-This landing page is ready for client delivery:
-1. All source code in `/src`
-2. Docker image ready for deployment
-3. Documentation complete
-4. Tests passing
+### Client Handoff
+- ✅ Fully functional CMS
+- ✅ Admin panel for content management
+- ✅ Responsive design
+- ✅ Cross-browser tested
+- ✅ Docker deployment
+- ✅ Complete documentation
-**Status**: 🟢 COMPLETE
+**Status**: 🟢 READY FOR DELIVERY
""")
```
@@ -990,42 +2735,45 @@ This landing page is ready for client delivery:
| Gate | Criteria | Pass Condition |
|------|----------|----------------|
-| Analysis | All components identified | 100% mockup coverage |
-| Architecture | Tech stack defined | Stack documented |
-| Implementation | All components built | No console errors |
-| Testing | All tests passing | 100% pass rate |
-| Docker | Container builds and runs | Health check passes |
-| Documentation | All docs created | README complete |
-| Validation | All audits passing | Score ≥ 8/10 |
+| Architecture | Full stack defined | Frontend + Backend + DB documented |
+| Backend | API working | All endpoints respond |
+| Frontend | Vue app working | Pages render correctly |
+| Admin | CRUD working | Content can be edited |
+| Database | Schema created | Tables and indexes exist |
+| Responsive | All breakpoints | Mobile, tablet, desktop tested |
+| Cross-browser | 3+ browsers | Chrome, Firefox, Safari pass |
+| E2E Tests | All passing | 100% test pass rate |
+| Docker | Container builds | Health check passes |
+| Documentation | Complete | README, API, Deploy docs exist |
## Error Handling
-### Build Errors
-```
-If build fails:
-1. Check console for errors
-2. Verify all dependencies installed
-3. Run `npm run lint` for issues
-4. Fix reported problems
-5. Retry build
+### Database Errors
+
+```bash
+# If migration fails
+cd backend
+rm -f ../database/landing.db
+npm run init-db
```
-### Test Failures
-```
-If tests fail:
-1. Run `npx playwright test --debug`
-2. Check screenshots in test-results/
-3. Fix identified issues
-4. Re-run tests
+### Build Errors
+
+```bash
+# If frontend build fails
+cd frontend
+rm -rf node_modules package-lock.json
+npm install
+npm run build
```
### Docker Issues
-```
-If Docker fails:
-1. Check Docker daemon running
-2. Verify Dockerfile syntax
-3. Check disk space
-4. Review build logs: `docker build --progress=plain .`
+
+```bash
+# If container fails
+docker-compose down -v
+docker-compose build --no-cache
+docker-compose up -d
```
## Handoff to Client
@@ -1033,65 +2781,71 @@ If Docker fails:
After completion, deliver:
1. **Source Code**
- - Complete `/src` directory
+ - Complete repository
- All components and pages
- - All assets and styles
+ - Admin panel
+ - Database migrations
-2. **Docker Image**
- - Pre-built image
- - Or Dockerfile for custom build
+2. **Docker Package**
+ - Pre-built images
+ - Docker Compose file
+ - Environment template
3. **Documentation**
- - README.md (quick start)
- - docs/TECHNICAL.md (technical details)
- - docs/DEPLOYMENT.md (deployment guide)
+ - README.md
+ - API Reference
+ - Deployment Guide
+ - Admin Guide
-4. **Tests**
- - All test files
- - Test report
- - Visual regression baselines
+4. **Test Evidence**
+ - E2E test reports
+ - Screenshot comparisons
+ - Coverage reports
-5. **Instructions**
- - How to run locally
- - How to deploy
- - How to customize
+5. **Credentials**
+ - Admin login
+ - JWT secret (change in production)
+ - Database location
## Example Invocation
```
-User: /landing-page --mockup_dir=./mockups --project_name=MyProduct --style=tailwind
+User: /landing-page --mockup_dir=./mockups --project_name=MyProduct --ui_framework=vuetify
Agent:
-1. Analyzes mockups in ./mockups/
-2. Creates project structure
-3. Implements components
-4. Writes E2E tests
-5. Creates Docker setup
-6. Generates documentation
-7. Validates everything
-8. Reports to Gitea
-9. Delivers ready-to-deploy package
+1. Analyzes mockups
+2. Designs architecture (Vue + Node + SQLite)
+3. Implements backend API
+4. Builds Vue frontend + Admin
+5. Creates responsive design
+6. Writes E2E tests
+7. Creates Docker setup
+8. Generates documentation
+9. Validates everything
+10. Reports to Gitea
+11. Delivers ready-to-deploy package
```
## Gitea Integration
Every step posts progress to the linked issue:
-1. 🎨 Analysis → Issue comment with component inventory
-2. 📐 Architecture → Issue comment with project structure
-3. 🛠️ Implementation → Issue comment with file changes
-4. ✅ Testing → Issue comment with test results
-5. 🐳 Docker → Issue comment with build status
-6. 📚 Documentation → Issue comment with deliverables
-7. ✅ Complete → Issue comment with final package
+1. 🎨 Analysis → Component inventory
+2. 📐 Architecture → Tech stack, schema
+3. ⚙️ Backend → API endpoints, database
+4. 🖼️ Frontend → Components, pages, admin
+5. ✅ Testing → E2E results
+6. 🐳 Docker → Container status
+7. 📚 Documentation → Deliverables
+8. ✅ Complete → Final package
## Status Tracking
-Update issue labels throughout:
+Update issue labels:
- `status: new` → Analysis starting
- `status: designing` → Architecture in progress
-- `status: implementing` → Components being built
+- `status: implementing` → Backend + Frontend
- `status: testing` → E2E tests running
- `status: releasing` → Docker building
- `status: completed` → Package delivered
\ No newline at end of file
diff --git a/.kilo/rules/prompt-engineering.md b/.kilo/rules/prompt-engineering.md
new file mode 100644
index 0000000..f542f45
--- /dev/null
+++ b/.kilo/rules/prompt-engineering.md
@@ -0,0 +1,328 @@
+# Prompt Engineering Rules
+
+Guidelines for crafting effective prompts for AI agents.
+
+## General Principles
+
+### Be Clear and Specific
+
+- Clearly state what you want the agent to do
+- Avoid ambiguity and vague instructions
+- Include specific file paths, function names, and line numbers when relevant
+
+**Bad:** Fix the code.
+**Good:** Fix the bug in the `calculateTotal` function that causes it to return incorrect results when cart is empty.
+
+### Provide Context
+
+- Use context mentions (`@/path/to/file`) to refer to specific files
+- Include relevant code snippets or error messages
+- Reference related issues or previous changes
+
+**Good:** `@/src/utils.ts` Refactor the `calculateTotal` function to use async/await instead of callbacks.
+
+### Break Down Tasks
+
+- Divide complex tasks into smaller, well-defined steps
+- Use numbered lists for multi-step instructions
+- Specify the order of operations
+
+**Good:**
+```
+1. First, analyze the current implementation
+2. Identify performance bottlenecks
+3. Refactor the main loop to use caching
+4. Add unit tests for the new implementation
+5. Verify the changes don't break existing tests
+```
+
+### Give Examples
+
+- If you have a specific coding style in mind, provide examples
+- Show the expected input/output format
+- Include code snippets that demonstrate the pattern
+
+### Specify Output Format
+
+- If you need output in a particular format, specify it
+- Common formats: JSON, Markdown, TypeScript interfaces
+- Include example structure when necessary
+
+## Thinking vs. Doing
+
+Guide agents through a "think-then-do" process:
+
+### Analyze Phase
+Ask the agent to analyze the current code, identify problems, or plan the approach.
+
+**Prompt Pattern:**
+```
+Analyze the current implementation of [feature].
+Identify:
+- Potential issues
+- Areas for improvement
+- Security vulnerabilities
+```
+
+### Plan Phase
+Have the agent outline the steps it will take to complete the task.
+
+**Prompt Pattern:**
+```
+Before making any changes, provide a plan:
+1. What files will be modified
+2. What functions will be added/changed
+3. What dependencies are needed
+4. What tests should be written
+```
+
+### Execute Phase
+Instruct the agent to implement the plan, one step at a time.
+
+**Prompt Pattern:**
+```
+Now implement the plan:
+1. Start with [first step]
+2. Then [second step]
+...
+```
+
+### Review Phase
+Carefully review the results of each step before proceeding.
+
+**Prompt Pattern:**
+```
+Review the changes:
+- Do they meet the requirements?
+- Are there any side effects?
+- Do the tests pass?
+```
+
+## Custom Instructions
+
+### Global Custom Instructions
+
+Apply to all agents and modes. Place in `.kilo/rules/global.md` or `AGENTS.md`.
+
+**Examples:**
+- Enforce coding style guidelines
+- Specify preferred libraries
+- Define project-specific conventions
+
+### Mode-Specific Custom Instructions
+
+Apply only to specific agents. Place in `.kilo/agents/[agent].md`.
+
+**Examples:**
+- Lead Developer: "Always write tests before code (TDD)"
+- Code Skeptic: "Check for security vulnerabilities first"
+- Frontend Developer: "Use Tailwind CSS for all styling"
+
+## Handling Ambiguity
+
+### When Request is Unclear
+
+The agent should:
+
+1. **Ask clarifying questions** using the `question` tool
+2. **Not make assumptions** without user confirmation
+3. **Provide options** for the user to choose from
+
+**Example:**
+```
+I need clarification:
+- Option A: Implement as a new module
+- Option B: Add to existing service
+- Option C: Create a separate microservice
+```
+
+### Providing Multiple Options
+
+When presenting choices:
+- Use clear, concise labels
+- Provide descriptions for each option
+- Recommend a default choice
+- Allow custom input
+
+## Providing Feedback
+
+### Rejecting Actions
+
+When the agent proposes an incorrect action:
+
+1. Explain *why* the action is wrong
+2. Provide the correct approach
+3. Give an example if helpful
+
+**Example:**
+```
+This approach won't work because [reason].
+Instead, use [correct approach].
+Here's an example: [code snippet]
+```
+
+### Rewording Requests
+
+If initial prompt doesn't produce desired results:
+
+1. Be more specific about requirements
+2. Add constraints or boundaries
+3. Provide examples of expected output
+4. Break into smaller sub-tasks
+
+## Prompt Patterns
+
+### Feature Request Pattern
+
+```markdown
+## Feature: [Feature Name]
+
+### Requirements
+1. [Requirement 1]
+2. [Requirement 2]
+
+### Acceptance Criteria
+- [ ] [Criterion 1]
+- [ ] [Criterion 2]
+
+### Files to Modify
+- `path/to/file1.ts`
+- `path/to/file2.ts`
+
+### Constraints
+- Use [library/framework]
+- Follow [pattern/style]
+- Must be backward compatible
+```
+
+### Bug Fix Pattern
+
+```markdown
+## Bug: [Bug Description]
+
+### Current Behavior
+[What's happening now]
+
+### Expected Behavior
+[What should happen]
+
+### Steps to Reproduce
+1. [Step 1]
+2. [Step 2]
+
+### Files Involved
+- `path/to/file.ts` (line X)
+
+### Error Message
+```
+[Stack trace or error message]
+```
+```
+
+### Refactoring Pattern
+
+```markdown
+## Refactor: [What to Refactor]
+
+### Current Implementation
+[Brief description or code snippet]
+
+### Target Implementation
+[What it should become]
+
+### Reason
+[Why this refactoring is needed]
+
+### Files to Update
+- [File list]
+
+### Requirements
+- Maintain existing functionality
+- Keep tests passing
+- Update documentation
+```
+
+## Examples
+
+### Good Prompts
+
+**Feature Implementation:**
+> `@/src/components/Button.tsx` Refactor the `Button` component to support three variants: primary, secondary, and danger. Use the design tokens from `@/src/styles/tokens.ts`.
+
+**Bug Fix:**
+> `@problems` Fix the TypeError in `calculateTotal` when the cart is empty. The function should return 0 for empty arrays.
+
+**Architecture:**
+> Create a new service for handling user notifications. Follow the pattern in `@/src/services/EmailService.ts`. The service should support email, SMS, and push notifications.
+
+### Bad Prompts
+
+**Too Vague:**
+> Fix the button. (What's wrong with it?)
+
+**No Context:**
+> Write some Python code. (What should it do?)
+
+**Too Broad:**
+> Fix everything. (What is "everything"?)
+
+**No Constraints:**
+> Create a new feature. (What feature? For what?)
+
+## Prompt Anti-Patterns
+
+### Avoid These Patterns
+
+1. **Kitchen Sink Prompts**
+ - Asking for too many things at once
+ - Better: Break into multiple focused prompts
+
+2. **Missing Constraints**
+ - Not specifying required libraries or patterns
+ - Better: Always mention relevant constraints
+
+3. **Assuming Knowledge**
+ - Expecting the agent to know project context
+ - Better: Provide `@file` references
+
+4. **Ignoring Output**
+ - Not reviewing agent's changes
+ - Better: Always review and provide feedback
+
+5. **No Iteration**
+ - Accepting first result without refinement
+ - Better: Iterate on prompts for better results
+
+## Context Mentions
+
+Use context mentions to provide specific file references:
+
+| Mention | Description |
+|---------|-------------|
+| `@file.js` | Reference a specific file |
+| `@/src/utils/` | Reference a directory |
+| `@problems` | Reference all errors in the file |
+| `@git` | Reference git history |
+| `@terminal` | Reference terminal output |
+
+## Iterative Prompting
+
+When initial results aren't perfect:
+
+1. **Identify Issues:** What's wrong with the current output?
+2. **Clarify Requirements:** Add more specific instructions
+3. **Provide Examples:** Show the expected format or pattern
+4. **Break Down:** Split complex tasks into smaller ones
+5. **Refine:** Adjust constraints or add context
+
+## Verification Checklist
+
+After receiving agent output:
+
+- [ ] Does it meet all stated requirements?
+- [ ] Are there any syntax errors?
+- [ ] Does it follow project conventions?
+- [ ] Are edge cases handled?
+- [ ] Is it backward compatible?
+- [ ] Are tests included/updated?
+- [ ] Is documentation updated?
\ No newline at end of file
diff --git a/.kilo/skills/blog/SKILL.md b/.kilo/skills/blog/SKILL.md
new file mode 100644
index 0000000..dcc13e9
--- /dev/null
+++ b/.kilo/skills/blog/SKILL.md
@@ -0,0 +1,489 @@
+---
+name: blog
+description: Blog/CMS domain knowledge - posts, categories, tags, comments, authors, SEO
+---
+
+# Blog Skill
+
+## Purpose
+
+Provides domain knowledge for building blog and content management systems: posts, categories, tags, comments, authors, SEO optimization.
+
+## Capabilities
+
+### Content Management
+- Post CRUD operations
+- Draft/Published/Archived states
+- Content scheduling
+- Rich text editing
+- Media embedding
+
+### Organization
+- Categories (hierarchical)
+- Tags (flat)
+- Author assignment
+- Content series
+
+### Comments
+- Comment moderation
+- Threaded comments
+- Spam filtering
+- Social login comments
+
+### SEO
+- Meta tags
+- Open Graph
+- Structured data (Schema.org)
+- Sitemap generation
+- RSS feeds
+
+### Analytics
+- View counts
+- Reading time estimation
+- Popular posts
+- Related posts
+
+## Database Schema
+
+### Posts
+
+```sql
+CREATE TABLE posts (
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
+ title TEXT NOT NULL,
+ slug TEXT UNIQUE NOT NULL,
+ excerpt TEXT,
+ content TEXT NOT NULL,
+ featured_image TEXT,
+ author_id INTEGER NOT NULL,
+ category_id INTEGER,
+ status TEXT DEFAULT 'draft', -- 'draft', 'published', 'archived'
+ published_at DATETIME,
+ meta_title TEXT,
+ meta_description TEXT,
+ canonical_url TEXT,
+ reading_time INTEGER, -- minutes
+ view_count INTEGER DEFAULT 0,
+ allow_comments BOOLEAN DEFAULT 1,
+ created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
+ updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,
+ FOREIGN KEY (author_id) REFERENCES users(id),
+ FOREIGN KEY (category_id) REFERENCES categories(id)
+);
+
+CREATE INDEX idx_posts_slug ON posts(slug);
+CREATE INDEX idx_posts_status ON posts(status);
+CREATE INDEX idx_posts_published ON posts(published_at);
+CREATE INDEX idx_posts_author ON posts(author_id);
+CREATE INDEX idx_posts_category ON posts(category_id);
+```
+
+### Categories
+
+```sql
+CREATE TABLE categories (
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
+ name TEXT NOT NULL,
+ slug TEXT UNIQUE NOT NULL,
+ description TEXT,
+ parent_id INTEGER,
+ image_url TEXT,
+ meta_title TEXT,
+ meta_description TEXT,
+ sort_order INTEGER DEFAULT 0,
+ FOREIGN KEY (parent_id) REFERENCES categories(id)
+);
+
+CREATE INDEX idx_categories_parent ON categories(parent_id);
+```
+
+### Tags
+
+```sql
+CREATE TABLE tags (
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
+ name TEXT NOT NULL,
+ slug TEXT UNIQUE NOT NULL,
+ description TEXT
+);
+
+CREATE TABLE post_tags (
+ post_id INTEGER NOT NULL,
+ tag_id INTEGER NOT NULL,
+ PRIMARY KEY (post_id, tag_id),
+ FOREIGN KEY (post_id) REFERENCES posts(id) ON DELETE CASCADE,
+ FOREIGN KEY (tag_id) REFERENCES tags(id) ON DELETE CASCADE
+);
+
+CREATE INDEX idx_post_tags_post ON post_tags(post_id);
+CREATE INDEX idx_post_tags_tag ON post_tags(tag_id);
+```
+
+### Comments
+
+```sql
+CREATE TABLE comments (
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
+ post_id INTEGER NOT NULL,
+ parent_id INTEGER, -- for threaded comments
+ author_name TEXT NOT NULL,
+ author_email TEXT NOT NULL,
+ author_url TEXT,
+ content TEXT NOT NULL,
+ status TEXT DEFAULT 'pending', -- 'pending', 'approved', 'spam', 'trash'
+ ip_address TEXT,
+ user_agent TEXT,
+ created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
+ FOREIGN KEY (post_id) REFERENCES posts(id) ON DELETE CASCADE,
+ FOREIGN KEY (parent_id) REFERENCES comments(id)
+);
+
+CREATE INDEX idx_comments_post ON comments(post_id);
+CREATE INDEX idx_comments_status ON comments(status);
+```
+
+### Authors
+
+```sql
+CREATE TABLE authors (
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
+ user_id INTEGER UNIQUE,
+ name TEXT NOT NULL,
+ bio TEXT,
+ avatar TEXT,
+ social_links TEXT, -- JSON: {"twitter": "...", "linkedin": "..."}
+ created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
+ FOREIGN KEY (user_id) REFERENCES users(id)
+);
+```
+
+## API Endpoints
+
+### Public API
+
+```yaml
+# Posts
+GET /api/posts # List published posts (paginated)
+GET /api/posts/:slug # Get post by slug
+GET /api/posts/author/:author # Posts by author
+GET /api/posts/category/:category # Posts by category
+GET /api/posts/tag/:tag # Posts by tag
+GET /api/posts/search?q=query # Search posts
+
+# Categories
+GET /api/categories # List categories
+GET /api/categories/:slug # Get category with posts
+
+# Tags
+GET /api/tags # List tags
+GET /api/tags/:slug # Get tag with posts
+
+# Comments
+GET /api/posts/:slug/comments # Get approved comments
+POST /api/posts/:slug/comments # Submit new comment
+
+# Feeds
+GET /api/feed/rss # RSS feed
+GET /api/feed/atom # Atom feed
+GET /api/sitemap.xml # Sitemap
+```
+
+### Admin API
+
+```yaml
+# Posts
+GET /api/admin/posts # List all posts (all statuses)
+POST /api/admin/posts # Create post
+PUT /api/admin/posts/:id # Update post
+DELETE /api/admin/posts/:id # Delete post
+POST /api/admin/posts/:id/publish # Publish post
+POST /api/admin/posts/:id/archive # Archive post
+
+# Categories
+GET /api/admin/categories # List all categories
+POST /api/admin/categories # Create category
+PUT /api/admin/categories/:id # Update category
+DELETE /api/admin/categories/:id # Delete category
+
+# Tags
+GET /api/admin/tags # List all tags
+POST /api/admin/tags # Create tag
+PUT /api/admin/tags/:id # Update tag
+DELETE /api/admin/tags/:id # Delete tag
+
+# Comments
+GET /api/admin/comments # List comments (all statuses)
+PUT /api/admin/comments/:id/approve # Approve comment
+PUT /api/admin/comments/:id/spam # Mark as spam
+DELETE /api/admin/comments/:id # Delete comment
+
+# Media
+POST /api/admin/media/upload # Upload media
+GET /api/admin/media # List media
+DELETE /api/admin/media/:id # Delete media
+```
+
+## Rich Content Features
+
+### Markdown Support
+
+```javascript
+// utils/markdown.js
+const marked = require('marked');
+const hljs = require('highlight.js');
+
+const renderer = {
+ code(code, language) {
+ const highlighted = language
+ ? hljs.highlight(code, { language }).value
+ : code;
+ return `${highlighted}
`;
+ },
+ image(href, title, alt) {
+ return `
${alt}`;
+ }
+};
+
+marked.use({ renderer });
+
+function parseMarkdown(content) {
+ return marked.parse(content);
+}
+
+function calculateReadingTime(content) {
+ const words = content.split(/\s+/).length;
+ return Math.ceil(words / 200); // 200 words per minute
+}
+```
+
+### Embed Support
+
+```javascript
+// utils/embeds.js
+const embedPatterns = {
+ youtube: /(?:youtube\.com\/watch\?v=|youtu\.be\/)([a-zA-Z0-9_-]+)/,
+ twitter: /twitter\.com\/\w+\/status\/(\d+)/,
+ twitter: /twitter\.com\/(\w+)\/status\/(\d+)/,
+ vimeo: /vimeo\.com\/(\d+)/,
+ codepen: /codepen\.io\/(\w+)\/pen\/(\w+)/
+};
+
+function parseEmbeds(content) {
+ let parsed = content;
+
+ for (const [platform, pattern] of Object.entries(embedPatterns)) {
+ parsed = parsed.replace(pattern, (match) => {
+ return generateEmbed(platform, match);
+ });
+ }
+
+ return parsed;
+}
+
+function generateEmbed(platform, url) {
+ switch (platform) {
+ case 'youtube':
+ const videoId = url.match(embedPatterns.youtube)[1];
+ return ``;
+ // ... other platforms
+ }
+}
+```
+
+## SEO Implementation
+
+### Meta Tags
+
+```javascript
+// utils/seo.js
+function generateMeta(post) {
+ return {
+ title: post.meta_title || `${post.title} | ${config.siteName}`,
+ description: post.meta_description || post.excerpt,
+ canonical: post.canonical_url || `${config.siteUrl}/posts/${post.slug}`,
+ ogType: 'article',
+ ogImage: post.featured_image,
+ articlePublishedTime: post.published_at,
+ articleAuthor: post.author.name
+ };
+}
+```
+
+### Structured Data
+
+```javascript
+// utils/schema.js
+function generateArticleSchema(post) {
+ return {
+ "@context": "https://schema.org",
+ "@type": "Article",
+ "headline": post.title,
+ "image": post.featured_image,
+ "author": {
+ "@type": "Person",
+ "name": post.author.name
+ },
+ "datePublished": post.published_at,
+ "dateModified": post.updated_at,
+ "description": post.excerpt
+ };
+}
+```
+
+### Sitemap
+
+```xml
+
+
+
+
+ https://example.com/
+ daily
+ 1.0
+
+ {#posts}
+
+ https://example.com/posts/{slug}
+ {updated_at}
+ weekly
+ 0.8
+
+ {/posts}
+
+```
+
+## Comment Moderation
+
+### Spam Detection
+
+```javascript
+// services/comments/spam.js
+function detectSpam(comment) {
+ const signals = [];
+
+ // Check for spam patterns
+ if (containsLinks(comment.content) > 3) signals.push('excessive_links');
+ if (isDuplicate(comment)) signals.push('duplicate');
+ if (isBlacklisted(comment.ip_address)) signals.push('blacklisted_ip');
+ if (containsSpamWords(comment.content)) signals.push('spam_words');
+
+ // Calculate spam score
+ const score = signals.length;
+
+ return {
+ isSpam: score >= 2,
+ score,
+ signals
+ };
+}
+```
+
+## Content Scheduling
+
+```javascript
+// services/scheduler.js
+async function publishScheduledPosts() {
+ const now = new Date();
+
+ const posts = await db.posts.findAll({
+ where: {
+ status: 'draft',
+ published_at: { [Op.lte]: now }
+ }
+ });
+
+ for (const post of posts) {
+ await post.update({ status: 'published' });
+ await notifySubscribers(post);
+ await updateSitemap();
+ }
+}
+
+// Run every minute
+setInterval(publishScheduledPosts, 60000);
+```
+
+## Related Posts
+
+```javascript
+// services/related.js
+async function getRelatedPosts(post, limit = 5) {
+ // Find posts with same category or tags
+ const related = await db.posts.findAll({
+ where: {
+ id: { [Op.ne]: post.id },
+ status: 'published',
+ [Op.or]: [
+ { category_id: post.category_id },
+ { '$tags.id$': post.tags.map(t => t.id) }
+ ]
+ },
+ include: [db.tags],
+ limit,
+ order: [['published_at', 'DESC']]
+ });
+
+ return related;
+}
+```
+
+## Performance
+
+### Query Optimization
+
+```javascript
+// Use joins for efficient loading
+const post = await db.posts.findOne({
+ where: { slug },
+ include: [
+ { model: db.authors, include: [db.users] },
+ { model: db.categories },
+ { model: db.tags }
+ ]
+});
+
+// Paginate efficiently
+const posts = await db.posts.findAll({
+ where: { status: 'published' },
+ limit: 20,
+ offset: (page - 1) * 20,
+ order: [['published_at', 'DESC']]
+});
+```
+
+### Caching
+
+```javascript
+// Cache popular posts
+async function getPopularPosts() {
+ const cacheKey = 'popular-posts';
+ const cached = await cache.get(cacheKey);
+
+ if (cached) return cached;
+
+ const posts = await db.posts.findAll({
+ order: [['view_count', 'DESC']],
+ limit: 10
+ });
+
+ await cache.set(cacheKey, posts, 3600); // 1 hour
+
+ return posts;
+}
+```
+
+## Security
+
+- Sanitize all user input (HTML, comments)
+- Validate author permissions
+- Rate limit comments
+- Use CSRF protection for forms
+- Implement CAPTCHA for guest comments
+
+## Integration Points
+
+- Email subscribers: SendGrid, Mailchimp
+- CDN for images: Cloudflare, AWS CloudFront
+- Analytics: Google Analytics, Plausible
+- Comment systems: Disqus, Facebook Comments
+- Search: Algolia, Elasticsearch
\ No newline at end of file
diff --git a/.kilo/skills/ecommerce/SKILL.md b/.kilo/skills/ecommerce/SKILL.md
new file mode 100644
index 0000000..ecd52ee
--- /dev/null
+++ b/.kilo/skills/ecommerce/SKILL.md
@@ -0,0 +1,394 @@
+---
+name: ecommerce
+description: E-commerce domain knowledge - products, carts, orders, payments, inventory management
+---
+
+# E-commerce Skill
+
+## Purpose
+
+Provides domain knowledge for building e-commerce systems: product catalogs, shopping carts, order processing, payment integration, and inventory management.
+
+## Capabilities
+
+### Product Catalog
+- Product CRUD operations
+- Categories and tags
+- Product variants (size, color)
+- Pricing and discounts
+- Product search and filtering
+- Image galleries
+
+### Shopping Cart
+- Add/remove items
+- Quantity updates
+- Cart persistence (session/database)
+- Price calculations
+- Discount codes
+
+### Order Processing
+- Order creation from cart
+- Order status workflow
+- Order history
+- Invoice generation
+- Email notifications
+
+### Payment Integration
+- Stripe integration
+- PayPal integration
+- Payment status tracking
+- Refund processing
+- Webhook handling
+
+### Inventory Management
+- Stock tracking
+- Low stock alerts
+- Inventory adjustments
+- Supplier management
+
+## Database Schema
+
+### Products
+
+```sql
+CREATE TABLE products (
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
+ sku TEXT UNIQUE NOT NULL,
+ name TEXT NOT NULL,
+ description TEXT,
+ price DECIMAL(10, 2) NOT NULL,
+ compare_at_price DECIMAL(10, 2),
+ cost_price DECIMAL(10, 2),
+ quantity INTEGER DEFAULT 0,
+ category_id INTEGER,
+ is_active BOOLEAN DEFAULT 1,
+ created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
+ updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,
+ FOREIGN KEY (category_id) REFERENCES categories(id)
+);
+
+CREATE TABLE product_variants (
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
+ product_id INTEGER NOT NULL,
+ sku TEXT UNIQUE NOT NULL,
+ name TEXT NOT NULL,
+ price_adjustment DECIMAL(10, 2) DEFAULT 0,
+ quantity INTEGER DEFAULT 0,
+ attributes TEXT, -- JSON: {"size": "M", "color": "red"}
+ FOREIGN KEY (product_id) REFERENCES products(id)
+);
+
+CREATE TABLE categories (
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
+ name TEXT NOT NULL,
+ slug TEXT UNIQUE NOT NULL,
+ parent_id INTEGER,
+ description TEXT,
+ image_url TEXT,
+ FOREIGN KEY (parent_id) REFERENCES categories(id)
+);
+```
+
+### Cart and Orders
+
+```sql
+CREATE TABLE carts (
+ id TEXT PRIMARY KEY, -- UUID
+ user_id INTEGER,
+ session_id TEXT,
+ created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
+ updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,
+ FOREIGN KEY (user_id) REFERENCES users(id)
+);
+
+CREATE TABLE cart_items (
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
+ cart_id TEXT NOT NULL,
+ product_id INTEGER NOT NULL,
+ variant_id INTEGER,
+ quantity INTEGER NOT NULL DEFAULT 1,
+ price DECIMAL(10, 2) NOT NULL,
+ FOREIGN KEY (cart_id) REFERENCES carts(id),
+ FOREIGN KEY (product_id) REFERENCES products(id)
+);
+
+CREATE TABLE orders (
+ id TEXT PRIMARY KEY, -- UUID
+ order_number TEXT UNIQUE NOT NULL,
+ user_id INTEGER,
+ email TEXT NOT NULL,
+ status TEXT DEFAULT 'pending',
+ subtotal DECIMAL(10, 2) NOT NULL,
+ tax DECIMAL(10, 2) DEFAULT 0,
+ shipping DECIMAL(10, 2) DEFAULT 0,
+ discount DECIMAL(10, 2) DEFAULT 0,
+ total DECIMAL(10, 2) NOT NULL,
+ currency TEXT DEFAULT 'USD',
+ shipping_address TEXT,
+ billing_address TEXT,
+ notes TEXT,
+ created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
+ updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,
+ FOREIGN KEY (user_id) REFERENCES users(id)
+);
+
+CREATE TABLE order_items (
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
+ order_id TEXT NOT NULL,
+ product_id INTEGER NOT NULL,
+ variant_id INTEGER,
+ name TEXT NOT NULL,
+ sku TEXT NOT NULL,
+ quantity INTEGER NOT NULL,
+ price DECIMAL(10, 2) NOT NULL,
+ total DECIMAL(10, 2) NOT NULL,
+ FOREIGN KEY (order_id) REFERENCES orders(id),
+ FOREIGN KEY (product_id) REFERENCES products(id)
+);
+
+CREATE TABLE payments (
+ id TEXT PRIMARY KEY, -- UUID
+ order_id TEXT NOT NULL,
+ provider TEXT NOT NULL, -- 'stripe', 'paypal'
+ transaction_id TEXT,
+ amount DECIMAL(10, 2) NOT NULL,
+ currency TEXT DEFAULT 'USD',
+ status TEXT DEFAULT 'pending',
+ metadata TEXT, -- JSON
+ created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
+ FOREIGN KEY (order_id) REFERENCES orders(id)
+);
+```
+
+### Inventory
+
+```sql
+CREATE TABLE inventory_transactions (
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
+ product_id INTEGER,
+ variant_id INTEGER,
+ quantity INTEGER NOT NULL,
+ type TEXT NOT NULL, -- 'purchase', 'sale', 'adjustment', 'return'
+ reference TEXT, -- order ID, PO ID
+ notes TEXT,
+ created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
+ FOREIGN KEY (product_id) REFERENCES products(id)
+);
+```
+
+## API Endpoints
+
+### Public API
+
+```yaml
+# Products
+GET /api/products # List products (with pagination, filters)
+GET /api/products/:slug # Get product by slug
+GET /api/categories # List categories
+GET /api/categories/:slug # Get category with products
+
+# Cart
+GET /api/cart # Get current cart
+POST /api/cart/items # Add item to cart
+PUT /api/cart/items/:id # Update quantity
+DELETE /api/cart/items/:id # Remove item
+POST /api/cart/coupon # Apply discount code
+
+# Checkout
+POST /api/checkout # Create order from cart
+POST /api/checkout/guest # Guest checkout
+GET /api/orders/:id # Get order details
+```
+
+### Admin API
+
+```yaml
+# Products
+GET /api/admin/products # List all products
+POST /api/admin/products # Create product
+PUT /api/admin/products/:id # Update product
+DELETE /api/admin/products/:id # Delete product
+
+# Categories
+GET /api/admin/categories # List all categories
+POST /api/admin/categories # Create category
+PUT /api/admin/categories/:id # Update category
+DELETE /api/admin/categories/:id # Delete category
+
+# Orders
+GET /api/admin/orders # List orders (with filters)
+PUT /api/admin/orders/:id # Update order status
+POST /api/admin/orders/:id/refund # Process refund
+
+# Inventory
+GET /api/admin/inventory # Inventory status
+PUT /api/admin/inventory/:id # Update stock
+POST /api/admin/inventory/adjust # Stock adjustment
+```
+
+## Payment Integration
+
+### Stripe
+
+```javascript
+// services/payment/stripe.js
+const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY);
+
+async function createPaymentIntent(order) {
+ const paymentIntent = await stripe.paymentIntents.create({
+ amount: Math.round(order.total * 100), // cents
+ currency: order.currency.toLowerCase(),
+ metadata: { orderId: order.id },
+ receipt_email: order.email
+ });
+
+ return {
+ clientSecret: paymentIntent.client_secret,
+ paymentIntentId: paymentIntent.id
+ };
+}
+
+async function processWebhook(signature, payload) {
+ const event = stripe.webhooks.constructEvent(
+ payload,
+ signature,
+ process.env.STRIPE_WEBHOOK_SECRET
+ );
+
+ switch (event.type) {
+ case 'payment_intent.succeeded':
+ await updatePaymentStatus(event.data.object.id, 'completed');
+ break;
+ case 'payment_intent.payment_failed':
+ await updatePaymentStatus(event.data.object.id, 'failed');
+ break;
+ }
+}
+```
+
+### PayPal
+
+```javascript
+// services/payment/paypal.js
+const paypal = require('@paypal/checkout-server-sdk');
+
+async function createOrder(order) {
+ const request = new orders.OrdersCreateRequest();
+ request.requestBody({
+ intent: 'CAPTURE',
+ purchase_units: [{
+ amount: {
+ currency_code: order.currency,
+ value: order.total.toFixed(2)
+ },
+ reference_id: order.id
+ }]
+ });
+
+ const response = await client.execute(request);
+ return response.result;
+}
+
+async function captureOrder(orderId) {
+ const request = new orders.OrdersCaptureRequest(orderId);
+ const response = await client.execute(request);
+ return response.result;
+}
+```
+
+## Order Statuses
+
+| Status | Description | Next Statuses |
+|--------|-------------|---------------|
+| `pending` | Created, awaiting payment | `processing`, `cancelled` |
+| `processing` | Payment confirmed, preparing | `shipped`, `on_hold` |
+| `shipped` | Shipped to customer | `delivered` |
+| `delivered` | Customer received | `completed` |
+| `completed` | Order complete | - |
+| `on_hold` | Manual review needed | `processing`, `cancelled` |
+| `cancelled` | Order cancelled | `refunded` |
+| `refunded` | Money returned to customer | - |
+
+## Email Templates
+
+### Order Confirmation
+
+```html
+Thank you for your order!
+Order #{{order_number}}
+
+Order Details
+{{#each items}}
+{{name}} x{{quantity}} - ${{total}}
+{{/each}}
+
+Total: ${{total}}
+
+Shipping Address
+{{shipping_address}}
+
+We'll send you another email when your order ships.
+```
+
+### Shipping Notification
+
+```html
+Your order has shipped!
+Order #{{order_number}}
+
+Tracking: {{tracking_number}}
+Carrier: {{carrier}}
+
+Estimated Delivery
+{{estimated_delivery}}
+```
+
+## Security Considerations
+
+### Payment Security
+- Never store credit card numbers
+- Use PCI-compliant payment providers
+- Implement CSRF protection
+- Use HTTPS everywhere
+
+### Order Fraud Prevention
+- Validate shipping address
+- Check for suspicious patterns (high value, rush shipping)
+- Implement rate limiting on checkout
+- Log all order actions
+
+## Performance Optimizations
+
+### Product Listings
+- Paginate results (20-50 per page)
+- Use database indexes on category, price
+- Cache category pages
+- Lazy load product images
+
+### Cart Performance
+- Store cart in Redis for quick access
+- Use database for persistence
+- Batch quantity updates
+
+### Inventory Checks
+- Real-time stock validation at checkout
+- Lock inventory during payment processing
+- Handle concurrent purchases gracefully
+
+## Integration Points
+
+- Product Import: CSV, JSON, API
+- Shipping Carriers: UPS, FedEx, DHL
+- Tax Calculation: TaxJar, Avalara
+- Email: SendGrid, Mailgun
+- Analytics: Google Analytics, Mixpanel
+
+## Handoff Protocol
+
+After implementation:
+1. Test checkout flow end-to-end
+2. Verify payment processing
+3. Check inventory deduction
+4. Test email notifications
+5. Verify order status transitions
+6. Review `@CodeSkeptic` for security audit
\ No newline at end of file