# BrandExplode — Product Specification
**Domain:** brandexplode.com  
**Version:** 1.1  
**Last Updated:** May 2026  
**Status:** Active Development — Phase 2 in progress

---

## 1. Vision

BrandExplode is an AI-powered personal brand automation platform that helps professionals, entrepreneurs, and agencies consistently publish high-quality content on LinkedIn, Twitter/X, and Facebook Pages — without manual effort.

The system generates multiple post variations, lets the user review and approve content through a clean web interface, publishes automatically, tracks analytics, and learns from user feedback to improve over time.

**Core Value Proposition:**
- AI generates posts → User approves → System publishes → Analytics tracked → AI improves

---

## 2. Target Users

- Entrepreneurs and founders building personal brands
- Agency owners managing client social media
- Consultants and coaches wanting consistent LinkedIn presence
- Panalinks clients (white-label opportunity)

---

## 3. Tech Stack

| Layer | Technology |
|-------|-----------|
| Backend | PHP 8.2+ |
| Database | SQLite |
| Frontend | Alpine.js + Tailwind CSS |
| Automation | Cron / PHP CLI |
| AI | OpenAI GPT-4o-mini |
| LinkedIn | LinkedIn REST API v2 (direct) |
| Twitter | Twitter/X API v2 |
| Facebook | Meta Graph API (Pages only) |
| Hosting | VPS (existing Panalinks infrastructure) |
| Deployment | cPanel/WHM + Git (app.brandexplode.com) |
| Version Control | Git + GitHub |
| CLI Coding | Claude Code |

---

## 4. Feature List

### 4.1 Content Generation
- Day-based prompt templates (e.g. Mon = News, Wed = Marketing, Fri = Productivity)
- Default system prompt per user/workspace
- Custom one-off prompts
- URL ingestion — paste any URL, AI reads and repurposes content
- Thread repurposing — HackerNews, Reddit, Twitter/X threads
- Series mode — generate X posts as a connected series
- Count selector — generate 1–10 posts per run (default 3)
- Post variations — Hook-focused, Story-focused, Data-focused styles
- AI image generation — DALL-E 3 generates a relevant image alongside each post
- Image prompt auto-derived from post content
- User can accept or reject the image independently of the post

### 4.2 Content Management
- Full-page post preview (not grid)
- Card view with full text visible
- Approve / Reject with mandatory Reason field
- Edit post before approving
- "Are you sure?" confirmation before publishing
- Status workflow: Draft → Approved → Published / Rejected
- Post cards show generated image thumbnail if available
- Post detail shows full image with "Include Image" / "Remove Image" toggle
- Image stored locally in /storage/images/{post_id}.png

### 4.3 Publishing
- LinkedIn personal profile posting (direct API)
- Twitter/X posting (Phase 3)
- Facebook Pages posting (Phase 3)
- Scheduled publishing (post at specific time)
- Immediate publishing option
- Duplicate detection — prevent same content posting twice
- User selects day of week + time for automatic posting
- User timezone stored in settings; all times stored in UTC and displayed in local timezone
- On approval, user can publish immediately, schedule for a specific date + time, or add to queue
- Posting schedule slots (e.g. Mon 9am, Wed 11am, Fri 3pm)
- Queue auto-fills the next available slot based on posting schedule

### 4.4 Prompt Management
- Prompt template library (CRUD)
- Day-of-week assignment
- System prompt + User prompt separately editable
- Preview what a prompt will generate
- Import/export prompts

### 4.5 Analytics
- Views / Impressions
- Likes / Reactions
- Comments
- Shares / Reposts
- Engagement Rate (calculated)
- Reach
- Scoring formula (configurable weights)
- Top performing posts dashboard
- Trend charts per platform
- Fetched automatically via scheduled PHP cron job

### 4.6 AI Learning Loop
- Rejection reasons stored per post
- Post scores stored after analytics fetch
- Rejection history passed as context to AI on next generation
- High-scoring post patterns surfaced to AI
- "Learn from my best posts" feature — AI analyses top 10 posts and extracts patterns

### 4.7 Settings
- Core idea / brand positioning statement
- Default system prompt
- Platform API credentials (LinkedIn, Twitter, Facebook)
- OpenAI API key
- User timezone
- Posting schedule preferences
- Scoring formula weights

### 4.8 Authentication
- Single user (personal use) — simple password login
- Multi-user (agency use) — user + workspace model (Phase 4)
- Session-based auth with PHP

### 4.9 Image Management
- Images generated via DALL-E 3 (1024x1024)
- Stored in /storage/images/ directory
- Downloaded from OpenAI URL and saved locally (OpenAI URLs expire after 1 hour)
- LinkedIn posts with images use multipart upload API (different from text-only)
- User can regenerate image independently with one click
- Phase 2 deliverable

---

## 5. Database Schema (SQLite)

### 5.1 `settings`
```sql
CREATE TABLE settings (
    id INTEGER PRIMARY KEY,
    key TEXT UNIQUE NOT NULL,
    value TEXT,
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
    updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
```
Keys include: `core_idea`, `default_system_prompt`, `linkedin_person_id`, `linkedin_client_id`, `linkedin_client_secret`, `linkedin_access_token`, `openai_api_key`, `user_timezone`, `posting_schedule`, `scoring_weights`

---

### 5.2 `prompt_templates`
```sql
CREATE TABLE prompt_templates (
    id INTEGER PRIMARY KEY,
    name TEXT NOT NULL,
    day_of_week TEXT, -- 'monday','wednesday','friday','any'
    content_type TEXT, -- 'standard','news','marketing','productivity','series','url_repurpose'
    system_prompt TEXT NOT NULL,
    user_prompt TEXT NOT NULL,
    post_count INTEGER DEFAULT 3,
    is_default INTEGER DEFAULT 0,
    is_active INTEGER DEFAULT 1,
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
    updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
```

---

### 5.3 `posts`
```sql
CREATE TABLE posts (
    id INTEGER PRIMARY KEY,
    title TEXT,
    content_raw TEXT NOT NULL,
    content_clean TEXT,
    platform TEXT DEFAULT 'linkedin', -- 'linkedin','twitter','facebook'
    status TEXT DEFAULT 'draft', -- 'draft','approved','published','rejected'
    prompt_template_id INTEGER REFERENCES prompt_templates(id),
    variation_style TEXT, -- 'hook','story','data'
    source_url TEXT, -- if generated from URL
    series_id TEXT, -- UUID linking series posts
    series_position INTEGER,
    rejection_reason TEXT,
    approved_at DATETIME,
    published_at DATETIME,
    scheduled_for DATETIME,
    linkedin_post_urn TEXT, -- returned by LinkedIn API after publish
    image_path TEXT, -- local path to generated image
    image_url TEXT, -- public URL for the image
    include_image INTEGER DEFAULT 0, -- 1 = attach image when publishing
    score REAL DEFAULT 0,
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
    updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,
    -- Phase 2 additions:
    ai_provider TEXT DEFAULT 'openai',
    ai_model TEXT DEFAULT 'gpt-4o-mini'
);
```

---

### 5.4 `post_analytics`
```sql
CREATE TABLE post_analytics (
    id INTEGER PRIMARY KEY,
    post_id INTEGER NOT NULL REFERENCES posts(id),
    platform TEXT DEFAULT 'linkedin',
    impressions INTEGER DEFAULT 0,
    views INTEGER DEFAULT 0,
    likes INTEGER DEFAULT 0,
    comments INTEGER DEFAULT 0,
    shares INTEGER DEFAULT 0,
    clicks INTEGER DEFAULT 0,
    engagement_rate REAL DEFAULT 0,
    reach INTEGER DEFAULT 0,
    fetched_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
```

---

### 5.5 `users`
```sql
CREATE TABLE users (
    id INTEGER PRIMARY KEY,
    name TEXT NOT NULL,
    email TEXT UNIQUE NOT NULL,
    password_hash TEXT NOT NULL,
    role TEXT DEFAULT 'admin', -- 'admin','editor'
    is_active INTEGER DEFAULT 1,
    last_login DATETIME,
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
    -- Phase 2 additions:
    remember_token TEXT,
    remember_token_expires DATETIME,
    is_super_admin INTEGER DEFAULT 0
);
```

---

### 5.6 `activity_log`
```sql
CREATE TABLE activity_log (
    id INTEGER PRIMARY KEY,
    user_id INTEGER REFERENCES users(id),
    action TEXT NOT NULL, -- 'post_approved','post_rejected','post_published' etc
    entity_type TEXT, -- 'post','prompt','setting'
    entity_id INTEGER,
    metadata TEXT, -- JSON string with extra info
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
```

---

### 5.7 `workspaces` (Phase 2 additions)
```sql
-- Columns added to existing workspaces table:
plan TEXT DEFAULT 'free',
billing_email TEXT,
openai_mode TEXT DEFAULT 'byok',
tokens_used_month INTEGER DEFAULT 0,
tokens_reset_at DATETIME
```

---

### 5.8 `workspace_users` (Phase 2, new)
```sql
CREATE TABLE workspace_users (
    workspace_id INTEGER NOT NULL REFERENCES workspaces(id),
    user_id INTEGER NOT NULL REFERENCES users(id),
    role TEXT DEFAULT 'editor', -- 'admin','editor'
    PRIMARY KEY (workspace_id, user_id)
);
```

---

### 5.9 `platform_settings` (Phase 2, new)
```sql
CREATE TABLE platform_settings (
    key TEXT PRIMARY KEY,
    value TEXT
);
```

---

## 6. PHP API Endpoints

All endpoints return JSON. Auth via session cookie.

### Posts
```
GET    /api/posts               List posts (filter by status, platform)
GET    /api/posts/{id}          Get single post with analytics
POST   /api/posts               Create post manually
PATCH  /api/posts/{id}          Update post (edit content, status)
DELETE /api/posts/{id}          Delete post
POST   /api/posts/{id}/approve  Approve post
POST   /api/posts/{id}/reject   Reject post with reason
POST   /api/posts/{id}/publish  Trigger immediate publish
```

### Prompt Templates
```
GET    /api/prompts             List all prompt templates
GET    /api/prompts/{id}        Get single template
POST   /api/prompts             Create template
PATCH  /api/prompts/{id}        Update template
DELETE /api/prompts/{id}        Delete template
POST   /api/prompts/{id}/test   Preview generation (calls OpenAI)
```

### Analytics
```
GET    /api/analytics           Dashboard summary stats
GET    /api/analytics/{post_id} Stats for single post
POST   /api/analytics/fetch     Trigger manual analytics fetch
```

### Settings
```
GET    /api/settings            Get all settings
PATCH  /api/settings            Update settings
POST   /api/settings/test-linkedin  Test LinkedIn connection
POST   /api/settings/test-openai    Test OpenAI connection
```

### Auth
```
POST   /auth/login              Login
POST   /auth/logout             Logout
GET    /auth/me                 Current user
```

---

## 7. UI Pages

### 7.1 Dashboard (`/`)
- Stats summary: Total posts, Published this week, Avg engagement
- Quick actions: Generate Posts, Review Drafts
- Recent activity feed
- Top performing post preview

### 7.2 Posts — Review Queue (`/posts`)
- Card layout (not grid) — full text visible per card
- Filter tabs: All / Drafts / Approved / Published / Rejected
- Per card: Post text, Platform badge, Date, Approve button, Reject button, Edit button
- Approve triggers "Are you sure?" modal
- Reject opens reason input modal
- Mobile-friendly swipe actions (Alpine.js)

### 7.3 Post Detail (`/posts/{id}`)
- Full post text (formatted)
- Platform preview (how it looks on LinkedIn)
- Analytics section (if published)
- Edit in place
- Status history timeline
- Rejection reason (if rejected)

### 7.4 Generate Posts (`/generate`)
- Select prompt template OR write custom prompt
- Paste URL option (with fetch + preview)
- Select platform
- Select count (1–10)
- Series toggle
- Generate button
- Preview generated posts before saving to DB

### 7.5 Prompt Templates (`/prompts`)
- List of all templates
- Day-of-week assignment display
- Edit / Delete / Duplicate
- Test button — generates sample post
- Create new template form

### 7.6 Analytics Dashboard (`/analytics`)
- Line charts: Impressions over time
- Bar charts: Engagement by post
- Top 10 posts by score
- Platform comparison (when multi-platform added)
- Date range filter

### 7.7 Settings (`/settings`)
- Core idea / positioning
- Default prompts
- API credentials (masked)
- Timezone selector (searchable)
- Posting schedule builder (add/remove day+time slots)
- Scoring formula weights
- Test connection buttons

### 7.8 Login (`/login`)
- Simple email + password
- Remember me
- Mobile-friendly

---

## 8. Scoring Formula

Default formula (weights configurable in settings):

```
score = (impressions * 0.1) 
      + (likes * 2.0) 
      + (comments * 3.0) 
      + (shares * 4.0) 
      + (clicks * 1.5)
```

Normalised to 0–100 scale based on your own post history.

Labels:
- 0–30: Low
- 31–60: Average
- 61–80: Good
- 81–100: Viral

---

## 9. Cron Jobs

- Scheduled posting handled by a native PHP CLI script (cron job)
- Post generation triggered directly from the UI via OpenAI API
- No webhook architecture needed
- `php cron/process_scheduled_posts.php` runs every 5 minutes
- All scheduling is driven by settings and database state in PHP

---

## 10. Build Phases

### Phase 1 — Core Foundation ✅ COMPLETE

**Goal:** Replace Notion with SQLite, working end-to-end LinkedIn pipeline

**Delivered:**
- SQLite database setup + migrations
- PHP API (posts CRUD + scheduling + publish queue endpoints)
- Basic UI: Login, Post review queue, Post detail
- Prompt template storage (hardcoded defaults initially)
- Native PHP cron job for scheduled posting
- "Are you sure?" confirmation modal
- Basic authentication
- Multi-workspace architecture with workspace_users
- LinkedIn OAuth 2.0 (connect, callback, disconnect)
- OpenAI GPT-4o-mini post generation
- Activity log page
- Mobile responsive with hamburger menu
- Deployed live at app.brandexplode.com

---

### Phase 2 — Intelligence Layer 🔄 IN PROGRESS

**Goal:** Prompt management + AI learning loop

**Completed so far:**
- Cron job: daily auto-generation at 9am IST
- Cron job: scheduled publish every 5 minutes
- Prompt Templates CRUD UI with day-based templates
- Default prompt seeder (Mon–Fri templates)
- Generate page: 3 tabs (Default / Quick Topic / From URL)
- URL ingestion with paste-text fallback
- Post IDs display (LI-00053 format)
- Session persistence (8hr default + Remember Me 30 days)
- Auto-generate toggle in Settings
- Delete post button (draft + rejected)
- LinkedIn publish success modal
- Activity page with timeline

**Remaining:**
- List / Card / Full view toggle on Posts page
- Pagination on Posts page
- Prompt IDs (PR-00001 format)
- Editable Quick Topic prompts
- Scheduling UI (Buffer-style datetime picker)
- AI Learning Loop (rejection reasons fed back to AI context)
- DALL-E 3 image generation

---

### Phase 3 — Multi-Platform
**Goal:** Twitter/X and Facebook Pages

**Deliverables:**
- Twitter API integration
- Facebook Pages API integration
- Platform selector in UI
- Per-platform content length limits
- Platform preview in post detail

**Tests:**
- Post to Twitter → appears on profile
- Post to Facebook Page → appears on page
- LinkedIn post unaffected by Twitter/Facebook additions

---

### Phase 4 — Analytics Dashboard + SaaS Prep
**Goal:** Full analytics + multi-user ready

