diff --git a/Contributing.md b/Contributing.md
new file mode 100644
index 0000000..00dd5a6
--- /dev/null
+++ b/Contributing.md
@@ -0,0 +1,316 @@
+# Contributing to MeshHook
+
+Thank you for your interest in contributing to MeshHook! This guide will help you get started with contributing to our webhook-first workflow engine.
+
+## About MeshHook
+
+MeshHook is an MIT-licensed, webhook-first workflow engine with a visual builder and Temporal-like durability via event sourcing on Postgres. We mesh your webhooks and orchestrate everything with simplicity, durability, and security.
+
+---
+
+## π Getting Started
+
+### Prerequisites
+
+Before you begin, ensure you have:
+
+- **Node.js** (v18 or later) or **Bun**
+- **pnpm** (recommended package manager)
+- **Git**
+- **Supabase CLI** (`pnpm install -g supabase`)
+- **Docker** (for local Supabase)
+
+### Setting Up Your Development Environment
+
+**1. Fork and clone**
+```bash
+git clone https://github.com/YOUR_USERNAME/meshhook.git
+cd meshhook
+```
+
+**2. Install dependencies**
+```bash
+pnpm install
+```
+
+**3. Setup environment**
+```bash
+pnpm run setup
+```
+Select "Local Development" when prompted.
+
+**4. Start Supabase locally**
+```bash
+pnpx supabase start
+```
+
+**5. Run database migrations**
+```bash
+pnpm run db:migrate
+```
+
+**6. Start the orchestrator**
+```bash
+pnpm run start
+```
+
+Your local instance should now be running at `http://localhost:8080`
+
+### Tech Stack
+
+- **UI/API**: SvelteKit (Svelte 5)
+- **Database/Queues/Realtime/Storage**: Supabase (Postgres)
+- **Workers**: Node.js or Bun (stateless)
+- **Queue**: pg-boss or pgmq (Postgres-native)
+- **Transforms**: JMESPath
+- **Single Service**: All components run on port 8080
+
+---
+
+## How to Contribute
+
+### Contribution Workflow
+
+**1. Create a feature branch**
+```bash
+git checkout -b feature/your-feature-name
+# or for bug fixes
+git checkout -b fix/bug-description
+```
+
+**2. Make your changes**
+- Write clean, readable code
+- Follow our style guide
+- Add tests if applicable
+- Update documentation if needed
+
+**3. Test your changes**
+```bash
+pnpm run lint
+pnpm run start
+pnpm run db:migrate # if you changed the database
+```
+
+**4. Commit your changes**
+```bash
+git add .
+git commit -m "Brief description of your changes"
+```
+
+Good commit messages:
+- β
`Add webhook retry logic`
+- β
`Fix event sourcing race condition`
+- β
`Update JMESPath transform examples`
+
+**5. Push to your fork**
+```bash
+git push origin feature/your-feature-name
+```
+
+**6. Create a Pull Request**
+
+Go to your fork on GitHub and click "New Pull Request". Fill out the PR template with:
+- Description of changes
+- Related issue number (if applicable)
+- Testing performed
+- Screenshots (for UI changes)
+
+**7. Address review feedback**
+- Respond to comments promptly
+- Make requested changes
+- Push updates to the same branch
+
+### What to Contribute
+
+We welcome contributions in many forms:
+
+- **Bug fixes** - Found a bug? Please fix it!
+- **New features** - Have an idea? Open an issue first to discuss
+- **Documentation** - Improve guides, add examples, fix typos
+- **Tests** - Add missing test coverage
+- **Performance improvements** - Make MeshHook faster
+- **Webhook integrations** - Add new webhook sources or destinations
+- **JMESPath transforms** - Create reusable transform templates
+- **UI/UX enhancements** - Improve the visual builder
+
+Looking for your first contribution? Check issues labeled `good first issue` or `hacktoberfest`.
+
+---
+
+## π Style Guide
+
+### JavaScript/TypeScript
+
+- Use **TypeScript** for new code
+- Use `const` and `let`, avoid `var`
+- Prefer arrow functions for callbacks
+- Use async/await over raw promises
+- Name variables descriptively (avoid single letters except in loops)
+- Add JSDoc comments for functions and complex logic
+
+### Svelte 5
+
+- Use **Svelte 5 runes** (`$state`, `$derived`, `$effect`)
+- Keep components small and focused
+- Use TypeScript in script blocks
+- Follow reactive programming patterns
+- Extract reusable logic into composables
+
+### CSS
+
+- Use **Tailwind CSS** utility classes when possible
+- For custom styles, use component-scoped CSS
+- Follow mobile-first responsive design
+- Maintain consistent spacing using Tailwind's scale
+
+### Database & Event Sourcing
+
+- Use **Postgres-native** features whenever possible
+- Follow event sourcing patterns for workflow state
+- Use pg-boss or pgmq for queue operations
+- Leverage Supabase Realtime for live updates
+- Write efficient queries, considering partitioning strategy
+
+### JMESPath Transforms
+
+- Keep transforms simple and readable
+- Add comments explaining complex expressions
+- Test transforms with sample data
+- Document expected input/output structures
+
+---
+
+## Community Standards
+
+### Code of Conduct
+
+We are committed to providing a welcoming and inclusive environment. We expect all contributors to:
+
+- **Be respectful** - Treat everyone with kindness and empathy
+- **Be collaborative** - Work together, share knowledge, help others
+- **Be patient** - Remember that everyone is learning
+- **Be constructive** - Provide helpful feedback, focus on solutions
+- **Be inclusive** - Welcome people of all backgrounds and skill levels
+
+### Communication
+
+- **GitHub Issues** - For bug reports and feature requests
+- **Pull Request comments** - For code-specific discussions
+- **Project discussions** - For general questions and ideas
+
+### Reporting Issues
+
+When reporting a bug, please include:
+- Clear description of the issue
+- Steps to reproduce
+- Expected vs actual behavior
+- Environment details (OS, Node version, Supabase version)
+- Screenshots or error logs if applicable
+- Relevant workflow configuration (if applicable)
+
+---
+
+## π Security
+
+- **Never commit sensitive information** (API keys, passwords, tokens, Supabase credentials)
+- Use environment variables for all configuration
+- `.env.staging` and `.env.production` are **not committed** to the repository
+- Report security vulnerabilities privately to the maintainers
+- Follow security best practices in webhook handling and data transformations
+
+---
+
+## β
Testing
+
+Before submitting a PR:
+- Test locally with `pnpm run start`
+- Verify migrations work: `pnpm run db:migrate`
+- Test webhook intake and workflow execution
+- Check for linting errors: `pnpm run lint`
+- Verify that existing functionality still works
+- Test with both local Supabase and remote instances (if possible)
+
+---
+
+## π Documentation
+
+When adding new features:
+- Update relevant documentation in `./docs/`
+- Add code comments for complex logic
+- Update PlantUML diagrams if architecture changes
+- Add examples for new webhook integrations or transforms
+- Update the README if necessary
+
+---
+
+## Useful Commands
+
+### Setup & Configuration
+```bash
+pnpm run setup # Interactive environment configuration
+pnpm run db:migrate # Run database migrations (auto-detects environment)
+```
+
+### Development
+```bash
+pnpm run start # Start the orchestrator worker
+pnpm mh --help # CLI help
+```
+
+### Testing & Linting
+```bash
+pnpm test # Run tests (if available)
+pnpm run lint # Check for linting errors
+```
+
+### Supabase
+```bash
+pnpx supabase start # Start local Supabase
+pnpx supabase stop # Stop local Supabase
+pnpx supabase status # Check Supabase status
+```
+
+---
+
+## Environment Files
+
+- `.env.local` - Local development (committed to repo with safe defaults)
+- `.env.staging` - Staging environment (**not committed**)
+- `.env.production` - Production environment (**not committed**)
+- `.env` - Symlink to active environment (created by setup script)
+
+**Never commit `.env.staging` or `.env.production`!**
+
+---
+
+## Architecture References
+
+Before making architectural changes, review:
+- `./docs/Architecture.md` - System architecture overview
+- `./docs/Event-Partitioning.md` - Event sourcing and partitioning strategy
+- `./docs/PRD.md` - Product requirements and design decisions
+- `./docs/diagrams/*.puml` - Visual architecture diagrams
+
+---
+
+## Questions?
+
+If you're unsure about anything:
+- Check existing documentation in `./docs/`
+- Review similar implementations in the codebase
+- Open a new issue with the "question" label
+- Reach out to maintainers through project communication channels
+
+---
+
+## Recognition
+
+All contributors are valued and will be recognized in our project documentation. Thank you for helping make MeshHook better!
+
+---
+
+**Happy Contributing! π**
+
+*MeshHook β Mesh your webhooks. Orchestrate everything.*
+
+This guide is maintained by the MeshHook community. If you find areas for improvement, please submit a PR!
\ No newline at end of file
diff --git a/Darkmode.md b/Darkmode.md
new file mode 100644
index 0000000..0a8e1a4
--- /dev/null
+++ b/Darkmode.md
@@ -0,0 +1,16 @@
+# Dark Mode Implementation
+
+## Overview
+MeshHook supports dark mode with automatic persistence across sessions and devices.
+
+## Usage
+- Click the moon/sun icon in the header to toggle
+- Theme preference is saved locally and synced to your account
+
+## For Developers
+- Theme colors are defined in `static/styles/themes.css`
+- Theme state is managed in `src/lib/stores/theme.js`
+- Use CSS variables for all colors in components
+
+## CSS Variables
+See `static/styles/themes.css` for the complete list of theme variables.
\ No newline at end of file
diff --git a/DeploymentGuide.md b/DeploymentGuide.md
new file mode 100644
index 0000000..3bf90ed
--- /dev/null
+++ b/DeploymentGuide.md
@@ -0,0 +1,831 @@
+# π MeshHook Deployment Guide
+
+> Webhook-first, deterministic, Postgres-native workflow engine
+
+## π Quick Links
+
+- [π Prerequisites](#-prerequisites)
+- [β‘ Setup](#-setup)
+- [π§ Configuration](#-configuration)
+- [π Deploy](#-deploy)
+- [π Security](#-security)
+- [π Monitor](#-monitor)
+- [π Scale](#-scale)
+- [π Updates](#-updates)
+- [π Troubleshoot](#-troubleshoot)
+
+---
+
+## π Prerequisites
+
+| Component | Version |
+|-----------|---------|
+| π’ Node.js | 18.x+ |
+| πΎ RAM | 2 GB+ |
+| πΏ Storage | 10 GB SSD |
+
+**Required:**
+- β
Supabase account ([sign up](https://supabase.com))
+- β
Git access
+- β
Domain (production)
+
+---
+
+## β‘ Setup
+
+### 1οΈβ£ Clone & Install
+
+```bash
+git clone https://github.com/your-org/meshhook.git
+cd meshhook && npm install && npm run build
+```
+
+### 2οΈβ£ Create Supabase Project
+
+1. Go to [supabase.com](https://supabase.com) β **New Project**
+2. Wait 2-3 minutes for initialization
+3. Copy from **Settings β API**:
+ - `PROJECT_URL`
+ - `ANON_KEY`
+ - `SERVICE_ROLE_KEY`
+ - `DATABASE_URL`
+
+### 3οΈβ£ Apply Migrations
+
+```bash
+npx supabase link --project-ref your-project-ref
+npx supabase db push
+```
+
+β
**Database ready!**
+
+---
+
+## π§ Configuration
+
+### Create `.env`
+
+```bash
+cp .env.example .env
+```
+
+### Required Variables
+
+```env
+# π Application
+NODE_ENV=production
+PUBLIC_APP_URL=https://your-domain.com
+PORT=3000
+
+# ποΈ Supabase
+PUBLIC_SUPABASE_URL=https://xxxxx.supabase.co
+PUBLIC_SUPABASE_ANON_KEY=eyJhbGc...
+SUPABASE_SERVICE_ROLE_KEY=eyJhbGc...
+DATABASE_URL=postgresql://postgres:password@db.xxxxx.supabase.co:5432/postgres
+
+# π Security
+WEBHOOK_SECRET=generate-random-secret
+JWT_SECRET=generate-random-secret
+```
+
+### Generate Secrets
+
+```bash
+openssl rand -base64 32 # Run twice
+```
+
+### Optional Variables
+
+```env
+WEBHOOK_TIMEOUT_MS=30000
+WORKER_CONCURRENCY=10
+LOG_LEVEL=info
+RATE_LIMIT_ENABLED=true
+```
+
+---
+
+## π Deploy
+
+### β‘ Option 1: Vercel (Fastest)
+
+```bash
+npm install -g vercel
+vercel --prod
+```
+
+Add env vars in Vercel dashboard β Environment Variables
+
+β
Live at `https://your-project.vercel.app`
+
+---
+
+### π³ Option 2: Docker
+
+**`Dockerfile`:**
+```dockerfile
+FROM node:18-alpine AS builder
+WORKDIR /app
+COPY package*.json ./
+RUN npm ci
+COPY . .
+RUN npm run build
+
+FROM node:18-alpine
+WORKDIR /app
+RUN apk add --no-cache dumb-init
+COPY --from=builder /app/build ./build
+COPY --from=builder /app/package*.json ./
+RUN npm ci --production
+EXPOSE 3000
+ENTRYPOINT ["dumb-init", "--"]
+CMD ["node", "build"]
+```
+
+**`docker-compose.yml`:**
+```yaml
+version: '3.8'
+services:
+ app:
+ build: .
+ ports: ["3000:3000"]
+ env_file: .env
+ depends_on: [worker]
+ restart: unless-stopped
+ healthcheck:
+ test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
+ interval: 30s
+ timeout: 10s
+ retries: 3
+
+ worker:
+ build: .
+ command: node worker.js
+ env_file: .env
+ restart: unless-stopped
+
+ nginx:
+ image: nginx:alpine
+ ports: ["80:80", "443:443"]
+ volumes:
+ - ./nginx.conf:/etc/nginx/nginx.conf:ro
+ - ./certs:/etc/nginx/certs:ro
+ depends_on: [app]
+```
+
+**Deploy:**
+```bash
+docker-compose up -d
+docker-compose logs -f
+```
+
+β
Live at `http://localhost`
+
+---
+
+### π₯οΈ Option 3: Linux VPS
+
+```bash
+ssh user@your-server-ip
+
+# Install Node.js
+curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash -
+sudo apt install -y nodejs git
+
+# Clone & setup
+git clone https://github.com/your-org/meshhook.git /var/www/meshhook
+cd /var/www/meshhook
+npm install && npm run build
+
+# Install PM2
+sudo npm install -g pm2
+
+# Create ecosystem.config.js
+cat > ecosystem.config.js << 'EOF'
+module.exports = {
+ apps: [{
+ name: 'meshhook',
+ script: './build/index.js',
+ instances: 'max',
+ exec_mode: 'cluster',
+ env: { NODE_ENV: 'production' },
+ max_memory_restart: '1G'
+ }, {
+ name: 'meshhook-worker',
+ script: './worker.js',
+ instances: 1,
+ env: { NODE_ENV: 'production' }
+ }]
+};
+EOF
+
+# Start
+pm2 start ecosystem.config.js
+pm2 startup && pm2 save
+
+# Setup Nginx
+sudo apt install -y nginx
+
+sudo tee /etc/nginx/sites-available/meshhook << 'EOF'
+server {
+ listen 80;
+ server_name your-domain.com;
+ location / {
+ proxy_pass http://localhost:3000;
+ proxy_set_header Host $host;
+ }
+}
+EOF
+
+sudo ln -s /etc/nginx/sites-available/meshhook /etc/nginx/sites-enabled/
+sudo systemctl restart nginx
+```
+
+β
Live at `http://your-domain.com`
+
+---
+
+### βΈοΈ Option 4: Kubernetes
+
+**`k8s/namespace.yaml`:**
+```yaml
+apiVersion: v1
+kind: Namespace
+metadata:
+ name: meshhook
+```
+
+**`k8s/secrets.yaml`:**
+```yaml
+apiVersion: v1
+kind: Secret
+metadata:
+ name: meshhook-secrets
+ namespace: meshhook
+type: Opaque
+stringData:
+ DATABASE_URL: postgresql://postgres:password@db.xxxxx.supabase.co:5432/postgres
+ SUPABASE_SERVICE_ROLE_KEY: your-key
+ WEBHOOK_SECRET: your-secret
+ JWT_SECRET: your-jwt-secret
+```
+
+**`k8s/deployment.yaml`:**
+```yaml
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ name: meshhook-app
+ namespace: meshhook
+spec:
+ replicas: 3
+ selector:
+ matchLabels:
+ app: meshhook
+ template:
+ metadata:
+ labels:
+ app: meshhook
+ spec:
+ containers:
+ - name: meshhook
+ image: your-registry/meshhook:latest
+ ports: [{containerPort: 3000}]
+ env:
+ - name: NODE_ENV
+ value: "production"
+ envFrom:
+ - secretRef:
+ name: meshhook-secrets
+ resources:
+ requests: {memory: "512Mi", cpu: "250m"}
+ limits: {memory: "1Gi", cpu: "500m"}
+ livenessProbe:
+ httpGet: {path: /health, port: 3000}
+ initialDelaySeconds: 30
+ periodSeconds: 10
+ readinessProbe:
+ httpGet: {path: /ready, port: 3000}
+ initialDelaySeconds: 5
+ periodSeconds: 5
+
+---
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ name: meshhook-worker
+ namespace: meshhook
+spec:
+ replicas: 5
+ selector:
+ matchLabels:
+ app: meshhook-worker
+ template:
+ metadata:
+ labels:
+ app: meshhook-worker
+ spec:
+ containers:
+ - name: worker
+ image: your-registry/meshhook:latest
+ command: ["node", "worker.js"]
+ envFrom:
+ - secretRef:
+ name: meshhook-secrets
+ resources:
+ requests: {memory: "256Mi", cpu: "250m"}
+ limits: {memory: "512Mi", cpu: "500m"}
+
+---
+apiVersion: v1
+kind: Service
+metadata:
+ name: meshhook-service
+ namespace: meshhook
+spec:
+ selector:
+ app: meshhook
+ ports:
+ - port: 80
+ targetPort: 3000
+ type: LoadBalancer
+```
+
+**Deploy:**
+```bash
+kubectl apply -f k8s/namespace.yaml
+kubectl create secret generic meshhook-secrets --from-env-file=.env -n meshhook
+kubectl apply -f k8s/
+kubectl get pods -n meshhook
+```
+
+β
Live via LoadBalancer IP
+
+---
+
+## π Security
+
+### π Enable RLS
+
+```sql
+ALTER TABLE workflows ENABLE ROW LEVEL SECURITY;
+ALTER TABLE workflow_runs ENABLE ROW LEVEL SECURITY;
+ALTER TABLE workflow_logs ENABLE ROW LEVEL SECURITY;
+
+CREATE POLICY tenant_isolation ON workflows
+ FOR ALL USING (tenant_id = auth.uid());
+
+CREATE POLICY tenant_isolation_runs ON workflow_runs
+ FOR ALL USING (workflow_id IN (
+ SELECT id FROM workflows WHERE tenant_id = auth.uid()
+ ));
+```
+
+### βοΈ Webhook Verification
+
+```javascript
+// src/lib/webhook-security.js
+import crypto from 'crypto';
+
+export function verifyWebhookSignature(body, signature, secret) {
+ const expectedSignature = crypto
+ .createHmac('sha256', secret)
+ .update(body)
+ .digest('hex');
+
+ return crypto.timingSafeEqual(
+ Buffer.from(signature),
+ Buffer.from(expectedSignature)
+ );
+}
+
+// Usage
+export async function POST({ request }) {
+ const signature = request.headers.get('X-Webhook-Signature');
+ const body = await request.text();
+
+ if (!verifyWebhookSignature(body, signature, process.env.WEBHOOK_SECRET)) {
+ return new Response('Invalid', { status: 401 });
+ }
+ // Process...
+}
+```
+
+### π Secrets Management
+
+**AWS:**
+```bash
+aws secretsmanager create-secret --name meshhook/secret --secret-string "value"
+```
+
+**GCP:**
+```bash
+echo -n "value" | gcloud secrets create meshhook-secret --data-file=-
+```
+
+**Azure:**
+```bash
+az keyvault secret set --vault-name meshhook-vault --name secret --value "value"
+```
+
+### π HTTPS/SSL
+
+**Self-Hosted with Let's Encrypt:**
+```bash
+sudo apt install -y certbot python3-certbot-nginx
+sudo certbot certonly --nginx -d your-domain.com
+```
+
+**Update Nginx:**
+```nginx
+server {
+ listen 443 ssl http2;
+ 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;
+ ssl_protocols TLSv1.2 TLSv1.3;
+ location / {
+ proxy_pass http://localhost:3000;
+ }
+}
+server {
+ listen 80;
+ server_name your-domain.com;
+ return 301 https://$server_name$request_uri;
+}
+```
+
+### βοΈ Security Checklist
+
+- [ ] Env vars configured
+- [ ] WEBHOOK_SECRET strong (32+ chars)
+- [ ] JWT_SECRET unique
+- [ ] HTTPS enabled
+- [ ] RLS enabled
+- [ ] Service role key protected
+- [ ] Rate limiting on
+
+---
+
+## π Monitor
+
+### π₯ Health Checks
+
+```javascript
+// src/routes/health/+server.js
+export async function GET() {
+ return new Response(JSON.stringify({ status: 'healthy' }), {
+ headers: { 'Content-Type': 'application/json' }
+ });
+}
+
+// src/routes/ready/+server.js
+import { supabase } from '$lib/supabase';
+
+export async function GET() {
+ try {
+ await supabase.from('workflows').select('count').limit(1);
+ return new Response(JSON.stringify({ status: 'ready' }));
+ } catch (error) {
+ return new Response(JSON.stringify({ status: 'not ready' }), { status: 503 });
+ }
+}
+```
+
+### π‘ Real-Time Logs
+
+```javascript
+// src/lib/logging.js
+import { createClient } from '@supabase/supabase-js';
+
+const supabase = createClient(
+ process.env.PUBLIC_SUPABASE_URL,
+ process.env.SUPABASE_SERVICE_ROLE_KEY
+);
+
+export function subscribeToLogs(workflowId, callback) {
+ return supabase.channel(`logs:${workflowId}`)
+ .on('postgres_changes', {
+ event: 'INSERT',
+ schema: 'public',
+ table: 'workflow_logs',
+ filter: `workflow_id=eq.${workflowId}`
+ }, (payload) => callback(payload.new))
+ .subscribe();
+}
+
+export async function logEvent(workflowId, runId, message, level = 'info') {
+ await supabase.from('workflow_logs').insert({
+ workflow_id: workflowId,
+ run_id: runId,
+ message,
+ level,
+ created_at: new Date().toISOString()
+ });
+}
+```
+
+### π¨ Error Tracking (Sentry)
+
+```bash
+npm install @sentry/sveltekit
+```
+
+```javascript
+// src/hooks.server.js
+import * as Sentry from "@sentry/sveltekit";
+
+Sentry.init({
+ dsn: process.env.SENTRY_DSN,
+ tracesSampleRate: 0.1,
+ environment: process.env.NODE_ENV
+});
+```
+
+---
+
+## π Scale
+
+### β¬οΈ Horizontal Scaling
+
+```bash
+# Docker
+docker-compose up -d --scale worker=5
+
+# Kubernetes
+kubectl scale deployment meshhook-app --replicas=10 -n meshhook
+kubectl autoscale deployment meshhook-app --min=3 --max=20 --cpu-percent=70 -n meshhook
+
+# PM2
+pm2 start npm --name "meshhook" -- start -i max
+```
+
+### ποΈ Database Optimization
+
+```sql
+-- Create indexes
+CREATE INDEX idx_workflows_tenant_id ON workflows(tenant_id);
+CREATE INDEX idx_workflow_runs_workflow_id ON workflow_runs(workflow_id);
+CREATE INDEX idx_workflow_runs_status ON workflow_runs(status);
+CREATE INDEX idx_workflow_logs_run_id ON workflow_logs(run_id);
+CREATE INDEX idx_workflow_logs_created_at ON workflow_logs(created_at DESC);
+
+-- Composite index
+CREATE INDEX idx_runs_tenant_status
+ ON workflow_runs(tenant_id, status, created_at DESC);
+
+-- Analyze
+EXPLAIN ANALYZE SELECT * FROM workflow_runs WHERE tenant_id = 'xxx';
+```
+
+### π Connection Pooling
+
+```env
+DATABASE_POOL_SIZE=20
+DATABASE_POOL_TIMEOUT=10000
+DATABASE_IDLE_TIMEOUT=30000
+```
+
+---
+
+## π Updates
+
+### π¦ Update Process
+
+```bash
+# 1. Backup
+pg_dump $DATABASE_URL > backup-$(date +%Y%m%d).sql
+
+# 2. Update code
+git pull origin main
+npm install
+
+# 3. Migrations
+npx supabase db push
+
+# 4. Build & test
+npm run build && npm run test
+
+# 5. Deploy
+# Vercel
+vercel --prod
+
+# Docker
+docker-compose down && docker-compose build && docker-compose up -d
+
+# PM2
+pm2 restart meshhook
+
+# Kubernetes
+kubectl set image deployment/meshhook-app meshhook=your-registry/meshhook:v1.1.0 -n meshhook
+```
+
+### π Rollback
+
+```bash
+# Git
+git checkout HEAD~1 && npm run build
+
+# PM2
+pm2 restart meshhook
+
+# Docker
+docker-compose down && docker-compose up -d
+
+# Kubernetes
+kubectl rollout undo deployment/meshhook-app -n meshhook
+
+# Database
+pg_restore -h your-db.supabase.co -U postgres -d postgres backup.sql
+```
+
+---
+
+## π Troubleshoot
+
+### β Database Connection Failed
+
+```bash
+echo $DATABASE_URL
+psql $DATABASE_URL -c "SELECT 1"
+telnet db.xxxxx.supabase.co 5432
+```
+
+**Check:** Supabase dashboard β Settings β Project Status
+
+---
+
+### β Webhook Signature Fails
+
+```bash
+echo $WEBHOOK_SECRET
+curl -X POST http://localhost:3000/api/webhooks/test \
+ -H "X-Webhook-Signature: $(echo -n 'test' | openssl dgst -sha256 -hmac $WEBHOOK_SECRET)" \
+ -d '{"test":"data"}'
+```
+
+**Check:** Middleware order (raw body before parsing)
+
+---
+
+### β Workers Not Processing
+
+```bash
+ps aux | grep worker
+docker ps | grep worker
+kubectl get pods -n meshhook -l app=meshhook-worker
+
+# Logs
+pm2 logs meshhook-worker
+docker-compose logs meshhook-worker
+kubectl logs -f deployment/meshhook-worker -n meshhook
+
+# Queue depth
+psql $DATABASE_URL -c "SELECT COUNT(*) FROM workflow_runs WHERE status='pending'"
+
+# Restart
+pm2 restart meshhook-worker
+docker-compose restart worker
+kubectl rollout restart deployment/meshhook-worker -n meshhook
+
+# Increase in .env
+WORKER_CONCURRENCY=20
+```
+
+---
+
+### β High Memory
+
+```bash
+docker stats
+kubectl top pod
+
+# Increase limits
+NODE_OPTIONS="--max-old-space-size=2048" npm start
+```
+
+**Docker:** `memory: 2G`
+**K8s:** `memory: "2Gi"`
+
+---
+
+### β Slow Queries
+
+```sql
+SELECT query, calls, mean_time FROM pg_stat_statements
+ORDER BY mean_time DESC LIMIT 10;
+
+EXPLAIN ANALYZE SELECT * FROM workflow_runs WHERE tenant_id = 'xxx';
+
+CREATE INDEX idx_runs_tenant_status ON workflow_runs(tenant_id, status);
+
+VACUUM ANALYZE;
+```
+
+---
+
+### β SSL Certificate Error
+
+```bash
+openssl s_client -connect your-domain.com:443 -showcerts | grep dates
+sudo certbot renew --force-renewal
+kubectl create secret tls meshhook-tls --cert=cert.pem --key=key.pem -n meshhook
+```
+
+---
+
+### β No Real-Time Logs
+
+```javascript
+const channel = supabase.channel('test');
+channel.subscribe((status) => console.log(status)); // Should be: SUBSCRIBED
+```
+
+```sql
+ALTER TABLE workflow_logs REPLICA IDENTITY FULL;
+CREATE POLICY "Enable realtime" ON workflow_logs FOR SELECT USING (true);
+```
+
+**Check:** Dashboard β Settings β API β Realtime β ON
+
+---
+
+### β Build Fails
+
+```bash
+rm -rf node_modules .svelte-kit dist build
+npm cache clean --force
+npm ci
+npm run build
+npm run typecheck
+```
+
+---
+
+## β
Deployment Checklist
+
+### Before Deploy
+
+- [ ] Tests passing
+- [ ] Env vars documented
+- [ ] Migrations tested
+- [ ] RLS policies created
+- [ ] Indexes added
+- [ ] Secrets generated (32+ chars)
+- [ ] HTTPS configured
+- [ ] CORS defined
+
+### During Deploy
+
+- [ ] Database backup created
+- [ ] Team notified
+- [ ] Health checks pass
+
+### After Deploy
+
+- [ ] App running
+- [ ] Users accessing
+- [ ] Webhooks working
+- [ ] Real-time logs ok
+- [ ] Performance good
+- [ ] Monitoring alerts on
+
+---
+
+## π Quick Ref
+
+### Commands
+
+```bash
+npm run dev # Dev server
+npm run build # Build
+npm run preview # Preview build
+npx supabase db push # Migrate
+npx supabase status # Status
+
+vercel --prod # Deploy to Vercel
+docker-compose up -d # Deploy Docker
+pm2 restart meshhook # Restart PM2
+kubectl apply -f k8s/ # Deploy K8s
+```
+
+### Endpoints
+
+| Path | Purpose |
+|------|---------|
+| `GET /health` | Health check |
+| `GET /ready` | Ready check |
+| `GET /api/workflows` | List workflows |
+| `POST /api/workflows` | Create workflow |
+| `POST /api/webhooks/:id` | Receive webhook |
+| `GET /api/workflows/:id/runs` | Get runs |
+
+---
+
+π **Docs:** [docs.meshhook.io](https://docs.meshhook.io)
+π **Issues:** [GitHub](https://github.com/your-org/meshhook/issues)
+π¬ **Support:** [Community](https://meshhook.io/community)
+
+---
+
+**π You're ready to deploy MeshHook!**
\ No newline at end of file
diff --git a/apps/web/src/app.css b/apps/web/src/app.css
index 4cee0a3..0ed0ff3 100644
--- a/apps/web/src/app.css
+++ b/apps/web/src/app.css
@@ -1,3 +1,5 @@
+@import '/styles/themes.css';
+
:root {
--color-bg-0: rgb(202, 216, 228);
--color-bg-1: hsl(209, 36%, 86%);
diff --git a/apps/web/src/lib/components/Header.svelte b/apps/web/src/lib/components/Header.svelte
index edaf4d2..322bb7e 100644
--- a/apps/web/src/lib/components/Header.svelte
+++ b/apps/web/src/lib/components/Header.svelte
@@ -1,5 +1,6 @@
+
+
+
+
\ No newline at end of file
diff --git a/apps/web/src/lib/stores/themes.js b/apps/web/src/lib/stores/themes.js
new file mode 100644
index 0000000..441e118
--- /dev/null
+++ b/apps/web/src/lib/stores/themes.js
@@ -0,0 +1,57 @@
+// src/lib/stores/theme.js
+import { writable } from 'svelte/store';
+import { browser } from '$app/environment';
+
+const THEME_KEY = 'meshhook-theme';
+
+function getSystemTheme() {
+ if (!browser) return 'light';
+ return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
+}
+
+function createThemeStore() {
+ // Get theme: localStorage > system preference > light
+ const storedTheme = browser ? localStorage.getItem(THEME_KEY) : null;
+ const initialTheme = storedTheme || getSystemTheme();
+
+ const { subscribe, set, update } = writable(initialTheme);
+
+ function applyTheme(theme) {
+ if (browser) {
+ document.documentElement.setAttribute('data-theme', theme);
+ localStorage.setItem(THEME_KEY, theme);
+ }
+ }
+
+ if (browser) {
+ applyTheme(initialTheme);
+
+ // Listen for system theme changes
+ const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
+ mediaQuery.addEventListener('change', (e) => {
+ // Only update if user hasn't manually set a preference
+ if (!localStorage.getItem(THEME_KEY)) {
+ const newTheme = e.matches ? 'dark' : 'light';
+ set(newTheme);
+ applyTheme(newTheme);
+ }
+ });
+ }
+
+ return {
+ subscribe,
+ toggle: () => {
+ update(current => {
+ const newTheme = current === 'light' ? 'dark' : 'light';
+ applyTheme(newTheme);
+ return newTheme;
+ });
+ },
+ set: (theme) => {
+ set(theme);
+ applyTheme(theme);
+ }
+ };
+}
+
+export const theme = createThemeStore();
\ No newline at end of file
diff --git a/apps/web/src/routes/+layout.svelte b/apps/web/src/routes/+layout.svelte
index 8c66aae..4918b3e 100644
--- a/apps/web/src/routes/+layout.svelte
+++ b/apps/web/src/routes/+layout.svelte
@@ -14,5 +14,7 @@
\ No newline at end of file
diff --git a/apps/web/src/routes/api/user/theme/+server.js b/apps/web/src/routes/api/user/theme/+server.js
new file mode 100644
index 0000000..8a6c168
--- /dev/null
+++ b/apps/web/src/routes/api/user/theme/+server.js
@@ -0,0 +1,57 @@
+import { json } from '@sveltejs/kit';
+import { createServerSupabaseClient } from '$lib/supabase.js';
+
+export async function POST(event) {
+ const supabase = createServerSupabaseClient(event);
+
+ const { data: { user } } = await supabase.auth.getUser();
+
+ if (!user) {
+ return json({ error: 'Unauthorized' }, { status: 401 });
+ }
+
+ const { theme } = await event.request.json();
+
+ if (!theme || !['light', 'dark'].includes(theme)) {
+ return json({ error: 'Invalid theme' }, { status: 400 });
+ }
+
+ const { error } = await supabase
+ .from('user_settings')
+ .upsert({
+ user_id: user.id,
+ theme_preference: theme,
+ updated_at: new Date().toISOString()
+ }, {
+ onConflict: 'user_id'
+ });
+
+ if (error) {
+ console.error('Failed to update theme:', error);
+ return json({ error: 'Failed to update theme' }, { status: 500 });
+ }
+
+ return json({ success: true, theme });
+}
+
+export async function GET(event) {
+ const supabase = createServerSupabaseClient(event);
+
+ const { data: { user } } = await supabase.auth.getUser();
+
+ if (!user) {
+ return json({ theme: 'light' });
+ }
+
+ const { data, error } = await supabase
+ .from('user_settings')
+ .select('theme_preference')
+ .eq('user_id', user.id)
+ .single();
+
+ if (error || !data) {
+ return json({ theme: 'light' });
+ }
+
+ return json({ theme: data.theme_preference });
+}
\ No newline at end of file
diff --git a/apps/web/static/styles/themes.css b/apps/web/static/styles/themes.css
new file mode 100644
index 0000000..c52231a
--- /dev/null
+++ b/apps/web/static/styles/themes.css
@@ -0,0 +1,175 @@
+/* static/styles/themes.css */
+/* MeshHook Theme System - CSS Custom Properties */
+
+/* ============================================
+ ROOT - Default Light Theme
+ ============================================ */
+:root {
+ /* Primary Colors */
+ --color-primary: #3b82f6;
+ --color-primary-hover: #2563eb;
+ --color-primary-light: #dbeafe;
+ --color-primary-dark: #1e40af;
+
+ /* Background Colors */
+ --color-bg-primary: #ffffff;
+ --color-bg-secondary: #f9fafb;
+ --color-bg-tertiary: #f3f4f6;
+ --color-bg-hover: #f3f4f6;
+ --color-bg-active: #e5e7eb;
+
+ /* Text Colors */
+ --color-text-primary: #111827;
+ --color-text-secondary: #6b7280;
+ --color-text-tertiary: #9ca3af;
+ --color-text-inverse: #ffffff;
+ --color-text-muted: #6b7280;
+
+ /* Border Colors */
+ --color-border-primary: #e5e7eb;
+ --color-border-secondary: #d1d5db;
+ --color-border-focus: #3b82f6;
+ --color-border-hover: #9ca3af;
+
+ /* Status Colors */
+ --color-success: #10b981;
+ --color-success-bg: #d1fae5;
+ --color-warning: #f59e0b;
+ --color-warning-bg: #fef3c7;
+ --color-error: #ef4444;
+ --color-error-bg: #fee2e2;
+ --color-info: #3b82f6;
+ --color-info-bg: #dbeafe;
+
+ /* Component Specific */
+ --color-card-bg: #ffffff;
+ --color-card-border: #e5e7eb;
+ --color-card-shadow: rgba(0, 0, 0, 0.1);
+
+ --color-input-bg: #ffffff;
+ --color-input-border: #d1d5db;
+ --color-input-focus: #3b82f6;
+ --color-input-disabled: #f3f4f6;
+
+ --color-button-primary: #3b82f6;
+ --color-button-primary-hover: #2563eb;
+ --color-button-secondary: #6b7280;
+ --color-button-secondary-hover: #4b5563;
+
+ --color-nav-bg: #ffffff;
+ --color-nav-border: #e5e7eb;
+ --color-nav-text: #111827;
+ --color-nav-hover: #f3f4f6;
+
+ --color-sidebar-bg: #f9fafb;
+ --color-sidebar-border: #e5e7eb;
+ --color-sidebar-text: #374151;
+ --color-sidebar-hover: #e5e7eb;
+ --color-sidebar-active: #dbeafe;
+
+ --color-code-bg: #f3f4f6;
+ --color-code-text: #1f2937;
+
+ /* Shadows */
+ --shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
+ --shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
+ --shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1);
+ --shadow-xl: 0 20px 25px -5px rgba(0, 0, 0, 0.1);
+
+ /* Transitions */
+ --transition-fast: 150ms ease-in-out;
+ --transition-normal: 250ms ease-in-out;
+ --transition-slow: 350ms ease-in-out;
+}
+
+/* ============================================
+ DARK THEME
+ ============================================ */
+[data-theme="dark"] {
+ /* Primary Colors */
+ --color-primary: #60a5fa;
+ --color-primary-hover: #3b82f6;
+ --color-primary-light: #1e3a8a;
+ --color-primary-dark: #93c5fd;
+
+ /* Background Colors */
+ --color-bg-primary: #111827;
+ --color-bg-secondary: #1f2937;
+ --color-bg-tertiary: #374151;
+ --color-bg-hover: #374151;
+ --color-bg-active: #4b5563;
+
+ /* Text Colors */
+ --color-text-primary: #f9fafb;
+ --color-text-secondary: #d1d5db;
+ --color-text-tertiary: #9ca3af;
+ --color-text-inverse: #111827;
+ --color-text-muted: #9ca3af;
+
+ /* Border Colors */
+ --color-border-primary: #374151;
+ --color-border-secondary: #4b5563;
+ --color-border-focus: #60a5fa;
+ --color-border-hover: #6b7280;
+
+ /* Status Colors */
+ --color-success: #34d399;
+ --color-success-bg: #064e3b;
+ --color-warning: #fbbf24;
+ --color-warning-bg: #78350f;
+ --color-error: #f87171;
+ --color-error-bg: #7f1d1d;
+ --color-info: #60a5fa;
+ --color-info-bg: #1e3a8a;
+
+ /* Component Specific */
+ --color-card-bg: #1f2937;
+ --color-card-border: #374151;
+ --color-card-shadow: rgba(0, 0, 0, 0.3);
+
+ --color-input-bg: #1f2937;
+ --color-input-border: #4b5563;
+ --color-input-focus: #60a5fa;
+ --color-input-disabled: #374151;
+
+ --color-button-primary: #60a5fa;
+ --color-button-primary-hover: #3b82f6;
+ --color-button-secondary: #6b7280;
+ --color-button-secondary-hover: #9ca3af;
+
+ --color-nav-bg: #1f2937;
+ --color-nav-border: #374151;
+ --color-nav-text: #f9fafb;
+ --color-nav-hover: #374151;
+
+ --color-sidebar-bg: #111827;
+ --color-sidebar-border: #374151;
+ --color-sidebar-text: #d1d5db;
+ --color-sidebar-hover: #374151;
+ --color-sidebar-active: #1e3a8a;
+
+ --color-code-bg: #0f172a;
+ --color-code-text: #e2e8f0;
+
+ /* Shadows (darker in dark mode) */
+ --shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.3);
+ --shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.4);
+ --shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.5);
+ --shadow-xl: 0 20px 25px -5px rgba(0, 0, 0, 0.6);
+}
+
+/* ============================================
+ BASE STYLES - Apply theme colors
+ ============================================ */
+body {
+ background-color: var(--color-bg-primary);
+ color: var(--color-text-primary);
+ transition: background-color var(--transition-normal), color var(--transition-normal);
+}
+
+/* Smooth theme transitions for all themed elements */
+* {
+ transition: background-color var(--transition-fast),
+ border-color var(--transition-fast),
+ color var(--transition-fast);
+}
\ No newline at end of file
diff --git a/supabase/migrations/20250111000008_add_theme_preference.sql b/supabase/migrations/20250111000008_add_theme_preference.sql
new file mode 100644
index 0000000..0da7041
--- /dev/null
+++ b/supabase/migrations/20250111000008_add_theme_preference.sql
@@ -0,0 +1,49 @@
+-- Add theme_preference to user_settings table
+-- Create user_settings table if it doesn't exist
+CREATE TABLE IF NOT EXISTS user_settings (
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
+ user_id UUID REFERENCES auth.users(id) ON DELETE CASCADE UNIQUE NOT NULL,
+ theme_preference TEXT DEFAULT 'light' CHECK (theme_preference IN ('light', 'dark')),
+ created_at TIMESTAMPTZ DEFAULT NOW(),
+ updated_at TIMESTAMPTZ DEFAULT NOW()
+);
+
+-- Add theme_preference column if table already exists but column doesn't
+DO $$
+BEGIN
+ IF NOT EXISTS (
+ SELECT 1 FROM information_schema.columns
+ WHERE table_name = 'user_settings' AND column_name = 'theme_preference'
+ ) THEN
+ ALTER TABLE user_settings
+ ADD COLUMN theme_preference TEXT DEFAULT 'light'
+ CHECK (theme_preference IN ('light', 'dark'));
+ END IF;
+END $$;
+
+-- Create indexes for faster queries
+CREATE INDEX IF NOT EXISTS idx_user_settings_user_id ON user_settings(user_id);
+CREATE INDEX IF NOT EXISTS idx_user_settings_theme ON user_settings(theme_preference);
+
+-- Enable Row Level Security
+ALTER TABLE user_settings ENABLE ROW LEVEL SECURITY;
+
+-- Drop existing policies if they exist
+DROP POLICY IF EXISTS "Users can read own settings" ON user_settings;
+DROP POLICY IF EXISTS "Users can insert own settings" ON user_settings;
+DROP POLICY IF EXISTS "Users can update own settings" ON user_settings;
+
+-- Policy: Users can read their own settings
+CREATE POLICY "Users can read own settings"
+ ON user_settings FOR SELECT
+ USING (auth.uid() = user_id);
+
+-- Policy: Users can insert their own settings
+CREATE POLICY "Users can insert own settings"
+ ON user_settings FOR INSERT
+ WITH CHECK (auth.uid() = user_id);
+
+-- Policy: Users can update their own settings
+CREATE POLICY "Users can update own settings"
+ ON user_settings FOR UPDATE
+ USING (auth.uid() = user_id);
\ No newline at end of file