Covers all 10 admin sections: Dashboard, Marketplace (new), Leads, Suppliers, Flags, Feedback, Emails (sent log, inbox, compose, audiences), pSEO Engine, SEO Hub, CMS (Templates, Scenarios, Articles), Tasks, Users. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
8.6 KiB
Admin Panel Guide
The admin panel lives at /admin/ and is restricted to users whose email is in ADMIN_EMAILS.
Dev shortcut: GET /auth/dev-login?email=<admin-email> (DEBUG mode only).
Sidebar navigation (left to right in layout): Dashboard → Marketplace → Leads → Suppliers → Flags → Feedback → Emails → pSEO → SEO
CMS sections (Templates, Scenarios, Articles) are linked from the sidebar too.
Dashboard /admin/
Quick-glance overview: user count, lead funnel summary, recent tasks, and credit economy totals. Entry point for everything else.
Marketplace /admin/marketplace
Single-screen health view for the two-sided market. Useful for daily ops check and spotting stalled leads or low supplier engagement.
Lead Funnel (top cards)
| Card | Meaning |
|---|---|
| Total Leads | All quote-type leads ever submitted |
| Verified New | Verified leads with status new — ready to be unlocked by a supplier |
| Unlocked | Distinct leads that have at least one lead_forward record |
| Won | Leads with status closed_won |
| Conversion Rate | Won ÷ Total |
Credit Economy
| Card | Meaning |
|---|---|
| Issued | Sum of all positive credit ledger entries (purchases + refills) |
| Consumed | Credits spent on lead unlocks (absolute value of lead_unlock entries) |
| Outstanding | Current credit_balance sum across all paid-tier suppliers |
| 30-day Burn | Credits consumed in the last 30 days |
Supplier Engagement
| Card | Meaning |
|---|---|
| Active | Paid-tier suppliers with credit_balance > 0 |
| Avg Unlocks | Average lead forwards per active supplier |
| Response Rate | Forwards where status != 'sent' ÷ total forwards |
Feature Flags — lead_unlock and supplier_signup toggles are inline on this page. Clicking saves immediately and refreshes (no full-page reload). Also accessible at /admin/flags.
Activity Stream — HTMX partial loaded on page open, showing the last 50 events across three tables: new leads, lead unlocks, credit ledger entries. Three dot colours: blue = lead created, green = unlock, amber = credit event.
Leads /admin/leads
List view (/admin/leads)
Summary cards at top: total leads / new+unverified / hot pipeline credits / forward rate.
Filters (HTMX live — updates table without page reload):
- Search — matches
contact_name,contact_email,contact_company - Status — new / pending_verification / contacted / forwarded / closed_won / closed_lost
- Heat — hot / warm / cool
- Country — ISO country code
- Period pills — Today / 7d / 30d / All
Detail view (/admin/leads/<id>)
Full lead record including all extended quote fields (build context, glass type, lighting, location status, financing, services needed, notes).
Inline HTMX actions (no full-page reload):
- Status change — dropdown + save button → swaps the status badge in place
- Forward to supplier — select supplier + send → appends row to forward history table
Forward history table shows: supplier name, current forward status, credit cost, sent timestamp.
Create lead (/admin/leads/new) — manual lead entry for phone/offline enquiries.
Heat scoring — set automatically on submission: hot = 35 credits (≥6 courts + confirmed budget + short timeline), warm = 20, cool = 8.
Suppliers /admin/suppliers
List view — search by name/email, filter by tier (free/basic/growth/pro) and country. Table shows tier badge, credit balance, and listing status.
Detail view (/admin/suppliers/<id>)
- Adjust credit balance (add or subtract, reason logged to
credit_ledger) - Change subscription tier
- View all lead forwards for this supplier with forward statuses
- Impersonate supplier (enter their session to debug dashboard issues)
Create supplier (/admin/suppliers/new) — manual supplier onboarding.
Feature Flags /admin/flags
Toggle on/off without redeploy. Current flags:
| Flag | Controls |
|---|---|
markets |
Market score pages visible to public |
payments |
Paddle checkout enabled |
planner_export |
PDF export tab visible in planner |
supplier_signup |
Supplier signup wizard accessible |
lead_unlock |
Suppliers can unlock leads (spend credits) |
Flags can also be toggled inline on the Marketplace dashboard for the two most-used flags.
Feedback /admin/feedback
All submissions from the on-page feedback widget (thumbs up/down + optional text). Filterable by page and rating. Rate-limited to 1 per IP per page per hour.
Emails
Sent Log /admin/emails
Every outgoing email recorded in email_sent. Filter by type (magic_link, lead_forward, weekly_digest, etc.), delivery event (delivered/bounced/opened/clicked), or free-text search on recipient/subject.
Clicking a row opens the detail view — shows metadata, Resend delivery event timeline, and a sandboxed HTML preview of the message body fetched live from Resend API.
Inbox /admin/emails/inbox
Inbound emails received via Resend inbound routing. Unread count shown as a badge in the sidebar. Detail view renders the HTML body in a sandboxed iframe with an inline reply form.
Compose /admin/emails/compose
Send one-off transactional or plain emails. Select from-address (leads@, hello@, etc.) and optionally wrap in the branded email shell.
Audiences /admin/emails/audiences
Lists all Resend audiences (waitlist, planner nurture, etc.) with contact counts. Drill into an audience to view contacts and remove individuals.
pSEO Engine /admin/pseo
Operational visibility for the programmatic SEO content pipeline. Four sub-tabs:
Content Gaps — for each template, shows DuckDB serving rows that have no matching article in the requested language. Use this to prioritise what to generate next.
Health Checks — per-article sanity checks:
- hreflang orphans (EN article exists, DE missing)
- missing HTML build files on disk
- broken
[scenario:slug]references in article markdown
Freshness — compares _serving_meta.json export timestamp vs MAX(updated_at) across articles per template. Status: 🟢 Fresh / 🟡 Stale / 🟣 No articles / ⚫ No data.
Jobs — live generation job monitor. Progress bars poll every 2s while jobs run. Error drilldown via <details> on failed jobs.
Generation is triggered from the Templates section (see below) — pSEO Engine is read-only observability.
SEO Hub /admin/seo
Aggregated SEO metrics from Google Search Console, Bing Webmaster Tools, and Umami. Three tabs:
- Search — keyword performance (impressions, clicks, CTR, position) synced daily
- Funnel — Umami pageview → planner → quote conversion funnel
- Scorecard — per-article GSC impressions/clicks overlay on article metadata
Sync button triggers an immediate background sync of all configured sources (otherwise syncs daily via scheduler).
Requires GSC_CLIENT_SECRETS_JSON, GSC_PROPERTY_URL, BING_API_KEY, and UMAMI_* env vars.
CMS
Templates /admin/templates
Each template = a Jinja2 Markdown template file + a DuckDB data source query. Templates produce articles at scale.
Actions per template:
- Edit — modify template body, data query, or metadata
- Preview — render a single row through the template without saving
- Generate — bulk generate articles for all (or specific) data rows; runs as background task; progress visible in pSEO Engine → Jobs
Scenarios /admin/scenarios
Public scenario cards shown on the landing page (e.g. "6-court indoor club in Munich"). Each has a name, description, financial state blob (pre-fills the planner), and a live PDF preview.
Articles /admin/articles
Generated article records. Filter by template, language, country, published status.
Per-article actions: Edit markdown inline, Publish/Unpublish (HTMX, no page reload), Rebuild HTML (re-runs Markdown → HTML without re-generating content), Delete.
Rebuild All button at top re-processes every published article's Markdown into HTML — use after template or CSS changes.
Tasks /admin/tasks
Worker queue state. Shows pending / running / failed tasks with payload and error log. Actions: Retry (re-enqueues), Delete (removes from queue).
Failed tasks do not auto-retry — manual retry is intentional so you can inspect the error first.
Users /admin/users
List all users (search by email/name). Detail view shows role, subscription state, scenarios, and recent activity. Impersonate button logs you in as that user — "Stop impersonating" in the top bar returns you to your admin session.