Skip to content

oseni99/harmon

Repository files navigation

HarmonyGift

HarmonyGift is a ritual gifting platform where creators generate personalized songs for loved ones (biographer → vibe selection → studio → public gift page).

This repo uses Next.js (App Router) + Tailwind + Supabase (Postgres) + Clerk + BullMQ worker.

Note: The current repo is on next@16 + react@19 (route structure + behavior match the product spec).


Prerequisites

  • Node.js 20+ recommended
  • pnpm installed

1) Install dependencies

From the repo root:

pnpm install

Worker dependencies:

pnpm -C worker install

2) Configure environment variables

Create a local env file:

cp .env.example .env.local

Fill at minimum:

  • NEXT_PUBLIC_SUPABASE_URL
  • NEXT_PUBLIC_SUPABASE_ANON_KEY
  • SUPABASE_SERVICE_ROLE_KEY
  • NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY
  • CLERK_SECRET_KEY
  • CLERK_WEBHOOK_SECRET
  • NEXT_PUBLIC_APP_URL (use http://localhost:3000 for local)

Feature-specific (needed only when you test those features):

  • Biographer + lyrics: ANTHROPIC_API_KEY (optional ANTHROPIC_MODEL)
  • Queues/worker: UPSTASH_REDIS_URL (Redis protocol URL for BullMQ)
  • Email delivery: RESEND_API_KEY, RESEND_FROM_EMAIL
  • R2 uploads: R2_* + R2_PUBLIC_URL
  • Audio synthesis: ELEVENLABS_API_KEY, optional ELEVEN_MUSIC_ENABLED, and optional ELEVENLABS_VOICE_ID (fallback)
  • Payments: STRIPE_*

3) Create Supabase project + apply schema/RLS

  1. Create a Supabase project.
  2. Open SQL Editor in Supabase.
  3. Run these files in order:
    • supabase/migrations/0001_init.sql
    • supabase/migrations/0002_rls.sql

More details: supabase/README.md

Realtime

Dashboard uses Supabase Realtime. Ensure these tables are included in the supabase_realtime publication:

  • public.songs
  • public.activity

0002_rls.sql attempts to add them automatically, but check your Supabase dashboard if needed.


4) Configure Clerk (Auth + Supabase JWT)

4.1 Create Clerk app

  1. Create a Clerk application.
  2. Copy keys into .env.local:
    • NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY
    • CLERK_SECRET_KEY

4.2 Create JWT template for Supabase (required for RLS + realtime)

Create a JWT template named supabase:

  • aud: authenticated
  • role: authenticated
  • custom claim: user_id = {{user.public_metadata.supabase_user_id}}

Recommended: configure the template to sign with HS256 using your Supabase project JWT secret (Supabase → Settings → API → JWT Secret).

Why: Supabase can then verify the Clerk token and expose claims via auth.jwt() for RLS policies.

4.3 Configure Clerk webhook (user sync)

This repo mirrors Clerk users into Supabase and writes the Supabase UUID into Clerk public metadata.

Webhook endpoint:

  • POST /api/webhooks/clerk

Webhook events:

  • user.created
  • user.updated

Local testing usually requires a tunnel (ex: ngrok):

ngrok http 3000

Then set the webhook URL in Clerk to your ngrok URL + /api/webhooks/clerk.


5) Run the app locally

Start Next.js:

pnpm dev

Open:

  • http://localhost:3000 → redirects to sign-in
  • After sign-in: /dashboard

If you see a warning about a missing Supabase session token, your Clerk JWT template or Supabase JWT verification is not configured correctly.


6) Run the worker (queues + timed drops + audio)

The worker is a separate, long-running process:

pnpm -C worker dev

Required for worker

  • UPSTASH_REDIS_URL must be set

Env loading (local)

The worker automatically loads:

  • repo root .env / .env.local
  • and optionally worker/.env / worker/.env.local (overrides)

7) Optional integrations (to test “everything” end-to-end)

Anthropic (biographer + lyric generation)

Set:

  • ANTHROPIC_API_KEY
  • (optional) ANTHROPIC_MODEL=claude-sonnet-4-6

Upstash Redis (BullMQ)

Set:

  • UPSTASH_REDIS_URL (use Upstash Redis URL / rediss://..., not the REST URL)

Resend (unlock emails)

Set:

  • RESEND_API_KEY
  • RESEND_FROM_EMAIL

Cloudflare R2 (audio + dedication uploads)

Set:

  • R2_ACCOUNT_ID
  • R2_ACCESS_KEY_ID
  • R2_SECRET_ACCESS_KEY
  • R2_BUCKET_NAME
  • R2_PUBLIC_URL (public base URL for serving uploaded objects)

ElevenLabs + FFmpeg (audio generation)

Set:

  • ELEVENLABS_API_KEY
  • (optional) ELEVEN_MUSIC_ENABLED=false to disable Eleven Music
  • (optional) ELEVENLABS_VOICE_ID (used for beat+TTS fallback)

Notes:

  • If ELEVENLABS_API_KEY is set, the worker will prefer Eleven Music (paid feature) to generate a real music track.
  • If Eleven Music fails (or you disable it), the worker falls back to a beat+TTS pipeline, which requires ELEVENLABS_VOICE_ID and beats in R2.

Upload beat mp3s to R2:

  • beats/afrobeat-001.mp3
  • beats/rap-001.mp3
  • beats/rnb-001.mp3
  • beats/soul-001.mp3

Stripe (credits + billing)

Set:

  • STRIPE_SECRET_KEY
  • STRIPE_WEBHOOK_SECRET
  • NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY
  • STRIPE_PRICE_TOPUP_ID (or STRIPE_PRICE_SUBSCRIPTION_ID)

Credits are granted from Stripe Price metadata:

  • add metadata.credits = <integer> on the Stripe Price

Webhook endpoint:

  • POST /api/webhooks/stripe

8) What to click (quick manual test path)

  1. /create/biographer → chat with Harmony until you have 4+ memories
  2. Continue → /create/vibe?sessionId=...
  3. Click Generate My Song → creates song + generates 3 lyric variants (charges 1 credit)
  4. Studio placeholder /create/studio?songId=...:
    • select a variant
    • edit lyrics
    • save
    • (optional) enqueue audio generation
  5. Public gift page /s/[slug]:
    • locked/unlocked depends on drop_at
    • plays are tracked via POST /api/public/songs/:slug/play

Troubleshooting

Dashboard shows “Missing Supabase session token”

  • Confirm Clerk JWT template is named supabase
  • Confirm it includes user_id claim
  • Confirm it’s signed using Supabase JWT secret (HS256)
  • Confirm your Clerk user has public_metadata.supabase_user_id set (webhook must run at least once)

Realtime doesn’t update

  • Ensure public.songs + public.activity are in the supabase_realtime publication
  • Ensure Clerk token is being passed to Realtime (the app calls client.realtime.setAuth(token))

Worker jobs don’t run

  • Confirm UPSTASH_REDIS_URL is set
  • Confirm the worker is running: pnpm -C worker dev

About

built an AI song creator but my friends hated AI slop

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages