Skip to content

Latest commit

 

History

370 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

World of Floorcraft

A social platform for the ballroom dance community built around the ISTD syllabus. Browse figures, explore transitions as interactive graphs, build competition routines, organize and score competitions with the skating system, share technique articles, and connect with dancers and teams.

Background

What is the ISTD Ballroom Syllabus?

The Imperial Society of Teachers of Dancing (ISTD) publishes "The Ballroom Technique," the definitive reference for standard ballroom dancing. It defines figures (named sequences of steps) for five dances and specifies which figures can precede or follow each other, forming a directed graph of transitions.

The Five Standard Dances

Dance Time Signature Character
Waltz 3/4 Rise-and-fall movement in triple time
Foxtrot 4/4 Smooth, progressive movement across the floor
Quickstep 4/4 Light, fast-moving dance with hops and runs
Tango 2/4 Sharp, staccato movements with dramatic character
Viennese Waltz 3/4 Fast, continuous turning

Examination Levels

Figures are introduced at progressively higher examination levels. Higher levels unlock additional figures and transitions:

  • Student Teacher / Associate (Bronze) — Foundation figures
  • Licentiate (Silver) — Intermediate figures and additional transitions
  • Fellow (Gold) — Advanced figures and the full transition set

Platform Features

Syllabus & Graph Tool

  • Browse figures for each dance with search and level filtering
  • Interactive directed graph visualization (React Flow + Dagre layout)
  • Full dance graphs and local figure neighborhood graphs
  • Figure detail pages with leader/follower step charts, footwork, CBM, sway, timing

Routine Builder

  • Build competition routines by selecting figures with transition validation
  • Level ceiling filtering (Bronze/Silver/Gold/Fellow)
  • Publish routines to your profile or share as feed posts

Social Network

  • Share routines with captions and write technique articles (WYSIWYG markdown editor)
  • Follow other dancers, like/comment/save posts
  • Organize saved posts into folders
  • User profiles with competition level badges
  • Following + Explore feed tabs

Organizations

  • Create or join teams (university ballroom teams, clubs, etc.)
  • Configurable membership: open, invite-only, or request-to-join
  • Org profile pages with posts, members, and settings
  • Org-scoped content visibility

Real-Time Messaging

  • Direct messages, group chats, and org channels
  • Real-time delivery via Convex reactive queries
  • Typing indicators and presence

Competition Organizer

Full competition lifecycle management with real-time scoring using the skating system.

  • Setup — Create competitions with multi-step wizard, schedule builder with drag-and-drop, event management with default groupings, staff/judge assignments
  • Registration — Couple registration, per-event or flat-fee pricing, Stripe Connect payments, competitor number assignment, TBA partner finder, team match submissions
  • Pre-comp — Add/drop request management, automatic round generation with heat assignments, schedule estimation, statistics dashboard, award calculator
  • Scoring — Full skating system engine (Rules 5–11), callback tally, single and multi-dance placement, tabulation tables, results workflow (compute → review → publish)
  • Judge UI — Standalone tablet interface with separate JWT auth (no platform account required), tap-to-toggle callback marking, tap-to-rank finals, real-time submission via Convex reactive queries
  • Comp Day — Scrutineer dashboard, registration table, deck captain check-in grid, emcee schedule with announcements, projector display, competitor live view
  • Post-comp — Public results with Summary + Marks tabs, competitor search and history, competition calendar with filters, organizer feedback forms with analytics, financial analytics, record removal requests
  • Org Views — Per-organization schedule, entries, and results for team coaches and admins

See docs/comp-organizer/ for full documentation.

Tech Stack

Layer Technology Purpose
Framework Next.js 15 (App Router) Server components, file-based routing
Language TypeScript End-to-end type safety
Styling Tailwind CSS v4 Utility-first CSS
UI Components shadcn/ui Accessible components on Radix UI primitives
Backend & DB Convex Reactive database, queries/mutations/actions, real-time subscriptions
Auth Clerk Authentication with OAuth providers; Convex JWT integration
Editor Tiptap WYSIWYG markdown editor for posts
Payments Stripe Competition registration payments via Connect; webhook fulfilled into Convex
Judge Auth jose Edge-compatible JWT for judge tablet sessions
Drag & Drop @dnd-kit/react Schedule builder reordering
Hosting Vercel Deployment platform
Package Manager pnpm Fast, disk-efficient package manager
Dev Environment Nix flake Reproducible development environment

Architecture

The codebase follows a modular monolith pattern organized by domain:

src/
  domains/
    syllabus/         # Figure graph, dance browsing UI
    routines/         # Routine builder UI
    social/           # Feed, posts, comments, likes, follows, saves UI
    messaging/        # DMs, group chats, org channels UI
    orgs/             # Organizations UI
    competitions/     # Competition organizer, scoring, judge UI, comp-day ops UI
  shared/
    ui/               # shadcn/ui components
    components/       # App shell (nav, layout, Convex/Clerk providers)
    lib/              # Utility helpers
convex/
  schema.ts           # All Convex tables and indexes
  lib/                # Auth, permission, money, time helpers
  syllabus/           # Convex syllabus functions
  routines.ts         # Convex routine functions
  social/             # Convex social functions
  orgs.ts             # Convex org functions
  messaging.ts        # Convex messaging functions
  competitions/       # Convex competition functions and Stripe actions

Each domain owns its UI components and route pages. Convex functions live alongside the schema in convex/ and serve as the backend boundary. See docs/ for detailed architecture documentation.

Database Schema

Core (Syllabus)

dances              1 ──── * figures           Figures belong to a dance
figures             1 ──── * figure_edges      Edges connect two figures (directed)

User Content

users               1 ──── * routines          Users own routines
routines            1 ──── * routine_entries   Routines contain ordered figures
users               1 ──── * posts             Users author posts
posts               1 ──── * comments          Posts have threaded comments
users               1 ──── * saved_posts       Users bookmark posts into folders

Social

users               * ──── * follows           Follow relationships (with pending state)
users               * ──── * organizations     Org membership (via memberships table)
organizations       1 ──── * conversations     Org channels
users               * ──── * conversations     DMs and group chats (via conversation_members)

Competitions

organizations       1 ──── * competitions      Competitions owned by orgs
competitions        1 ──── * competition_days  Multi-day schedule structure
competition_days    1 ──── * schedule_blocks   Sessions within a day
competitions        1 ──── * competition_events Events (e.g. "Novice Waltz")
competitions        * ──── * judges            Judge assignments (global directory)
competitions        1 ──── * registrations     Per-person registration
entries             * ──── 1 event             Couple entries (leader + follower)
entries             1 ──── * callback_marks    Preliminary round marks
entries             1 ──── * final_marks       Final round placements
rounds              1 ──── * heats             Heat assignments per round
competitions        1 ──── * feedback_forms    Post-comp feedback collection

Design

Color System

Dark theme with accent colors mapped to examination levels:

  • Bronze #CD7F32 — Student Teacher / Associate
  • Silver #C0C0C0 — Licentiate
  • Gold #FFD700 — Fellow

Available as Tailwind utilities: text-bronze, border-silver, bg-gold, etc.

Getting Started

Prerequisites

  • Nix with flakes enabled, or Node.js 22 with pnpm
    • Convex Node actions support Node 18/20/22/24; use Node 22 for this project and avoid Node 26.
  • A Convex account
  • A Clerk application with a Convex JWT template
  • Stripe test keys if you are exercising competition payments

Setup

# Enter dev environment (if using Nix)
direnv allow
# or: nix develop

# Install dependencies
pnpm install

# Set up local environment variables
cp .env.example .env.local
# Add NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY and CLERK_SECRET_KEY from Clerk.
# NEXT_PUBLIC_CONVEX_URL is written by `npx convex dev`.
# JUDGE_JWT_SECRET is generated and set on the Convex deployment below.

# Provision/link Convex with a supported Node version.
# In the Nix shell you can run `npx convex ...` directly; otherwise use mise to force Node 22.
# On the first run, Convex may create the deployment and then stop because
# required Convex env values such as CLERK_JWT_ISSUER_DOMAIN or JUDGE_JWT_SECRET
# are not set yet; continue with the env set commands.
mise exec node@22 -- npx convex dev --once

# Configure required backend environment variables on the Convex deployment.
# CLERK_JWT_ISSUER_DOMAIN is Clerk's Frontend API URL / JWT issuer for the Convex template.
# JUDGE_JWT_SECRET signs judge tablet JWTs and must be a strong 32+ character secret.
mise exec node@22 -- npx convex env set CLERK_JWT_ISSUER_DOMAIN https://your-app.clerk.accounts.dev
mise exec node@22 -- npx convex env set JUDGE_JWT_SECRET "$(openssl rand -base64 32)"

# Optional: only if you want online competition registration payments now.
# Manual payment recording and analytics work without Stripe.
mise exec node@22 -- npx convex env set STRIPE_SECRET_KEY sk_test_...
mise exec node@22 -- npx convex env set STRIPE_CHECKOUT_ALLOWED_ORIGINS https://your-app.example.com,http://localhost:3000
mise exec node@22 -- npx convex env set STRIPE_WEBHOOK_SECRET whsec_...

# Validate schema/functions again after Convex env is configured.
mise exec node@22 -- npx convex dev --once

