Skip to content

demilt11-lab/publisting

Repository files navigation

Publisting

Music publishing rights intelligence platform for A&R and sync licensing teams, live at publisting.net. Search songwriter credits, publishing splits, PRO affiliations (ASCAP / BMI / SESAC), streaming performance, and catalog valuations across Spotify, Apple Music, Tidal, MusicBrainz, and a dozen other sources.

Stack

  • Frontend: React 18 + TypeScript (strict) + Vite + shadcn/ui — hosted on Vercel (SPA rewrites, caching, and security headers in vercel.json)
  • Backend: Supabase (PostgreSQL + Row-Level Security + ~140 Edge Functions)
  • Testing: Vitest + Testing Library
  • Domain: publisting.net

Development

npm install
cp .env.example .env   # fill in your Supabase project values
npm run dev            # dev server on :8080
Command What it does
npm run build Stage-string check, then production build to dist/
npm run lint ESLint + stage-string check
npm run typecheck tsc -b (strict mode)
npm test Vitest suite (one-shot); npm run test:watch for watch mode
npm run preview Serve the production build locally

Environment variables

Only public values live in .env — they are embedded in the browser bundle:

VITE_SUPABASE_URL=https://<project-ref>.supabase.co
VITE_SUPABASE_PUBLISHABLE_KEY=<anon-key>

In production both are set in Vercel (Project → Settings → Environment Variables); .env is not committed. Server-side secrets never go in .env — see below.

Crawl4AI metadata crawler

The crawl4ai/ directory runs a self-hosted Crawl4AI server that the crawl4ai-crawler Supabase edge function uses to crawl DSP song credits, PRO/rights-org affiliations and splits (BMI, ASCAP, The MLC, HFA, SoundExchange), streaming/playlist stats, chart placements, radio airplay, and official social links. See crawl4ai/README.md for setup.

Project structure

src/
  pages/          Route components (lazy-loaded; admin routes gated by AdminGate)
  components/     Feature components + shadcn/ui primitives in components/ui
  hooks/          Data hooks (auth, teams, watchlists, lookups, …)
  lib/            Domain logic: parsers, normalizers, scoring, api/ fetch wrappers
  contexts/       App-wide providers (team, system status, catalog import)
  integrations/   Supabase client + generated DB types
  test/           Vitest suites for critical business logic
supabase/
  functions/      Deno edge functions (one directory per lookup/integration)
  migrations/     SQL migrations (source of truth for schema + RLS)

Deployment

  • Frontend: Push to main → Vercel auto-deploys to publisting.net
  • Edge Functions: supabase functions deploy --all --project-ref <ref>
  • Migrations: supabase db push --project-ref <ref>
  • Auth: In the Supabase dashboard set Site URL to https://publisting.net, allow-list https://publisting.net/**, and enable the Google/Apple OAuth providers.

Edge Function secrets (set in Supabase dashboard)

Secret Purpose
GOOGLE_AI_API_KEY Google AI Studio (Gemini 2.5 Flash, text-embedding-004)
SPOTIFY_CLIENT_ID / SPOTIFY_CLIENT_SECRET Spotify API
DISCOGS_TOKEN Discogs API
GENIUS_TOKEN Genius API
FIRECRAWL_API_KEY Web scraping (optional — pro-lookup falls back to the AI lookup)
CRAWL4AI_URL Self-hosted crawl4ai server URL — powers the crawl4ai-crawler pipeline (BMI, ASCAP, The MLC, HFA, SoundExchange, DSP credits, charts, radio, social)
CRAWL4AI_API_TOKEN Bearer token for the crawl4ai server (only if JWT auth is enabled)
CRAWL4AI_LLM_PROVIDER LiteLLM provider for extraction (optional; default openai/gpt-4o-mini)
CRAWL4AI_PROXY_URL Route the crawler's headless browser through a residential/rotating proxy, e.g. http://user:pass@gw.dataimpulse.com:823 (optional; or set CRAWL4AI_PROXY_SERVER/_USERNAME/_PASSWORD separately)
CRAWL4AI_SOCIAL_PROXY_URL Dedicated proxy for social crawls (Instagram/TikTok/etc.), which are IP-sensitive and often need a separate residential pool. Falls back to CRAWL4AI_PROXY_URL when unset (or set CRAWL4AI_SOCIAL_PROXY_SERVER/_USERNAME/_PASSWORD).
CHARTMETRIC_REFRESH_TOKEN Chartmetric data
HUNTER_API_KEY Contact discovery
YOUTUBE_API_KEY YouTube data
SOUNDCHARTS_API_KEY Soundcharts
ALLOWED_ORIGIN CORS origin (https://publisting.net) — also locks the internal lookup/data functions' CORS to the app origin
INTERNAL_FUNCTION_SECRET Optional. When set, gates the internal-only credit/enrichment functions (spotify-credits-lookup, genius-lookup, apple-credits-lookup, hunter-lookup) so only other edge functions (which send the matching x-internal-secret header) can call them. Unset = gate disabled (safe default). Set any long random string to lock these paid endpoints down.
BUDGET_<PROVIDER> Optional per-provider daily call ceiling override (e.g. BUDGET_HUNTER=1000, BUDGET_GEMINI=5000). Defaults are built in; set to tune the global daily spend cap without a redeploy.

Post-deploy smoke test

  1. Load the app — landing page renders, no console errors.
  2. Sign up / sign in (email + Google OAuth), confirm the session persists on refresh.
  3. Run a song lookup from the home page; credits and sources populate.
  4. Add an artist to a watchlist; check it appears on /watchlist.
  5. Export credits to CSV/XLSX/PDF from a lookup result (exercises the lazy-loaded export chunks).
  6. As an admin user, open /admin/health for provider status.

About

Resources

Security policy

Stars

1 star

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors