Files
padelnomics/docs/ADMIN.md
Deeman 607dc35a9d docs: add ADMIN.md — comprehensive admin panel guide
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>
2026-02-25 09:44:33 +01:00

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 Flagslead_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.