big-screen-2 / CLAUDE.md
Mathias
Redesign dashboard: combined metrics, 8 leaderboards, medals & achievements
5dda8e1

SDR Status Tracker

Overview

Interactive SDR (Sales Development Representative) activity tracker dashboard. FastAPI backend fetches data from Google Sheets and serves a vanilla JS frontend with leaderboards and progress tables. Built for ScaleupXQ - a B2B sales consulting company.

Project Structure

sdr-status-tracker-v2/
β”œβ”€β”€ app.py                  # FastAPI backend (API routes, Google Sheets integration, caching)
β”œβ”€β”€ excel_parser.py         # Excel file parser (local fallback when Sheets unavailable)
β”œβ”€β”€ detect_columns.py       # Auto-detects column layout from sheet headers β†’ column_config.json
β”œβ”€β”€ static/
β”‚   └── index.html          # Frontend dashboard (vanilla HTML/CSS/JS, progress tables)
β”œβ”€β”€ data/                   # Local Excel files for offline/fallback use (gitignored)
β”œβ”€β”€ months_config.json      # Month definitions (sheet IDs, tab names, start_week)
β”œβ”€β”€ column_config.json      # Column layout mapping (weekly + monthly positions)
β”œβ”€β”€ credentials.json        # Google service account key (gitignored β€” do NOT commit)
β”œβ”€β”€ SETUP_SECRETS.md        # Instructions for setting up secrets (gitignored)
β”œβ”€β”€ requirements.txt        # Python dependencies
β”œβ”€β”€ Dockerfile              # Production container (python:3.11-slim + uvicorn)
β”œβ”€β”€ README.md               # HuggingFace Space config + description
β”œβ”€β”€ CLAUDE.md               # This file - development context
β”œβ”€β”€ DEVELOPMENT.md          # Technical details and customization guide
└── BRAND_GUIDELINES.md     # ScaleupXQ brand identity guide

Brand Guidelines

IMPORTANT: All UI changes must follow the ScaleupXQ brand guidelines in BRAND_GUIDELINES.md.

Key brand elements:

  • Primary Color: #6D3EF3 (purple)
  • Font: Inter (Google Fonts)
  • Tone: Bold, engaging, playfully authentic

Deployment

Tech Stack

  • Backend: FastAPI (Python 3.11), served via uvicorn
  • Data Source: Google Sheets API (primary), Excel files via openpyxl (fallback)
  • Frontend: Vanilla HTML/CSS/JavaScript in static/index.html
  • Styling: CSS custom properties, gradients, glassmorphism, HTML progress bars
  • Real-time: Server-Sent Events (SSE) for live refresh on data changes
  • Caching: In-memory per-month cache with 1-hour TTL, webhook invalidation

Data Flow

Google Sheets β†’ FastAPI /api/data β†’ JSON β†’ Frontend fetch β†’ Tables + Leaderboard
                    ↑ cache (1h TTL)
                    ↑ webhook invalidation via /api/invalidate-cache

The frontend calls /api/data?month=2026-02 on load and on month selector change. The backend fetches from Google Sheets (or cache), parses the DAILY tab into per-SDR activity blocks, and returns JSON with weekly + monthly totals.

API Endpoints

Endpoint Method Description
/ GET Serve static/index.html
/api/data?month=ID GET Fetch parsed case data for a month
/api/months GET List available months for dropdown
/api/config GET Current sheet configuration
/api/column-config GET Current column layout
/api/cache-status GET Cache age and TTL info
/api/invalidate-cache POST Clear cache (webhook or refresh button)
/api/reload-config POST Reload column_config.json + months_config.json
/api/events GET SSE stream for real-time refresh
/api/debug?month=ID GET Raw sheet data and parsed blocks (debugging)

Data Structure

Source: Google Sheets

Each month has its own Google Sheet (or tab). The DAILY tab has this layout:

  • Column A: Case name (merged cells)
  • Column B: GS/SDR name (merged cells)
  • Column C: Activity type (Calls, Emails, LinkedIn, Prospects, Discovery, SQL)
  • Columns D onwards: Weekly blocks (5 daily columns + target + percentage), then monthly totals

Configuration Files

months_config.json β€” defines available months:

{
  "months": [
    {"id": "2026-02", "label": "February 2026", "sheet_id": "...", "tab_name": "DAILY - for SDR to add data🌟", "start_week": 6}
  ],
  "default_month": "2026-02"
}

column_config.json β€” maps column positions for weekly/monthly data:

{
  "weeks": [
    {"week_num": 2, "daily_start": 3, "daily_end": 7, "target_col": 8, "pct_col": 9}
  ],
  "monthly": {"target_col": 32, "actual_col": 33, "pct_col": 34}
}

Scoring System (Leaderboard)

Capping Rule (IMPORTANT)

You cannot reach 100% unless ALL individual targets are met. Each target gets an equal share of 100%. If any target is below 100%, over-performance on other targets is capped. Only when ALL targets are >= 100% does over-performance count.

Example with 4 targets (25% share each):

  • If targets are 120%, 80%, 100%, 110% β†’ Score is capped: 25 + 20 + 25 + 25 = 95%
  • If targets are 120%, 100%, 100%, 110% β†’ All met, uncapped: 30 + 25 + 25 + 27.5 = 107.5%

Legacy Points (not currently used)

  • Won (Vunnet): 3 points
  • Offer Sent (Tilbud sendt): 2 points
  • Meeting Booked (MΓΈte booket): 1 point

Color Scheme (ScaleupXQ Brand)

/* Primary */
--primary: #6D3EF3;        /* ScaleupXQ Purple - headers, highlights */
--primary-dark: #602DF2;   /* Darker variant - hover states */

/* Status colors from brand palette */
--success: #70E0B1;        /* Emerald 300 - won deals, positive */
--warning: #FFF09B;        /* Marigold 300 - pending/offers */
--danger: #FF8474;         /* Tangerine 300 - lost deals */
--info: #ABECFA;           /* Zodiac 300 - informational */
--purple: #B89EFF;         /* Lilac 300 - accents */

/* Backgrounds */
--bg-dark: #0D0B13;        /* Base 600 - dark background */

See BRAND_GUIDELINES.md for complete color palette and usage rules.

Common Tasks

Add a new month

  1. Add entry to months_config.json with id, label, sheet_id, tab_name, start_week
  2. Update default_month if it should be the default
  3. If column layout differs, run python detect_columns.py to regenerate column_config.json
  4. Deploy: git push sxq2 main

Change column layout

Run python detect_columns.py (reads sheet headers via Google Sheets API) or edit column_config.json manually. Hit POST /api/reload-config to apply without restart.

Local development

pip install -r requirements.txt
# Set GOOGLE_CREDENTIALS env var (JSON string of service account key)
python app.py  # Starts on http://localhost:7860

Modify progress bar / table colors

Edit the CSS custom properties and progress bar color thresholds in static/index.html. See BRAND_GUIDELINES.md for the approved color palette.

Change leaderboard scoring

Edit the scoring logic in static/index.html β€” the capping rule is implemented in the frontend.

Environment Variables

Variable Required Description
GOOGLE_CREDENTIALS Yes Service account JSON key (as string)
GOOGLE_SHEET_ID No Default sheet ID (fallback if no months_config.json)
GOOGLE_SHEET_GID No Default tab/sheet GID (fallback, default 1864606926)
WEBHOOK_SECRET No Optional secret for cache invalidation webhook

Git Remotes

sxq:  https://huggingface.co/spaces/ScaleupXQ/big-screen   (legacy)
sxq2: https://huggingface.co/spaces/ScaleupXQ/big-screen-2 (current)

Deploy command: git push sxq2 main