Skip to content

g30r93g/racedash

Repository files navigation

RaceDash

Timing data extraction, YouTube chapter generation, and lap timer overlay rendering for race footage — packaged as a desktop app.

Architecture

graph TB
    subgraph Apps
        Desktop["apps/desktop<br/><small>Electron app</small>"]
        Renderer["apps/renderer<br/><small>Remotion compositions</small>"]
    end

    subgraph Packages
        Engine["packages/engine<br/><small>Orchestration layer</small>"]
        Core["packages/core<br/><small>Domain types</small>"]
        Scraper["packages/scraper<br/><small>Web scraping</small>"]
        Timestamps["packages/timestamps<br/><small>Timestamp calculation</small>"]
        Compositor["packages/compositor<br/><small>Remotion bundler + renderer</small>"]
    end

    Desktop --> Engine
    Desktop --> Renderer
    Renderer --> Timestamps
    Renderer --> Core
    Engine --> Scraper
    Engine --> Timestamps
    Engine --> Compositor
    Engine --> Core
    Scraper --> Core
    Timestamps --> Core
    Compositor --> Core

    subgraph Cloud["Cloud"]
        API["apps/api<br/><small>Fastify REST API</small>"]
        Admin["apps/web-admin<br/><small>Next.js dashboard</small>"]
        DB["packages/db<br/><small>Drizzle ORM schema</small>"]
        Infra["infra/<br/><small>AWS CDK stacks</small>"]
    end

    Desktop -.->|"authenticated fetch"| API
    API --> DB
    Admin --> DB
    Infra --> API

    subgraph AWS["AWS Services"]
        S3["S3<br/><small>Uploads + renders</small>"]
        StepFn["Step Functions<br/><small>Render pipeline</small>"]
        Lambda["Lambda<br/><small>Pipeline tasks</small>"]
        SQS["SQS<br/><small>Social upload queue</small>"]
        SES["SES<br/><small>Email notifications</small>"]
        CloudFront["CloudFront<br/><small>Signed URL downloads</small>"]
        MediaConvert["MediaConvert<br/><small>Video processing</small>"]
    end

    API -.-> S3
    API -.-> StepFn
    StepFn -.-> Lambda
    Lambda -.-> S3
    Lambda -.-> SQS
    Lambda -.-> SES
    Lambda -.-> MediaConvert
    CloudFront -.-> S3
Loading

Package overview

Package Description Docs
@racedash/core Domain types and constants — no runtime dependencies README
@racedash/scraper Fetches and parses timing data from AlphaTiming README
@racedash/timestamps Offset parsing, lap timestamp calculation, and YouTube chapter formatting README
@racedash/compositor Remotion bundler/renderer abstraction, GPU detection, and FFmpeg codec validation README
@racedash/engine Orchestration layer — composes scraper, timestamps, and compositor README
@racedash/db Drizzle ORM schema — PostgreSQL tables for users, licenses, credits, jobs README

Apps

App Description Docs
@racedash/desktop Electron app with project library, creation wizard, editor, and video preview README
@racedash/renderer Remotion compositions for overlay styles (banner, esports, geometric-banner, minimal, modern) README
@racedash/api Fastify REST API — deployed as AWS Lambda README
@racedash/web-admin Next.js admin dashboard with Clerk auth README

Infrastructure

Component Description Docs
@racedash/infra AWS CDK stacks, Lambda functions, Step Functions pipeline, LocalStack testing README

Prerequisites

Tool Install Verify
Node.js v20+ nodejs.org (LTS) node --version
pnpm npm install -g pnpm pnpm --version
FFmpeg macOS: brew install ffmpeg · Windows: winget install ffmpeg · Linux: sudo apt install ffmpeg ffmpeg -version

Windows support for racedash render is experimental. The Windows render path uses a transparent VP9 WebM overlay internally, so ProRes support is not required.


Getting started

git clone https://github.com/your-org/racedash.git
cd racedash
pnpm install

Local development

Desktop app

pnpm desktop:dev

Build and test

pnpm turbo build       # Build all packages
pnpm turbo test        # Run tests across all packages
pnpm turbo typecheck   # Type-check everything
pnpm lint              # Lint

Cloud services (local)

The API runs on your host (not in Docker) with hot-reload. Docker provides the infrastructure it depends on: PostgreSQL and LocalStack (emulated AWS services).

Service Port
API 3000
Admin dashboard 3001
PostgreSQL 5433
LocalStack 4566

1. Start infrastructure

pnpm local:up       # Start Postgres + LocalStack (waits for readiness)

This creates S3 buckets, SQS queues, SES identity, and the Step Functions state machine automatically.

2. Configure environment

pnpm setup:env

An interactive script that generates apps/api/.env.local. LocalStack vars are auto-populated from infra/localstack-init/env.localstack. You'll be prompted for:

  • DATABASE_URL — Press Enter to accept the default (postgresql://racedash:racedash_local@localhost:5433/racedash_local)
  • CLERK_SECRET_KEY — From dashboard.clerk.com → API Keys (starts with sk_test_)
  • CLERK_WEBHOOK_SECRET — Optional. Needed for user sync. Requires ngrok (see Webhooks below)
  • STRIPE_SECRET_KEY — From Stripe dashboard → Developers → API Keys (starts with sk_test_)
  • STRIPE_WEBHOOK_SECRET — Optional. Use stripe listen CLI (see Webhooks below)
  • STRIPE_PRICE_* — From Stripe dashboard → Products → price IDs (starts with price_)
  • ADMIN_APP_ORIGIN — URL of the admin app for CORS. Default http://localhost:3001

3. Push the database schema

DATABASE_URL="postgresql://racedash:racedash_local@localhost:5433/racedash_local" \
  pnpm drizzle-kit push --force

4. Start the API

cd apps/api && pnpm dev    # Runs on localhost:3000 with hot-reload

5. Point the desktop app at the local API

cp apps/desktop/.env.example apps/desktop/.env
# Set VITE_API_URL=http://localhost:3000
# Set VITE_CLERK_PUBLISHABLE_KEY=pk_test_...

Webhooks (local)

The API receives webhooks from Clerk (user sync) and Stripe (payments). For local development, you need tunnels to forward these to your host.

Clerk webhooks (ngrok):

ngrok http 3000

Copy the https://xxx.ngrok-free.app URL, then in dashboard.clerk.com → Webhooks → Add Endpoint:

  • URL: https://xxx.ngrok-free.app/api/webhooks/clerk
  • Events: user.created
  • Copy the signing secret → set as CLERK_WEBHOOK_SECRET in .env.local

Stripe webhooks (Stripe CLI):

stripe listen --forward-to localhost:3000/api/webhooks/stripe

The CLI prints the webhook signing secret directly — set it as STRIPE_WEBHOOK_SECRET in .env.local.

Infrastructure commands

pnpm local:up              # Start Postgres + LocalStack
pnpm local:down            # Stop everything
pnpm local:fresh           # Wipe volumes and restart clean
pnpm local:logs            # Tail all container logs
pnpm local:logs:localstack # Tail LocalStack logs only
pnpm local:logs:postgres   # Tail Postgres logs only
pnpm local:version-check   # Warn if pinned LocalStack is outdated
pnpm local:ses             # Inspect sent emails in LocalStack
pnpm local:sfn:list        # List Step Functions executions
pnpm local:sfn:execute     # Start/check SFN executions
pnpm setup:env             # Interactive .env.local generator

LocalStack integration tests

cd infra
pnpm localstack:up         # Start standalone LocalStack
pnpm test:local            # Run integration tests
pnpm test:local:watch      # Watch mode
pnpm localstack:down       # Stop container

Overlay styles

Style Description
banner Full-width top bar with accent band and central lap timer. Practice/qualifying: last-lap and session-best panels flanking the timer. Race: position counter and lap counter only. Timer background flashes purple/green/red on lap completion. Configurable accent, text, and timer colours.
esports Floating card (default: bottom-left) with gradient accent bar, position badge, and lap counter. Two icon-badged time panels (last lap, session best) above a current elapsed time bar.
geometric-banner Full-width top bar with five coloured SVG polygon sections. Each section holds a data point (position, last lap, timer, previous lap, lap count). In race mode, collapses to three sections. Timer section flashes with lap performance colours.
minimal Compact floating card (default: bottom-left) with a lap number badge, large italic elapsed time, and three stat columns (position, last lap, session best). Same layout across all modes.
modern Horizontal bar (default: bottom-centre) with a subtle diagonal stripe pattern. Large elapsed time on the left, position/last lap/session best stats on the right separated by a thin divider.

About

Render overlays onto your race footage.

Resources

Stars

Watchers

Forks

Releases

No releases published

Contributors

Languages