**Deliverables:**
- Analytics dashboard with charts (Chart.js)
- Top posts leaderboard
- Multi-user auth (workspace model)
- White-label settings (logo, brand name)
- Export posts to CSV

**Tests:**
- Charts render correctly on mobile
- Multi-user: User A cannot see User B posts
- Export CSV contains all published posts with analytics

---

## 11. Testing Strategy

### Unit Tests (PHPUnit)
- Content cleaning functions (strip markdown, emojis, fix newlines)
- Scoring formula calculations
- Prompt template rendering with variables
- SQLite CRUD operations

### Integration Tests
- UI triggers post generation directly via OpenAI API and writes to SQLite
- UI approve → PHP publish flow → LinkedIn API → status update
- Analytics fetch → score calculation → DB update

### Manual QA Checklist (per phase)
- [ ] Generate posts produces correct count
- [ ] All posts appear in review queue
- [ ] Approve flow publishes correctly
- [ ] Reject stores reason
- [ ] "Are you sure?" modal works
- [ ] Mobile layout renders correctly (375px viewport)
- [ ] Login/logout session works
- [ ] API credentials masked in UI

### Regression Tests (after each phase)
- Re-run Phase 1 QA checklist after Phase 2 is built
- Re-run Phase 1+2 checklist after Phase 3 is built

---

## 12. File Structure

```
brandexplode/
├── api/
│   ├── posts.php
│   ├── prompts.php
│   ├── analytics.php
│   ├── settings.php
│   ├── generate.php
│   └── auth.php
├── cron/
│   ├── generate_posts.php
│   ├── publish_scheduled.php
│   └── README_CRON.md
├── db/
│   ├── schema.sql
│   ├── bootstrap.php
│   └── migrations/
│       ├── add_ai_provider_to_posts.php
│       ├── add_remember_token.php
│       ├── create_admin.php
│       └── seed_default_prompts.php
├── lib/
│   ├── Auth.php
│   ├── Database.php
│   ├── EnvLoader.php
│   └── ContentCleaner.php
├── public/
│   └── index.php
├── storage/
│   ├── logs/
│   └── images/
├── views/
│   ├── layout.php
│   ├── dashboard.php
│   ├── posts.php
│   ├── post_detail.php
│   ├── generate.php
│   ├── prompts.php
│   ├── activity.php
│   ├── settings.php
│   └── login.php
├── .env.example
├── .gitignore
├── README.md
└── product.md (this file)
```

---

## 13. Environment Variables (.env)

```
APP_NAME=BrandExplode
APP_URL=https://app.brandexplode.com
APP_ENV=production

DB_PATH=/home/brandexplode/db/brandexplode.sqlite

SESSION_SECRET=your_secret_here

OPENAI_API_KEY=sk-...

LINKEDIN_CLIENT_ID=86zrrnma150kyx
LINKEDIN_CLIENT_SECRET=...
LINKEDIN_PERSON_ID=N4wPtbl7hC
LINKEDIN_ACCESS_TOKEN=...
LINKEDIN_API_VERSION=202503

STORAGE_PATH=/home/brandexplode/storage
```

---

## 14. Monetization Model (Future)

| Plan | Price | Features |
|------|-------|----------|
| Solo | $19/month | 1 user, LinkedIn only, 30 posts/month |
| Pro | $49/month | 1 user, all platforms, unlimited posts |
| Agency | $149/month | 5 users, all platforms, white-label |

---

## 15. Claude Code Build Instructions

When starting Claude Code session:

1. Point Claude Code at the `brandexplode/` directory
2. Say: "Read product.md first. We are building Phase 1. Start with the database schema and PHP Database class."
3. After each file: commit to Git with descriptive message
4. Test each endpoint before moving to next
5. Use `.env` file for all credentials — never hardcode

**Git commit convention:**
```
feat: add posts API endpoint
fix: correct scoring formula
test: add PHPUnit for ContentCleaner
chore: update schema with analytics table
```

---

*BrandExplode — Explode your brand with AI*
