# For God so loved the world, that he gave his only begotten Son, that whosoever believeth in him should not perish, but have everlasting life. — John 3:16 (KJV)

# Project Excellence Guide

**Version:** 1.4

> *"Whatever you do, work at it with all your heart, as working for the Lord."* — Colossians 3:23

This guide outlines the features and standards every project should implement to serve users with excellence.

---

## CRITICAL: AI-Monitored Community Systems

> *"Listen to advice and accept instruction, that you may gain wisdom."* — Proverbs 19:20

**EVERY FaithStack project MUST implement these four AI-monitored systems:**

| System | Section | Purpose | AI Monitors |
|--------|---------|---------|-------------|
| **Feedback Balloon** | [17](#17-page-level-feedback-balloon) | Per-page quick feedback | Sentiment, bugs → escalates to tickets |
| **Support Tickets** | [18](#18-support-ticket-system) | Structured help requests | SLA violations → alerts human |
| **Community Help** | [19](#19-community-help-board) | Peer-to-peer Q&A | Unanswered → AI responds or escalates |
| **Testimonials (DB)** | [20](#20-database-driven-testimonials) | Social proof | NEVER hardcode testimonials |

**Quick Start Checklist:**

```markdown
## Community Systems Implementation Checklist

- [ ] FeedbackBalloonChirho.svelte component on all pages
- [ ] /api-chirho/feedback-chirho endpoint (KV + D1)
- [ ] /support-chirho ticket portal with SLA tracking
- [ ] /features-chirho voting board
- [ ] /community-chirho Q&A board
- [ ] Scheduled worker (every 5 min) for AI monitoring
- [ ] Daily digest email at 8am
- [ ] Admin dashboard for all systems
- [ ] testimonials_chirho table (never hardcode!)
```

**AI Monitoring Agent Prompt:** See Section 17.10 in orchestrator-chirho/AGENTS.md for the full AI agent prompt to copy into your project.

---

## 1. Required Legal Documents

Every project must have proper legal documentation in the footer of every page.

### Footer Links (Required)

Your footer MUST include links to:

| Document | Path | Description |
|----------|------|-------------|
| **Privacy Policy** | `/privacy-fe` | How you collect, use, and protect user data. GDPR/CCPA compliant. |
| **Terms of Service** | `/terms-fe` | Legal agreement between you and users. Liability limitations. |
| **Contact** | `/contact-fe` or `mailto:` | How users can reach you for support. |

### Footer Links (Recommended for Paid Products)

| Document | Path | Description |
|----------|------|-------------|
| **Refund Policy** | `/refunds-fe` | Clear refund terms. Required for app stores and payment processors. |
| **Cookie Policy** | `/cookies-fe` or in Privacy | EU/UK GDPR requirement. What cookies you use and why. |
| **Accessibility** | `/accessibility-fe` | WCAG 2.1 AA compliance statement. |

### Example Footer Structure

```html
<footer>
  <nav>
    <a href="/privacy-fe">Privacy Policy</a>
    <a href="/terms-fe">Terms of Service</a>
    <a href="/refunds-fe">Refund Policy</a>
    <a href="/contact-fe">Contact</a>
  </nav>
  <p>&copy; 2025 Your Company. All rights reserved.</p>
</footer>
```

---

## 2. User Feedback System

Every project needs a way to collect user feedback. This should be stored locally in your project's database, not sent externally.

### Requirements

1. **Feedback Widget** - A visible button or form on key pages
2. **Categories** - Allow users to categorize: Bug, Feature Request, General
3. **Rating** - Optional satisfaction rating (1-5 stars)
4. **Anonymous Option** - Let users submit without login if desired
5. **Public Toggle** - Option to make feedback publicly visible

### Database Schema

```sql
CREATE TABLE feedback_chirho (
  id_chirho TEXT PRIMARY KEY,
  type_chirho TEXT CHECK(type_chirho IN ('bug', 'feature', 'general')),
  subject_chirho TEXT NOT NULL,
  message_chirho TEXT NOT NULL,
  email_chirho TEXT,
  rating_chirho INTEGER CHECK(rating_chirho >= 1 AND rating_chirho <= 5),
  user_id_chirho TEXT,
  page_url_chirho TEXT,
  public_chirho INTEGER DEFAULT 0,
  interesting_context_and_headers_chirho TEXT,
  created_at_chirho INTEGER NOT NULL
);
```

### API Route

| Route | Method | Purpose |
|-------|--------|---------|
| `/api-fe/feedback-fe` | POST | Submit feedback |

### Implementation Notes

- Store feedback in YOUR project's D1/database
- Review feedback weekly
- Respond to critical bugs within 24 hours
- Feature requests inform your roadmap
- `interesting_context_and_headers_chirho` can store user agent, referrer, etc.

---

## 3. Feature Suggestion System

Allow users to suggest and vote on features. This builds community and guides development.

### Required Elements

1. **Suggestion Form** - Title, description, category
2. **Voting System** - Upvotes/downvotes on suggestions
3. **Status Labels** - Planned, In Progress, Completed, Declined
4. **Public Visibility** - Users can see others' suggestions
5. **Comment System** - Users can discuss suggestions

### Routes

| Route | Purpose |
|-------|---------|
| `/features-fe` | List all suggestions, sorted by votes |
| `/features-fe/new-fe` | Submit new suggestion |
| `/features-fe/:id` | View single suggestion with comments |

### Database Schema

```sql
CREATE TABLE feature_suggestions_chirho (
  id_chirho TEXT PRIMARY KEY,
  title_chirho TEXT NOT NULL,
  description_chirho TEXT,
  category_chirho TEXT,
  status_chirho TEXT DEFAULT 'pending',
  user_id_chirho TEXT NOT NULL,
  upvotes_chirho INTEGER DEFAULT 0,
  downvotes_chirho INTEGER DEFAULT 0,
  created_at_chirho INTEGER NOT NULL,
  updated_at_chirho INTEGER NOT NULL
);

CREATE TABLE feature_votes_chirho (
  suggestion_id_chirho TEXT NOT NULL,
  user_id_chirho TEXT NOT NULL,
  vote_chirho INTEGER CHECK(vote_chirho IN (-1, 1)),
  created_at_chirho INTEGER NOT NULL,
  PRIMARY KEY (suggestion_id_chirho, user_id_chirho)
);

CREATE TABLE feature_comments_chirho (
  id_chirho TEXT PRIMARY KEY,
  suggestion_id_chirho TEXT NOT NULL,
  user_id_chirho TEXT NOT NULL,
  content_chirho TEXT NOT NULL,
  created_at_chirho INTEGER NOT NULL,
  FOREIGN KEY (suggestion_id_chirho) REFERENCES feature_suggestions_chirho(id_chirho)
);
```

---

## 4. API Key Management

If your project exposes any API or integrations, provide a proper API key system.

### Requirements

1. **Key Generation** - Secure random tokens (32+ bytes)
2. **Key Display** - Show full key only once at creation
3. **Key Revocation** - Users can delete/rotate keys
4. **Rate Limiting** - Track usage per key
5. **Scopes** - Optional fine-grained permissions

### Key Format Recommendation

```
prefix_base64randomdata

Example: sk_live_7fK9xMq2nP4wL8vR3tY6...
```

Prefixes help identify key type:
- `sk_live_` - Live/production secret key
- `sk_test_` - Test/sandbox secret key
- `pk_live_` - Live publishable key (safe for frontend)

### Database Schema

```sql
CREATE TABLE api_keys_chirho (
  id_chirho TEXT PRIMARY KEY,
  user_id_chirho TEXT NOT NULL,
  key_hash_chirho TEXT NOT NULL,
  key_prefix_chirho TEXT NOT NULL,
  name_chirho TEXT,
  scopes_chirho TEXT,
  last_used_at_chirho INTEGER,
  expires_at_chirho INTEGER,
  revoked_at_chirho INTEGER,
  created_at_chirho INTEGER NOT NULL
);
```

### Security: API Key Hashing

Use SHA-256 hash applied 4 times:

```typescript
async function hashApiKeyChirho(keyChirho: string): Promise<string> {
  let hashChirho = keyChirho;
  for (let i = 0; i < 4; i++) {
    const encoderChirho = new TextEncoder();
    const dataChirho = encoderChirho.encode(hashChirho);
    const hashBufferChirho = await crypto.subtle.digest('SHA-256', dataChirho);
    const hashArrayChirho = Array.from(new Uint8Array(hashBufferChirho));
    hashChirho = hashArrayChirho.map(b => b.toString(16).padStart(2, '0')).join('');
  }
  return hashChirho;
}
```

### Security Notes

- **NEVER** store API keys in plaintext
- Hash with SHA-256 (4 iterations) for API keys
- Show full key only at creation time
- Implement rate limiting per key
- Log all API key usage for auditing

---

## 5. Security Requirements

### Password Hashing

Use **bcrypt** with 12 rounds for password hashing in Cloudflare Workers:

```typescript
import bcrypt from 'bcryptjs';

// Hash password
const hashChirho = await bcrypt.hash(passwordChirho, 12);

// Verify password
const validChirho = await bcrypt.compare(passwordChirho, hashChirho);
```

Note: Argon2id is not compatible with Cloudflare Workers runtime.

### Session Management

- Use secure, HTTP-only cookies
- Implement CSRF protection
- Set appropriate cookie expiration
- Use SameSite=Strict or Lax

### Required Security Headers

```typescript
const securityHeadersChirho = {
  'Strict-Transport-Security': 'max-age=31536000; includeSubDomains',
  'X-Content-Type-Options': 'nosniff',
  'X-Frame-Options': 'DENY',
  'X-XSS-Protection': '1; mode=block',
  'Referrer-Policy': 'strict-origin-when-cross-origin',
  'Content-Security-Policy': "default-src 'self'"
};
```

---

## 6. Admin Routes

Protected administrative routes should follow this pattern:

### Route Structure

| Route | Purpose |
|-------|---------|
| `/admin-fe` | Admin dashboard overview |
| `/admin-fe/users-fe` | User management |
| `/admin-fe/content-fe` | Content moderation |
| `/admin-fe/settings-fe` | System configuration |
| `/admin-fe/logs-fe` | Activity logs |

### Access Control

Implement role-based access:

```typescript
const ADMIN_ROLES_CHIRHO = ['admin', 'super_admin', 'moderator'];

async function requireAdminChirho(requestChirho: Request, roleChirho?: string) {
  const sessionChirho = await getSessionChirho(requestChirho);
  if (!sessionChirho || !ADMIN_ROLES_CHIRHO.includes(sessionChirho.roleChirho)) {
    throw redirect(302, '/login-fe?error=unauthorized');
  }
  if (roleChirho && sessionChirho.roleChirho !== roleChirho) {
    throw error(403, 'Insufficient permissions');
  }
}
```

---

## 7. Email System (Remail Integration)

If your project doesn't have a working email system, use the Remail API.

### Documentation

**Full API documentation:** https://remail-fe.perffection.com/docs-fe

### Setup

1. **Request a Platform API Key** - Contact the orchestrator admin to get a platform API key for your project
2. **Add to Environment** - Add the key to your project's secrets

```bash
# wrangler.toml secrets or .env
REMAIL_API_KEY_CHIRHO=rk_your_platform_key_here
REMAIL_ENDPOINT_CHIRHO=https://remail-fe.perffection.com
```

### Pricing & Limits

- **Credits:** 10,000 emails for $5 (never expires)
- **Rate Limit:** 100 emails/minute per API key
- **Max Recipients:** 1000 per request

See the full documentation at the link above for API usage examples and integration guides.

---

## 8. Compliance Standards

### GDPR Compliance (EU Users)

1. **Consent Banner** - Cookie consent before non-essential cookies
2. **Data Export** - Users can download their data (Article 20)
3. **Data Deletion** - Users can request account deletion (Article 17)
4. **Privacy Policy** - Clear explanation of data processing
5. **Lawful Basis** - Document legal basis for each data processing activity

### Data Export Endpoint

```
GET /api-fe/export-my-data-fe
Authorization: Bearer <token>
```

Returns: ZIP file with all user data in JSON format

### Data Deletion Endpoint

```
DELETE /api-fe/delete-my-account-fe
Authorization: Bearer <token>
```

Deletes: All user data within 30 days (or immediately)

---

## 9. AI Support Integration

Provide users with AI-powered support options.

### Recommended Setup

1. **Chat Widget** - Embedded AI chat for common questions
2. **Voice Support** - Phone/voice AI for complex issues
3. **Human Escalation** - Clear path to human support when needed

### Voice Support (ElevenLabs Agent AI)

For voice-enabled support agents:
- Use ElevenLabs Conversational AI (Agent AI)
- Integrate via webhook for real-time data access
- The agent can call your API endpoints during conversation
- Provide clear knowledge base
- Enable human escalation triggers
- Log conversations for quality assurance

### Webhook Integration

ElevenLabs Agent AI can call your backend during conversations:

```typescript
// /api-fe/elevenlabs-webhook-fe
export async function POST({ request }) {
  const dataChirho = await request.json();

  // Handle agent actions like looking up user data
  if (dataChirho.action === 'lookup_order') {
    const orderChirho = await getOrderChirho(dataChirho.orderId);
    return json({ orderChirho });
  }

  return json({ success: true });
}
```

---

## 10. Referral System

If implementing referrals or affiliate programs:

### Payout Delay

**IMPORTANT:** Implement a 2-week minimum delay before referral payouts.

Reasons:
- Prevents chargebacks from being paid out
- Prevents refund abuse
- Prevents fake account fraud
- Allows time to receive money to pay people with

### Database Schema

```sql
CREATE TABLE referral_payouts_chirho (
  id_chirho TEXT PRIMARY KEY,
  referrer_id_chirho TEXT NOT NULL,
  referred_id_chirho TEXT NOT NULL,
  amount_cents_chirho INTEGER NOT NULL,
  eligible_at_chirho INTEGER NOT NULL,
  paid_at_chirho INTEGER,
  status_chirho TEXT DEFAULT 'pending',
  created_at_chirho INTEGER NOT NULL
);
```

---

## 11. Coupon & Promotion System

Use Stripe's built-in coupon system for discounts. This integrates directly with Checkout and subscriptions.

### Stripe Concepts

| Concept | Description |
|---------|-------------|
| **Coupon** | The actual discount (e.g., 20% off, $10 off). Created in Stripe Dashboard or API. |
| **Promotion Code** | Customer-facing code that applies a coupon (e.g., \`WELCOME20-FE\`). What users type at checkout. |

### Creating Coupons (Stripe Dashboard)

1. Go to **Products > Coupons** in Stripe Dashboard
2. Click **+ New coupon**
3. Configure:
   - **Percentage off** or **Fixed amount**
   - **Duration:** Once, Repeating, or Forever (for subscriptions)
   - **Redemption limits:** Max total redemptions, first-time customers only
   - **Expiration date**

### Creating Promotion Codes

After creating a coupon, create promotion codes for it:

1. Click on the coupon in Stripe Dashboard
2. Click **+ New promotion code**
3. Set the **Code** (e.g., \`CHRISTMAS25-FE\`, \`LAUNCH50-FE\`)
4. Configure restrictions:
   - **First-time orders only**
   - **Minimum order amount**
   - **Specific customers**
   - **Expiration date**
   - **Maximum redemptions**

### Applying at Checkout

\`\`\`typescript
// SvelteKit example - pass promotion code to Stripe Checkout
const sessionChirho = await stripe.checkout.sessions.create({
  mode: 'subscription',
  line_items: [{ price: priceIdChirho, quantity: 1 }],
  success_url: \`\${originChirho}/success-fe?session_id={CHECKOUT_SESSION_ID}\`,
  cancel_url: \`\${originChirho}/pricing-fe\`,
  // Allow customers to enter promotion codes
  allow_promotion_codes: true,
  // OR apply a specific code automatically
  // discounts: [{ promotion_code: 'promo_xxxxx' }],
});
\`\`\`

### Recommended Promotion Code Strategy

| Code Pattern | Use Case | Example |
|--------------|----------|---------|
| \`WELCOME##-FE\` | New customer discount | \`WELCOME20-FE\` (20% off first purchase) |
| \`LAUNCH##-FE\` | Product launch | \`LAUNCH50-FE\` (50% off during launch) |
| \`FRIEND##-FE\` | Referral codes | \`FRIEND25-FE\` (25% off for referred users) |
| \`HOLIDAY##-FE\` | Seasonal promotions | \`CHRISTMAS30-FE\`, \`NEWYEAR25-FE\` |
| \`ANNUAL##-FE\` | Encourage annual plans | \`ANNUAL20-FE\` (20% off annual subscription) |

### Best Practices

1. **Always set expiration dates** - Avoid perpetual discounts
2. **Limit redemptions** - Set max uses to control costs
3. **Track performance** - Review coupon analytics in Stripe Dashboard
4. **First-time only for acquisition** - Use for new customer discounts
5. **Stackable vs exclusive** - Decide if codes can combine (default: no)

### Local Tracking (Optional)

If you need to track promotions locally for analytics:

\`\`\`sql
CREATE TABLE promotion_redemptions_chirho (
  id_chirho TEXT PRIMARY KEY,
  user_id_chirho TEXT NOT NULL,
  promotion_code_chirho TEXT NOT NULL,
  stripe_coupon_id_chirho TEXT NOT NULL,
  discount_amount_cents_chirho INTEGER,
  discount_percent_chirho INTEGER,
  order_id_chirho TEXT,
  created_at_chirho INTEGER NOT NULL
);
\`\`\`

### Stripe Documentation

**Full docs:** https://docs.stripe.com/billing/subscriptions/coupons

---

## 12. Marketing & Visibility

### ChristianHN Posting Guidelines

For faith-based projects, only post to ChristianHN:

1. **First Production Launch** - When you launch to public
2. **Major Version Releases** - v2.0, v3.0 etc (not minor updates)
3. **Significant Milestones** - Major features, pivots, open-sourcing

**DO NOT** post:
- Every update or patch
- Beta/alpha releases
- Minor feature additions
- Regular blog posts

---

## 13. Testing Requirements

### Minimum Coverage

- **Unit Tests:** 60% code coverage minimum
- **Integration Tests:** All critical user paths
- **E2E Tests:** Main user journeys

### Test Structure

```
tests_chirho/
  unit/           # Unit tests
  integration/    # API/service tests
  e2e/            # End-to-end browser tests
```

### Running Tests

```bash
bun test              # Run all tests
bun test:watch        # Watch mode
bun test:coverage     # Coverage report
```

---

## 14. Deployment Checklist

Before every deployment:

- [ ] All tests passing
- [ ] No TypeScript errors
- [ ] Environment variables set
- [ ] Database migrations ready
- [ ] Privacy/Terms pages exist
- [ ] Footer links working
- [ ] HTTPS enabled
- [ ] Security headers set
- [ ] Error tracking configured
- [ ] Backup strategy in place

---

## 15. Monitoring & Alerts

### Required Monitoring

1. **Uptime Monitoring** - Is the site accessible?
2. **Error Tracking** - JavaScript and server errors
3. **Performance** - Response times, Core Web Vitals
4. **SSL Expiry** - Certificate monitoring

### Alert Thresholds

| Metric | Warning | Critical |
|--------|---------|----------|
| Response Time | >500ms | >2000ms |
| Error Rate | >0.5% | >2% |
| Uptime | <99.5% | <99% |
| SSL Expiry | 30 days | 7 days |

---

## 16. REST API Standards for Website Builder Integration

Every product in the FaithStack ecosystem should expose REST APIs that can be consumed by website builders (Perffection, WordPress, Webflow, etc.) and AI agents.

### API Route Naming Convention

All API routes MUST use the `-chirho` suffix:

```typescript
// Core CRUD pattern
GET    /api-chirho/churches-chirho              // List resources
GET    /api-chirho/churches-chirho/:id-chirho   // Get single resource
POST   /api-chirho/churches-chirho              // Create resource
PATCH  /api-chirho/churches-chirho/:id-chirho   // Update resource
DELETE /api-chirho/churches-chirho/:id-chirho   // Delete resource

// Public embeddable endpoints (no auth required, rate limited)
GET    /api-chirho/embed-chirho/widget-chirho   // Get embeddable widget config
POST   /api-chirho/embed-chirho/action-chirho   // Handle widget actions
```

### Product-Specific API Requirements

| Product | Required Endpoints |
|---------|-------------------|
| **FaithCoin** | `/api-chirho/churches-chirho`, `/api-chirho/wallets-chirho`, `/api-chirho/transactions-chirho`, `/api-chirho/donations-chirho` |
| **KingdomInvest** | `/api-chirho/investments-chirho`, `/api-chirho/returns-chirho`, `/api-chirho/portfolio-chirho` |
| **Perffection** | `/api-chirho/sites-chirho`, `/api-chirho/templates-chirho`, `/api-chirho/deployments-chirho` |
| **SonshineCoders** | `/api-chirho/courses-chirho`, `/api-chirho/enrollments-chirho`, `/api-chirho/certificates-chirho` |
| **FaithMatch** | `/api-chirho/profiles-chirho`, `/api-chirho/matches-chirho`, `/api-chirho/messages-chirho` |
| **Koinonia** | `/api-chirho/groups-chirho`, `/api-chirho/events-chirho`, `/api-chirho/prayers-chirho` |
| **FaithStory** | `/api-chirho/testimonies-chirho`, `/api-chirho/books-chirho`, `/api-chirho/chapters-chirho` |
| **Manna** | `/api-chirho/transcriptions-chirho`, `/api-chirho/meetings-chirho`, `/api-chirho/notes-chirho` |
| **Sentraphi** | `/api-chirho/scan-chirho`, `/api-chirho/verify-chirho`, `/api-chirho/trust-score-chirho` |
| **OpenOrphanage** | `/api-chirho/orphanages-chirho`, `/api-chirho/donations-chirho`, `/api-chirho/reports-chirho` |

### OpenAPI Specification

Every project MUST have an OpenAPI spec at:

```
GET /api-chirho/openapi-chirho.yaml   # Or .json
```

### Embed Widget System

Products should support embeddable widgets for website builders:

```html
<!-- Example: Donation widget embed -->
<script
  src="https://faithcoin-chirho.workers.dev/embed-chirho/widget.js"
  data-church-id-chirho="abc123"
  data-theme-chirho="light"
  data-amount-chirho="suggested"
></script>
```

Widget endpoints:
| Endpoint | Description |
|----------|-------------|
| `/embed-chirho/widget.js` | JavaScript loader |
| `/embed-chirho/config-chirho/:id` | Widget configuration |
| `/embed-chirho/action-chirho` | Handle widget interactions |

### Response Format

All APIs should return consistent JSON:

```typescript
// Success response
{
  "data_chirho": { ... },
  "meta_chirho": {
    "page_chirho": 1,
    "per_page_chirho": 20,
    "total_chirho": 100
  }
}

// Error response
{
  "error_chirho": {
    "code_chirho": "VALIDATION_ERROR",
    "message_chirho": "Invalid input",
    "details_chirho": [...]
  }
}
```

---

## 17. Page-Level Feedback Balloon

Every page should have a floating feedback balloon that captures context-aware feedback with metadata.

### Requirements

1. **Visible on Every Page** - Floating button in corner (bottom-right recommended)
2. **Context Capture** - Automatically stores current page URL, viewport size, user agent
3. **User Association** - Links to logged-in user if available
4. **KV Storage** - Quick writes to KV for speed, batch sync to D1
5. **Admin Dashboard** - Review, respond, and manage all feedback

### Component Structure

\`\`\`svelte
<!-- FeedbackBalloonChirho.svelte -->
<script lang="ts">
  let isOpenChirho = $state(false);
  let typeChirho = $state<'bug' | 'feature' | 'general'>('general');
  let messageChirho = $state('');

  async function submitFeedbackChirho() {
    await fetch('/api-chirho/feedback-balloon-chirho', {
      method: 'POST',
      body: JSON.stringify({
        typeChirho,
        messageChirho,
        pageUrlChirho: window.location.href,
        screenWidthChirho: window.innerWidth,
        screenHeightChirho: window.innerHeight
      })
    });
  }
</script>

<button onclick={() => isOpenChirho = !isOpenChirho}
  class="fixed bottom-4 right-4 w-12 h-12 rounded-full bg-blue-600 text-white shadow-lg">
  💬
</button>
\`\`\`

### KV Storage Pattern

Store feedback in KV first for speed, then batch sync to D1:

\`\`\`typescript
// POST /api-chirho/feedback-balloon-chirho
export async function POST({ request, platform, locals }) {
  const bodyChirho = await request.json();
  const feedbackIdChirho = crypto.randomUUID();

  const feedbackChirho = {
    idChirho: feedbackIdChirho,
    typeChirho: bodyChirho.typeChirho,
    messageChirho: bodyChirho.messageChirho,
    pageUrlChirho: bodyChirho.pageUrlChirho,
    screenWidthChirho: bodyChirho.screenWidthChirho,
    screenHeightChirho: bodyChirho.screenHeightChirho,
    userIdChirho: locals.userChirho?.idChirho || null,
    userAgentChirho: request.headers.get('user-agent'),
    createdAtChirho: Date.now(),
    statusChirho: 'new'
  };

  // Store in KV for immediate write
  await platform.env.FEEDBACK_KV_CHIRHO.put(
    \`feedback:\${feedbackIdChirho}\`,
    JSON.stringify(feedbackChirho),
    { expirationTtl: 60 * 60 * 24 * 30 } // 30 days
  );

  // Add to pending list for D1 sync
  const pendingListChirho = await platform.env.FEEDBACK_KV_CHIRHO.get('pending_sync_chirho') || '[]';
  const pendingChirho = JSON.parse(pendingListChirho);
  pendingChirho.push(feedbackIdChirho);
  await platform.env.FEEDBACK_KV_CHIRHO.put('pending_sync_chirho', JSON.stringify(pendingChirho));

  return json({ successChirho: true, idChirho: feedbackIdChirho });
}
\`\`\`

### Admin Routes

| Route | Purpose |
|-------|---------|
| \`/admin-chirho/feedback-chirho\` | List all feedback with filters |
| \`/admin-chirho/feedback-chirho/:id\` | View single feedback with context |
| \`/api-chirho/feedback-chirho/:id/respond-chirho\` | Send response to user |
| \`/api-chirho/feedback-chirho/:id/status-chirho\` | Update status (new, in_progress, resolved, wont_fix) |

---

## 18. Support Ticket System

For products with paying customers, implement a proper support ticket system.

### Requirements

1. **Ticket Creation** - Users can create tickets with priority
2. **Ticket Tracking** - Unique ticket IDs, status updates
3. **Email Notifications** - Notify on updates (via 2SMTP)
4. **SLA Tracking** - Track response times per priority
5. **Admin Dashboard** - Manage, assign, respond to tickets

### Database Schema

\`\`\`sql
CREATE TABLE support_tickets_chirho (
  id_chirho TEXT PRIMARY KEY,
  ticket_number_chirho TEXT UNIQUE NOT NULL,
  user_id_chirho TEXT NOT NULL,
  subject_chirho TEXT NOT NULL,
  description_chirho TEXT NOT NULL,
  category_chirho TEXT CHECK(category_chirho IN ('billing', 'technical', 'account', 'feature', 'other')),
  priority_chirho TEXT DEFAULT 'normal' CHECK(priority_chirho IN ('low', 'normal', 'high', 'urgent')),
  status_chirho TEXT DEFAULT 'open' CHECK(status_chirho IN ('open', 'in_progress', 'waiting_customer', 'resolved', 'closed')),
  assigned_to_chirho TEXT,
  first_response_at_chirho INTEGER,
  resolved_at_chirho INTEGER,
  created_at_chirho INTEGER NOT NULL,
  updated_at_chirho INTEGER NOT NULL
);

CREATE TABLE ticket_messages_chirho (
  id_chirho TEXT PRIMARY KEY,
  ticket_id_chirho TEXT NOT NULL,
  sender_type_chirho TEXT CHECK(sender_type_chirho IN ('customer', 'support', 'system')),
  sender_id_chirho TEXT,
  message_chirho TEXT NOT NULL,
  attachments_chirho TEXT, -- JSON array of R2 URLs
  created_at_chirho INTEGER NOT NULL,
  FOREIGN KEY (ticket_id_chirho) REFERENCES support_tickets_chirho(id_chirho)
);

CREATE INDEX idx_tickets_user_chirho ON support_tickets_chirho(user_id_chirho);
CREATE INDEX idx_tickets_status_chirho ON support_tickets_chirho(status_chirho);
\`\`\`

### Routes

| Route | Purpose |
|-------|---------|
| \`/support-chirho\` | User's ticket list |
| \`/support-chirho/new-chirho\` | Create new ticket |
| \`/support-chirho/:id\` | View ticket conversation |
| \`/admin-chirho/tickets-chirho\` | Admin ticket queue |
| \`/admin-chirho/tickets-chirho/:id\` | Admin ticket detail |

### Ticket Number Format

\`\`\`typescript
// Format: PROJECT-YYYYMM-XXXXX
function generateTicketNumberChirho(projectPrefixChirho: string): string {
  const dateChirho = new Date();
  const yearMonthChirho = \`\${dateChirho.getFullYear()}\${String(dateChirho.getMonth() + 1).padStart(2, '0')}\`;
  const randomChirho = Math.random().toString(36).substring(2, 7).toUpperCase();
  return \`\${projectPrefixChirho}-\${yearMonthChirho}-\${randomChirho}\`;
}
// Example: SMTP-202601-A3B7K
\`\`\`

---

## 19. Community Help Board

Allow users to help each other, reducing support burden and building community.

### Requirements

1. **Question & Answer Format** - Users post questions, others answer
2. **Voting System** - Upvote helpful answers
3. **Accepted Answer** - Question author marks best answer
4. **Categories/Tags** - Organize by topic
5. **Search** - Full-text search for existing answers

### Database Schema

\`\`\`sql
CREATE TABLE community_questions_chirho (
  id_chirho TEXT PRIMARY KEY,
  user_id_chirho TEXT NOT NULL,
  title_chirho TEXT NOT NULL,
  body_chirho TEXT NOT NULL,
  tags_chirho TEXT, -- JSON array
  view_count_chirho INTEGER DEFAULT 0,
  answer_count_chirho INTEGER DEFAULT 0,
  accepted_answer_id_chirho TEXT,
  is_solved_chirho INTEGER DEFAULT 0,
  created_at_chirho INTEGER NOT NULL,
  updated_at_chirho INTEGER NOT NULL
);

CREATE TABLE community_answers_chirho (
  id_chirho TEXT PRIMARY KEY,
  question_id_chirho TEXT NOT NULL,
  user_id_chirho TEXT NOT NULL,
  body_chirho TEXT NOT NULL,
  upvotes_chirho INTEGER DEFAULT 0,
  is_accepted_chirho INTEGER DEFAULT 0,
  created_at_chirho INTEGER NOT NULL,
  updated_at_chirho INTEGER NOT NULL,
  FOREIGN KEY (question_id_chirho) REFERENCES community_questions_chirho(id_chirho)
);

CREATE TABLE community_votes_chirho (
  answer_id_chirho TEXT NOT NULL,
  user_id_chirho TEXT NOT NULL,
  vote_chirho INTEGER DEFAULT 1,
  created_at_chirho INTEGER NOT NULL,
  PRIMARY KEY (answer_id_chirho, user_id_chirho)
);

CREATE INDEX idx_questions_tags_chirho ON community_questions_chirho(tags_chirho);
CREATE INDEX idx_questions_solved_chirho ON community_questions_chirho(is_solved_chirho);
\`\`\`

### Routes

| Route | Purpose |
|-------|---------|
| \`/community-chirho\` | Question list with search |
| \`/community-chirho/ask-chirho\` | Create new question |
| \`/community-chirho/:id\` | View question and answers |
| \`/community-chirho/tags-chirho/:tag\` | Filter by tag |

---

## 20. Database-Driven Testimonials

Never hardcode testimonials. Store them in the database so they're verifiable and manageable.

### Why Database Testimonials?

1. **Integrity** - No fake testimonials
2. **Verifiable** - Linked to real users (with permission)
3. **Easy Updates** - Add/remove without code changes
4. **Admin Control** - Approve before displaying
5. **Analytics** - Track which testimonials convert

### Database Schema

\`\`\`sql
CREATE TABLE testimonials_chirho (
  id_chirho TEXT PRIMARY KEY,
  user_id_chirho TEXT, -- Null if external testimonial
  author_name_chirho TEXT NOT NULL,
  author_title_chirho TEXT, -- e.g., "Pastor, Grace Church"
  author_company_chirho TEXT,
  author_avatar_url_chirho TEXT,
  quote_chirho TEXT NOT NULL,
  rating_chirho INTEGER CHECK(rating_chirho >= 1 AND rating_chirho <= 5),
  source_chirho TEXT, -- 'app_review', 'email', 'interview', 'social'
  source_url_chirho TEXT, -- Link to original if applicable
  is_featured_chirho INTEGER DEFAULT 0,
  is_approved_chirho INTEGER DEFAULT 0,
  display_order_chirho INTEGER DEFAULT 0,
  page_location_chirho TEXT, -- 'homepage', 'pricing', 'features'
  created_at_chirho INTEGER NOT NULL
);

CREATE INDEX idx_testimonials_approved_chirho ON testimonials_chirho(is_approved_chirho);
CREATE INDEX idx_testimonials_featured_chirho ON testimonials_chirho(is_featured_chirho);
CREATE INDEX idx_testimonials_location_chirho ON testimonials_chirho(page_location_chirho);
\`\`\`

### Collection Workflow

1. **Request Permission** - After positive interaction, ask: "Can we quote you?"
2. **Capture Exact Quote** - Store their exact words
3. **Get Approval** - Show them the final version
4. **Link to User** - Associate with their account if they have one
5. **Admin Approval** - Review before displaying

### API Endpoints

\`\`\`typescript
// GET /api-chirho/testimonials-chirho?location=homepage&limit=3
// Returns approved testimonials for display

// POST /api-chirho/testimonials-chirho (admin only)
// Create new testimonial

// POST /api-chirho/testimonials-chirho/request-chirho
// Send testimonial request email to user
\`\`\`

### Component Usage

\`\`\`svelte
<script lang="ts">
  let { testimonials = [] }: { testimonials: TestimonialChirho[] } = $props();
</script>

{#if testimonials.length > 0}
  <section class="testimonials-chirho">
    <h2>What Our Users Say</h2>
    {#each testimonials as testimonialChirho}
      <blockquote>
        <p>"{testimonialChirho.quoteChirho}"</p>
        <footer>
          {#if testimonialChirho.authorAvatarUrlChirho}
            <img src={testimonialChirho.authorAvatarUrlChirho} alt={testimonialChirho.authorNameChirho} />
          {/if}
          <cite>
            {testimonialChirho.authorNameChirho}
            {#if testimonialChirho.authorTitleChirho}
              <span>{testimonialChirho.authorTitleChirho}</span>
            {/if}
          </cite>
        </footer>
      </blockquote>
    {/each}
  </section>
{:else}
  <!-- Show beta message or nothing until real testimonials exist -->
  <section class="beta-notice-chirho">
    <p>We're building in public. Be among the first to share your experience!</p>
  </section>
{/if}
\`\`\`

### Admin Routes

| Route | Purpose |
|-------|---------|
| \`/admin-chirho/testimonials-chirho\` | List all testimonials |
| \`/admin-chirho/testimonials-chirho/new-chirho\` | Add testimonial manually |
| \`/admin-chirho/testimonials-chirho/:id\` | Edit/approve testimonial |
| \`/admin-chirho/testimonials-chirho/requests-chirho\` | Pending testimonial requests |

---

## 21. Customer Satisfaction Surveys

Measure and improve customer satisfaction with structured surveys at key moments.

### Survey Types

| Type | Trigger | Question | Scale |
|------|---------|----------|-------|
| **CSAT** | After support ticket resolved | "How satisfied were you with this interaction?" | 1-5 stars |
| **NPS** | Monthly/quarterly email | "How likely are you to recommend us?" | 0-10 scale |
| **CES** | After key action | "How easy was it to [action]?" | 1-7 scale |
| **Exit Survey** | Account cancellation | "Why are you leaving?" | Multiple choice + text |

### Database Schema

\`\`\`sql
CREATE TABLE satisfaction_surveys_chirho (
  id_chirho TEXT PRIMARY KEY,
  survey_type_chirho TEXT NOT NULL, -- csat | nps | ces | exit | custom
  user_id_chirho TEXT,
  user_email_chirho TEXT,

  -- Scores
  score_chirho INTEGER, -- The numeric rating
  score_max_chirho INTEGER, -- Max possible (5, 10, 7)

  -- Context
  trigger_type_chirho TEXT, -- ticket_resolved | purchase | monthly | cancellation
  trigger_id_chirho TEXT, -- Related ticket/order ID
  page_url_chirho TEXT,

  -- Responses
  feedback_text_chirho TEXT, -- Optional free-text
  selected_reasons_chirho TEXT, -- JSON array for exit surveys

  -- AI Analysis
  ai_sentiment_chirho TEXT, -- positive | neutral | negative
  ai_categories_chirho TEXT, -- JSON array of detected topics
  ai_action_items_chirho TEXT, -- JSON array of suggested actions
  ai_added_to_kb_chirho INTEGER DEFAULT 0, -- 1 if added to knowledge base

  -- Follow-up
  follow_up_sent_chirho INTEGER DEFAULT 0,
  follow_up_response_chirho TEXT,

  created_at_chirho TEXT DEFAULT CURRENT_TIMESTAMP
);

CREATE INDEX idx_surveys_type_chirho ON satisfaction_surveys_chirho(survey_type_chirho);
CREATE INDEX idx_surveys_score_chirho ON satisfaction_surveys_chirho(score_chirho);
CREATE INDEX idx_surveys_user_chirho ON satisfaction_surveys_chirho(user_id_chirho);
\`\`\`

### NPS Categories

| Score | Category | Action |
|-------|----------|--------|
| 9-10 | Promoters | Request testimonial, referral program |
| 7-8 | Passives | Ask what would make it a 10 |
| 0-6 | Detractors | Immediate follow-up, escalate to human |

### Survey Triggers

\`\`\`typescript
// Trigger CSAT after ticket resolution
async function onTicketResolvedChirho(ticketChirho: TicketChirho, env: Env) {
  await env.SURVEY_KV.put(
    \`survey:csat:\${ticketChirho.id_chirho}\`,
    JSON.stringify({
      type: 'csat',
      user_email: ticketChirho.user_email_chirho,
      trigger_id: ticketChirho.id_chirho,
      send_after: Date.now() + (24 * 60 * 60 * 1000) // 24 hours later
    })
  );
}

// Trigger exit survey on cancellation
async function onSubscriptionCancelledChirho(userChirho: UserChirho, env: Env) {
  // Immediately show exit survey modal or send email
  await sendExitSurveyChirho(userChirho, env);
}
\`\`\`

### AI Analysis of Survey Responses

\`\`\`typescript
async function analyzeSurveyResponseChirho(surveyChirho: SurveyChirho, env: Env) {
  const analysisChirho = await env.AI.run('@cf/meta/llama-3-8b-instruct', {
    messages: [{
      role: 'user',
      content: \`Analyze this customer feedback:
Score: \${surveyChirho.score_chirho}/\${surveyChirho.score_max_chirho}
Feedback: \${surveyChirho.feedback_text_chirho}

Return JSON with:
1. sentiment: positive|neutral|negative
2. categories: array of topics (billing, features, performance, support, ux)
3. action_items: array of specific actionable improvements
4. add_to_kb: boolean - should this be added to knowledge base?\`
    }]
  });

  // Update survey with AI analysis
  await updateSurveyAnalysisChirho(surveyChirho.id_chirho, analysisChirho, env);

  // If valuable insight, add to knowledge base
  if (analysisChirho.add_to_kb) {
    await addToKnowledgeBaseChirho(surveyChirho, analysisChirho, env);
  }
}
\`\`\`

### Metrics Dashboard

Track these metrics monthly:

| Metric | Formula | Target |
|--------|---------|--------|
| NPS Score | % Promoters - % Detractors | > 50 |
| CSAT Average | Sum of scores / Count | > 4.0 |
| Response Rate | Surveys completed / Surveys sent | > 20% |
| Detractor Recovery | Detractors who became Promoters | > 10% |

---

## 22. Internal Knowledge Base for Support Agents

AI-powered knowledge base built from customer interactions, surveys, and resolved tickets.

### How It Works

1. **AI monitors** all customer interactions (feedback, tickets, surveys, Q&A)
2. **AI extracts** valuable insights, common issues, and solutions
3. **AI adds** entries to knowledge base with proper categorization
4. **Support agents** (human or AI) query knowledge base for answers
5. **AI learns** from successful resolutions and improves suggestions

### Database Schema

\`\`\`sql
CREATE TABLE knowledge_base_chirho (
  id_chirho TEXT PRIMARY KEY,

  -- Content
  title_chirho TEXT NOT NULL,
  content_chirho TEXT NOT NULL, -- Markdown supported
  summary_chirho TEXT, -- AI-generated short summary

  -- Classification
  category_chirho TEXT NOT NULL, -- billing | technical | feature | policy | how-to
  subcategory_chirho TEXT,
  tags_chirho TEXT, -- JSON array

  -- Source tracking (where this knowledge came from)
  source_type_chirho TEXT, -- ticket | survey | feedback | question | manual
  source_id_chirho TEXT, -- Original ticket/survey ID
  source_url_chirho TEXT,

  -- AI metadata
  ai_generated_chirho INTEGER DEFAULT 0, -- 1 if AI created this
  ai_confidence_chirho REAL, -- 0.0-1.0 confidence in accuracy
  ai_embeddings_chirho TEXT, -- Vector embeddings for semantic search

  -- Usage stats
  view_count_chirho INTEGER DEFAULT 0,
  helpful_count_chirho INTEGER DEFAULT 0,
  not_helpful_count_chirho INTEGER DEFAULT 0,
  used_in_responses_chirho INTEGER DEFAULT 0, -- Times AI used this to answer

  -- Lifecycle
  status_chirho TEXT DEFAULT 'draft', -- draft | published | archived
  approved_by_chirho TEXT, -- Human who approved (null if auto-approved)
  last_verified_chirho TEXT, -- When last checked for accuracy
  expires_at_chirho TEXT, -- For time-sensitive info

  created_at_chirho TEXT DEFAULT CURRENT_TIMESTAMP,
  updated_at_chirho TEXT DEFAULT CURRENT_TIMESTAMP
);

CREATE TABLE kb_article_relations_chirho (
  id_chirho TEXT PRIMARY KEY,
  article_id_chirho TEXT NOT NULL REFERENCES knowledge_base_chirho(id_chirho),
  related_article_id_chirho TEXT NOT NULL REFERENCES knowledge_base_chirho(id_chirho),
  relation_type_chirho TEXT, -- see_also | prerequisite | supersedes
  created_at_chirho TEXT DEFAULT CURRENT_TIMESTAMP
);

CREATE TABLE kb_search_logs_chirho (
  id_chirho TEXT PRIMARY KEY,
  query_chirho TEXT NOT NULL,
  results_count_chirho INTEGER,
  clicked_article_id_chirho TEXT,
  was_helpful_chirho INTEGER, -- User feedback after reading
  searcher_type_chirho TEXT, -- agent | ai | user
  created_at_chirho TEXT DEFAULT CURRENT_TIMESTAMP
);

CREATE INDEX idx_kb_category_chirho ON knowledge_base_chirho(category_chirho);
CREATE INDEX idx_kb_status_chirho ON knowledge_base_chirho(status_chirho);
CREATE INDEX idx_kb_source_chirho ON knowledge_base_chirho(source_type_chirho);
\`\`\`

### Auto-Population from Customer Interactions

\`\`\`typescript
// When a ticket is resolved successfully
async function onTicketResolvedChirho(ticketChirho: TicketChirho, env: Env) {
  // Only learn from tickets resolved quickly with high CSAT
  if (ticketChirho.resolution_time_chirho < 3600 && ticketChirho.csat_score_chirho >= 4) {
    const articleChirho = await env.AI.run('@cf/meta/llama-3-8b-instruct', {
      messages: [{
        role: 'user',
        content: \`Create a knowledge base article from this resolved support ticket:

ISSUE: \${ticketChirho.title_chirho}
DESCRIPTION: \${ticketChirho.description_chirho}
SOLUTION: \${ticketChirho.resolution_chirho}
CATEGORY: \${ticketChirho.category_chirho}

Return JSON with:
- title: Clear, searchable title
- content: Step-by-step solution in markdown
- summary: One sentence summary
- category: billing|technical|feature|policy|how-to
- tags: array of relevant keywords
- confidence: 0.0-1.0 how confident this is reusable\`
      }]
    });

    if (articleChirho.confidence > 0.7) {
      await createKbArticleChirho({
        ...articleChirho,
        source_type: 'ticket',
        source_id: ticketChirho.id_chirho,
        ai_generated: 1,
        status: articleChirho.confidence > 0.9 ? 'published' : 'draft'
      }, env);
    }
  }
}

// Learn from survey feedback
async function learnFromSurveyChirho(surveyChirho: SurveyChirho, analysisChirho: AnalysisChirho, env: Env) {
  // Extract actionable insights
  for (const actionItemChirho of analysisChirho.action_items) {
    // Check if we already have an article about this
    const existingChirho = await searchKbChirho(actionItemChirho, env);

    if (!existingChirho.length) {
      // Create new article about this issue
      await createKbArticleChirho({
        title: \`Customer Feedback: \${actionItemChirho}\`,
        content: \`## Customer Insight\n\n\${surveyChirho.feedback_text_chirho}\n\n## Action Required\n\n\${actionItemChirho}\`,
        category: analysisChirho.categories[0] || 'feedback',
        source_type: 'survey',
        source_id: surveyChirho.id_chirho,
        status: 'draft' // Human review required
      }, env);
    }
  }
}
\`\`\`

### AI Agent Knowledge Base Query

\`\`\`typescript
// When AI support agent needs to answer a question
async function queryKnowledgeBaseChirho(questionChirho: string, env: Env): Promise<KbResultChirho[]> {
  // 1. Semantic search using embeddings
  const embeddingsChirho = await getEmbeddingsChirho(questionChirho, env);

  // 2. Search published articles
  const resultsChirho = await env.DB.prepare(\`
    SELECT *,
      (helpful_count_chirho - not_helpful_count_chirho) as helpfulness_score_chirho
    FROM knowledge_base_chirho
    WHERE status_chirho = 'published'
    ORDER BY helpfulness_score_chirho DESC
    LIMIT 5
  \`).all();

  // 3. Log the search for improvement
  await logKbSearchChirho(questionChirho, resultsChirho, env);

  return resultsChirho;
}

// AI uses KB to craft response
async function craftResponseWithKbChirho(
  ticketChirho: TicketChirho,
  kbResultsChirho: KbResultChirho[],
  env: Env
): Promise<string> {
  const contextChirho = kbResultsChirho.map(r =>
    \`### \${r.title_chirho}\n\${r.content_chirho}\`
  ).join('\n\n');

  const responseChirho = await env.AI.run('@cf/meta/llama-3-8b-instruct', {
    messages: [{
      role: 'system',
      content: \`You are a helpful support agent. Use the following knowledge base articles to answer the customer's question. Cite the article if you use it.

KNOWLEDGE BASE:
\${contextChirho}\`
    }, {
      role: 'user',
      content: ticketChirho.description_chirho
    }]
  });

  // Track which articles were used
  for (const articleChirho of kbResultsChirho) {
    if (responseChirho.includes(articleChirho.title_chirho)) {
      await incrementKbUsageChirho(articleChirho.id_chirho, env);
    }
  }

  return responseChirho;
}
\`\`\`

### Knowledge Base Admin Routes

| Route | Purpose |
|-------|---------|
| \`/admin-chirho/kb-chirho\` | Browse all articles |
| \`/admin-chirho/kb-chirho/drafts-chirho\` | Review AI-generated drafts |
| \`/admin-chirho/kb-chirho/new-chirho\` | Create article manually |
| \`/admin-chirho/kb-chirho/:id\` | Edit/publish article |
| \`/admin-chirho/kb-chirho/analytics-chirho\` | Search patterns, popular articles |
| \`/admin-chirho/kb-chirho/gaps-chirho\` | Questions without KB matches |

### Knowledge Base Quality Metrics

| Metric | Description | Target |
|--------|-------------|--------|
| Coverage | % of tickets answered using KB | > 60% |
| Accuracy | % of KB answers rated helpful | > 80% |
| Freshness | % of articles verified in last 90 days | > 90% |
| Gap Rate | % of searches with no results | < 10% |

### Feedback Loop

\`\`\`
Customer Question → AI searches KB → Response sent
                                          ↓
                                   Customer rates helpful?
                                     ↙            ↘
                                  Yes              No
                                   ↓                ↓
                            Increment           Flag for review
                            helpful_count       Human improves article
                                                     ↓
                                              Improved article
                                              serves future customers
\`\`\`

---

## Summary Checklist

Use this checklist to verify your project meets all requirements:

### Legal & Compliance
- [ ] Privacy Policy page exists at `/privacy-fe`
- [ ] Terms of Service page exists at `/terms-fe`
- [ ] Contact method available at `/contact-fe`
- [ ] Cookie consent (if using cookies, EU users)
- [ ] GDPR data export available
- [ ] GDPR data deletion available

### User Features
- [ ] Feedback system implemented (`/api-fe/feedback-fe`)
- [ ] Feature suggestion system with comments
- [ ] API key management (if API exposed)

### Payments (if paid product)
- [ ] Stripe integration configured
- [ ] Promotion codes enabled at checkout (`allow_promotion_codes: true`)
- [ ] Launch coupon created (e.g., `LAUNCH50-FE`)

### Email
- [ ] Remail API configured (or custom SMTP)
- [ ] Transactional emails working
- [ ] Email templates created

### Security
- [ ] Passwords hashed with bcrypt (12 rounds)
- [ ] API keys hashed with SHA-256 (4x)
- [ ] Security headers configured
- [ ] HTTPS enforced
- [ ] Admin routes protected at `/admin-fe/*`

### Quality
- [ ] Tests written and passing
- [ ] Error tracking enabled
- [ ] Monitoring configured

### REST APIs (for ecosystem products)
- [ ] REST APIs exposed with `-chirho` suffix
- [ ] OpenAPI spec at `/api-chirho/openapi-chirho.yaml`
- [ ] Embed widget system for website builders
- [ ] Consistent JSON response format

---

## Changelog

### Version 1.3 (2025-12-31)
- Added REST API Standards for Website Builder Integration (section 16)
- API route naming conventions with `-chirho` suffix
- Product-specific API requirements table
- OpenAPI specification requirements
- Embed widget system patterns
- Consistent JSON response format

### Version 1.2 (2025-12-27)
- Added Coupon & Promotion System using Stripe (section 11)
- Promotion codes, checkout integration, best practices

### Version 1.1 (2025-12-27)
- Simplified Remail documentation - now points to official docs
- Platform API key model for email integration

### Version 1.0 (2025-12-27)
- Initial release
- Legal documents with `-fe` route pattern
- User feedback system with extended schema
- Feature suggestion system with comments
- API key management with SHA-256 hashing
- Remail email integration
- ElevenLabs Agent AI integration with webhooks
- Referral system with payout delay reasoning
- Admin routes with `-fe` pattern

---

> *"Whatever you do, do it all for the glory of God."* — 1 Corinthians 10:31

**JESUS CHRIST IS LORD**