# Seed syllabus data
pnpm seed

# Start dev server
pnpm dev

Website backend setup

For the deployed website, configure these places:

  1. Clerk — create the app, enable the sign-in providers you want, and add a Convex JWT template with audience/application ID convex. Copy Clerk's Frontend API URL / JWT issuer into the Convex env var below.
  2. Convex — create/deploy the Convex deployment, then set:
    mise exec node@22 -- npx convex env set CLERK_JWT_ISSUER_DOMAIN https://your-app.clerk.accounts.dev
    mise exec node@22 -- npx convex env set JUDGE_JWT_SECRET "$(openssl rand -base64 32)"
  3. Vercel / website host — set:
    NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_...
    CLERK_SECRET_KEY=sk_...
    NEXT_PUBLIC_CONVEX_URL=https://your-deployment.convex.cloud
    NEXT_PUBLIC_CLERK_SIGN_IN_URL=/sign-in
    NEXT_PUBLIC_CLERK_SIGN_UP_URL=/sign-up
  4. Optional Stripe online payments — if enabling competition checkout, set these on Convex and configure the Stripe webhook endpoint to the Convex site URL (https://your-deployment.convex.site/stripe/webhook) or the Next.js compatibility route (https://your-site.example.com/api/stripe/webhook):
    mise exec node@22 -- npx convex env set STRIPE_SECRET_KEY sk_...
    mise exec node@22 -- npx convex env set STRIPE_CHECKOUT_ALLOWED_ORIGINS https://your-site.example.com
    mise exec node@22 -- npx convex env set STRIPE_WEBHOOK_SECRET whsec_...

GitHub → Vercel automatic deploys

This repo's vercel.json uses pnpm vercel-build, which runs:

convex deploy --cmd-url-env-var-name NEXT_PUBLIC_CONVEX_URL --cmd 'pnpm build:next'

That makes every Vercel build deploy the Convex backend and build the Next.js site against the same production Convex URL. To enable it in Vercel:

  1. In Convex Dashboard, open the production deployment and generate a Production Deploy Key.
  2. In Vercel, add the environment variable below for Production:
    CONVEX_DEPLOY_KEY=<your production deploy key>
  3. Keep the Clerk website env vars in Vercel:
    NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_...
    CLERK_SECRET_KEY=sk_...
    NEXT_PUBLIC_CLERK_SIGN_IN_URL=/sign-in
    NEXT_PUBLIC_CLERK_SIGN_UP_URL=/sign-up

You do not need to manually set NEXT_PUBLIC_CONVEX_URL in Vercel for this path; convex deploy --cmd-url-env-var-name NEXT_PUBLIC_CONVEX_URL injects the correct production URL into the build. Add Stripe env values in the Convex Dashboard later only when enabling online payments.

Data Pipeline

Figures are extracted from scanned pages of "The Ballroom Technique" using Claude's vision API:

# 1. Extract figures from PDF page images
python scripts/extract_figures.py

# 2. Seed Convex from extracted YAML
pnpm seed

Available Scripts

Command Description
pnpm dev Start development server
pnpm convex:dev Run Convex dev server (regenerates _generated/)
pnpm build Production build
pnpm lint Run ESLint
pnpm seed Seed Convex syllabus data from extracted YAML
pnpm test Run Convex function tests
pnpm test:e2e Run Playwright end-to-end tests

Status

Implemented

  • Syllabus browsing with search and level filters
  • React Flow graph visualization (Dagre layout, edge-on-demand)
  • Figure detail pages with leader/follower step data
  • Routine builder with figure picker and transition validation
  • Social feed with shared routines and technique articles (Tiptap editor)
  • Follow system, likes, comments, notifications
  • Save/bookmark system with folders
  • User profiles with competition level badges
  • Organizations with configurable membership (open, invite-only, request-to-join)
  • Real-time messaging via Convex (DMs, group chats, org channels)
  • Competition organizer — full lifecycle from creation to post-comp analytics
  • Skating system scoring engine (Rules 5–11) with tabulation
  • Judge tablet UI with standalone JWT auth
  • Comp-day dashboards (scrutineer, registration table, deck captain, emcee)
  • Real-time competition views (projector display, competitor live view)
  • Results browsing, competitor history, competition calendar
  • Feedback forms with analytics, payment analytics
  • Clerk authentication with route protection
  • Dark theme with ISTD level accent colors
  • PDF extraction and database seed pipeline

Convex function tests cover the migrated backend behavior.

Future

  • Photo/video media support
  • Email/push notifications
  • AI choreography assistant
  • Viennese Waltz syllabus data

Documentation

License

LGPL-3.0 — see LICENSE.

About

Competition management and community platform for ballroom dancers

Resources

Stars

1 star

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages