Project Info
Inspiration
We've all got Notes apps full of half-written lyrics and 2 a.m. voice memos that we never actually finish. The ideas are there – we can hear the hooks and the beats clearly in our heads – but there's usually a big gap between having a spark of an idea and actually sitting down to produce it. At the same time, we love the process of writing music. We didn't want a "generate" button that does everything for us; we wanted to stay in the driver's seat – choosing the words, tweaking the melodies, and building the track piece by piece. We built ProduceThing to help bridge that gap. It's a studio that helps you finish what you start, acting as a collaborator that handles the technical friction while you keep the creative control.
What it does
ProduceThing is an AI music studio built around writing. Grammarly for lyrics A real-time lyric editor that highlights clichés, filler words, repetition, and weak phrasing as you type – with one-click tighten, de-cliché, punch-up, and hook suggestions. Cursor for songwriting Ghost-text autocomplete that understands your rhyme scheme, cadence, and full-song context. Press Tab to accept. AI co-writer + agent Chat with GPT/Claude to iterate on lines, fix flow, or generate ideas. In autonomous mode, Claude can compose, layer, and refine an entire session from a single prompt. Layer-based production Tracks are split into stems so you can add, remove, regenerate, mute/solo, A/B compare, and export — like a lightweight DAW. Music video generation Generate a lip-synced video from a selfie with AI backgrounds and share-ready output.
How we built it
The Frontend Built with Next.js 16, React 19, and TypeScript. We used a transparent textarea layered over a highlighted overlay – the same pattern used in modern code editors – to provide real-time lyric analysis without breaking the writing flow. The Audio Engine We integrated the Suno API for music generation and 12-stem separation. To speed things up, we deployed htdemucs on Modal using T4 GPUs for parallel 3-stem separation. We ran both pipelines in a race – whichever finished first (usually Modal in ~20s vs ~60s) served the user. AI Orchestration Powered by Vercel AI SDK v6 with dual-model routing: GPT-5 Nano handles fast chat and lyric rewrites. Claude Opus 4.6 manages the autonomous "Agent Mode." Lyric Analysis Engine A custom client-side engine that tracks 40+ cliché phrases, 15 filler words, and uses suffix-normalized rhyme clustering and syllable counting. UI/UX Styled with Tailwind CSS 4 and Radix UI, with multi-track mixing handled via the Web Audio API and waveform-playlist.
Challenges we ran into
Defining the "unexplored" space: AI tools already offer massive flexibility in generating sounds, but we realized the lyric space was still largely a "black box" of generic text. We spent hours riffing with mentors and sponsors, trying to figure out where we could actually contribute. Designing the agent: Designing the agent wasn't just engineering – it was musicology. We had to teach it the nuances of bridge transitions, tension and release, and song architecture so it could act as a peer, not a script. Balancing vibes and rigid songwriting constraints: Lyrics are a messy mix of math and soul. We had to build an editor that tracks rigid constraints – like syllable counts and rhyme density – without making the writer feel like they were filling out a spreadsheet. The challenge was keeping the creative flow alive while the engine calculated the structure in the background.
Accomplishments we're proud of
We successfully built a parallelized audio pipeline that races Modal (T4 GPUs) against Suno's native processing. Dropping the stem separation time from ~60s to ~20s wasn't just a performance win; it saved the "creative flow" of the entire app. The Lyric Coach actually coaches: Our client-side analysis engine doesn't just find rhymes; it genuinely improves writing. Seeing it catch clichés and filler words in real-time makes the AI feel like a rigorous editor rather than just a ghostwriter. Getting Claude Opus 4.6 to autonomously plan and execute a multi-track session – orchestrating lyrics, structure, and stems – was our biggest technical breakthrough. Watching it "think" through a song structure is a true "wow" moment.
What we learned
Agency > Automation: Most people don't want an AI to make a song for them; they want the AI to help them make a song better. Control is the most important feature we built. Hybrid Logic wins: LLMs are great for brainstorming, but they're bad at counting. Combining hard-coded rule-based analysis (syllable counting) with LLM rewrites gave us much better results than an LLM alone. When building for artists, you have to engineer for flow. In music, a 60-second wait for a stem separation kills the creative flow. We learned that engineering for speed – like our parallelized Modal + Suno pipeline – isn't just a technical "nice-to-have"; it's a requirement for staying in the "flow state."
What's next
Live vocal coaching. We want to move beyond lyrics and stems by adding real-time recording capabilities. Using the same logic as our lyric analyzer, we'll build a vocal coach that provides instant feedback on pitch, rhythm, and delivery as you record. Translate to different languages This is a fun challenge because translating a song isn't just swapping words – it's about preserving the rhyme and the rhythm. We want to build a tool that helps artists "port" their tracks into new languages without losing the syllable count or the "vibe."
Technical Deep Dive
1. Parallelized Stem Separation Pipeline
The biggest UX bottleneck in stem separation is latency. Suno's /stem endpoint splits a track into 12 stems but takes 60-120s. We couldn't ship that wait time.
Solution: Race two pipelines in parallel and deduplicate with a first-wins strategy.
Track complete ──┬── Modal Demucs (T4 GPU, htdemucs) ── 3 stems in ~20s
│
└── Suno /stem API ───────────────── 12 stems in 60-120s
│
deliveredStems (Set) ◄────┘
First pipeline to deliver each stem wins.
How it works:
- After Suno generation completes (
status=complete), we fire both pipelines simultaneously - A
Set<StemType>calleddeliveredStemstracks what's arrived — if Demucs deliversdrumsfirst, Suno'sdrumsis silently dropped - Core stems (drums, vocals, bass) buffer in a
pendingCoreMap. Once all 3 arrive — from whichever pipeline — we do an atomic swap: remove the full-mix placeholder layer, add 3 individual stem layers in one React state update. No flicker. - Non-core stems (guitar, keyboard, strings, etc.) go to
stemCachefor instant manual adds later - Demucs failure is swallowed with
.catch()— Suno handles all 12 stems as fallback. Zero degradation.
The Modal side: Our demucs_endpoint.py runs htdemucs (Hybrid Transformer Demucs) on a T4 GPU with pre-downloaded weights baked into the container image — no runtime download delay. One warm instance stays alive (keep_warm=1) to eliminate cold starts.
Result: Users get their first playable stems in ~20s instead of 60-120s. The remaining 9 stems trickle in via Suno's progressive polling while the user is already mixing.
2. Lyric Analysis Engine
We built a real-time lyric analysis system that runs entirely client-side — no round-trip to an LLM for basic feedback. It catches problems as you type.
Syllable counting uses the syllable npm package for per-line cadence analysis. We feed this into a cadence profiler (rap-theory.ts) that computes avg/min/max syllables, variance, and classifies flow as "tight," "balanced," or "loose."
Rhyme detection uses a custom phonetic normalization pipeline:
// English spelling is a disaster. We normalize before comparing.
const SUFFIX_NORMALIZATIONS: [RegExp, string][] = [
[/ight$/, "ite"], // "night" → "nite"
[/ould$/, "ood"], // "would" → "wood"
[/tion$/, "shun"], // "nation" → "nashun"
[/sion$/, "shun"], // "vision" → "vishun"
[/ck$/, "k"], // "rock" → "rok"
// ... 6 more rules
];
After normalization, we extract the last 3 characters as a rhymeKey and cluster lines that share endings. Lines with ≥2 matches form rhyme groups — this feeds into an ABAB rhyme scheme builder that labels patterns across verses.
Cliche detection matches against 48 hardcoded phrases ("heart on my sleeve," "dance in the rain," etc.) and highlights them inline. Filler word detection flags weak words ("basically," "literally," "you know"). Repetition tracking tokenizes the full lyric, counts unigrams appearing ≥3x and n-grams (2-3 word phrases) appearing ≥2x, and annotates them with "word" appears Nx labels.
On top of the client-side engine, we have an LLM-powered insight layer (/api/lyrics/analyze) that uses GPT-4o-mini to generate thematic analysis, rhyme targets (5 rhymes per target word), and writing tips — with a graceful fallback so the panel never breaks if the LLM fails.
3. Dual-Model AI Routing + Agent Mode
We don't use one model for everything. Different tasks need different tradeoffs:
| Mode | Model | Why |
|---|---|---|
| Normal | GPT-5 Nano | Fast, cheap. Good for "add more bass" or "make it darker." Sub-second responses. |
| Agent | Claude Opus 4.6 | Powerful multi-step reasoning. Can compose an entire track autonomously from "make me a lo-fi hip hop beat." |
The routing logic is dead simple — if agentMode is true, we always use Claude. Otherwise, the user toggles between OpenAI and Anthropic.
Agent mode is where it gets interesting. Claude Opus operates in a Plan → Execute → Observe → Reflect loop:
- Plan: The agent reasons about what a genre needs ("lo-fi hip hop typically has mellow drums, a jazzy bass, and vinyl-crackle FX")
- Execute: Calls
generate_track→ waits for stem separation → chainsadd_layercalls for cached stems - Observe: Parses enriched tool results that include cached stem lists and layer counts
- Reflect: Summarizes what was built and suggests next refinements
The loop is powered by Vercel AI SDK v6's sendAutomaticallyWhen: lastAssistantMessageIsCompleteWithToolCalls — when the assistant's response includes tool calls, the SDK automatically sends tool results back, creating a natural agent loop without custom orchestration.
Critical implementation detail: In agent mode, tool callbacks await the full Suno generation + stem separation pipeline and return detailed state. In normal mode, they fire-and-forget and return immediately. Same tools, different depth — because the agent needs rich context to chain decisions, but a human user just needs the UI to update.
6 tools available: generate_track, add_layer, regenerate_layer, remove_layer, set_lyrics, get_composition_state
System Architecture
┌─────────────────────────────────────────────────────────────────────┐
│ User (Browser) │
│ │
│ ┌──────────┐ ┌──────────┐ ┌───────────┐ ┌───────────────────┐ │
│ │ Chat │ │ Layer │ │ Waveform │ │ Transport + │ │
│ │ Panel │ │ Sidebar │ │ Display │ │ Master Volume │ │
│ │ │ │ │ │ │ │ │ │
│ │ Drag a │ │ Volume │ │ waveform- │ │ Web Audio API │ │
│ │ layer ──►│ │ Mute │ │ playlist │ │ (GainNode mixing) │ │
│ │ to chat │ │ Solo │ │ (canvas) │ │ │ │
│ └────┬─────┘ └──────────┘ └───────────┘ └───────────────────┘ │
│ │ │
└───────┼─────────────────────────────────────────────────────────────┘
│
▼
┌───────────────────────── Next.js API Routes ─────────────────────────┐
│ │
│ /api/chat ──────────┬──► GPT-5 Nano (normal mode) │
│ └──► Claude Opus 4.6 (agent mode) │
│ │ │
│ ▼ (tool calls) │
│ /api/generate ─────────► Suno /generate ──► poll /clips │
│ │ │
│ status=complete │ │
│ ▼ │
│ /api/stem ─────────────► Suno /stem (12 stems) ──┐ │
│ /api/stem-demucs ──────► Modal htdemucs (3 stems)─┤ RACE │
│ ▼ │
│ deliveredStems (Set) │
│ First-wins dedup │
│ │ │
│ /api/audio-proxy ◄───── CDN whitelist proxy ◄────┘ │
│ │
│ /api/lyrics/analyze ──► GPT-4o-mini (theme + rhyme targets) │
│ │
└──────────────────────────────────────────────────────────────────────┘
│ │
▼ ▼
┌──────────────┐ ┌──────────────────┐
│ Suno API │ │ Modal (T4 GPU) │
│ │ │ │
│ • Generate │ │ htdemucs │
│ • Stem (12) │ │ Pre-baked │
│ • Clips │ │ weights │
│ │ │ keep_warm=1 │
└──────────────┘ └──────────────────┘
Local Setup
git clone https://github.com/ads2280/treehacks26.git
cd treehacks26/app
cp .env.example .env.local
npm install
npm run dev
Environment Variables
| Variable | Required | What it does |
|---|---|---|
SUNO_API_KEY | Yes | Bearer token for Suno music generation + stem separation |
OPENAI_API_KEY | Yes | GPT-5 Nano (chat) + GPT-4o-mini (lyric analysis) + DALL-E 2 (video backgrounds) |
ANTHROPIC_API_KEY | Yes | Claude Opus 4.6 for agent mode |
HEYGEN_API_KEY | Yes | HeyGen API for music video generation (talking-photo avatars) |
MODAL_DEMUCS_URL | Optional | Modal Demucs endpoint. Falls back to Suno-only stems if not set. |
Modal Demucs (optional, but recommended)
pip install modal
modal deploy modal/demucs_endpoint.py
# Copy the deployed URL → MODAL_DEMUCS_URL
Commands
npm run dev # Dev server on :3000
npm run build # Production build
npm test # Vitest
npm run test:watch # Vitest watch
What We Built (and Why)
| Feature | Problem it solves | How it works |
|---|---|---|
| Parallel stem pipeline | 60-120s wait is a UX killer | Race Modal (T4) vs Suno, deduplicate with Set, atomic layer swap |
| Layer-by-layer composition | "I typed a prompt and got a song" isn't creative | Stems cached → instant add/remove, A/B comparison on regenerate |
| Agent mode | Complex compositions need multi-step reasoning | Claude Opus Plan→Execute→Observe→Reflect loop via AI SDK v6 |
| Lyric analysis engine | Writers need feedback, not just a text box | Client-side syllable/rhyme/cliche/repetition analysis + LLM insights |
| Drag-layer-to-chat | Targeting a specific layer by typing its name is friction | Drag from sidebar → chat prefixes message with layer context |
| Music video generation | A track without visuals isn't shareable | Selfie → HeyGen avatar → DALL-E background → lip-synced MP4 |
| Suno retry + normalization | Suno API returns inconsistent formats and rate-limits aggressively | Exponential backoff + Retry-After header + response normalization |
Analysis
View
Metric
- 26
- 17
- 9
Figures cover GitHub contributors during the hackathon window. A co-authored commit counts in full for each author, so per-member totals add up to more than the whole-team figures.
Technology
- AnthropicIn code
- CSSIn code
- Next.jsIn code
- OpenAIIn code
- PythonIn code
- ReactIn code
- Tailwind CSSIn code
- TypeScriptIn code
- Vercel AI SDKIn code
- VercelClaimed
9 of 10 appear in the indexed code. 1 claimed on Devpost could not be matched to code, which may simply mean the tool leaves no trace in the repository.
AI coding agents
- Claude CodeConfig · Commits
Detected from committed agent config files and commit authorship. Absence of a signal is not proof an agent was unused.
Codebase size
Source size
626 KB
Source files
137
Counts recognized source files only; vendored directories, binaries and lockfiles are excluded, so this is smaller than the repository on disk.
Repository
anikasomaia/producer
173 files · 4.1 MB · @ d922c81
Structure
Interface
110 files · 64%Screens, components and styles rendered to the user.
+2 moreAPI & routing
21 files · 12%Request entry points: routes, handlers and controllers.
Application logic
1 file · 1%Domain rules, services and shared utilities.
Supporting
Layers are inferred from where files sit in the tree, not from reading the code. A project that names its directories unconventionally will read oddly here — open the file browser to check anything the diagram implies.
Languages
- TypeScript89%
- Markdown8%
- CSS2%
- Python1%
Share of indexed source by file size. Binary and vendored files are excluded.
Dependencies
app/package.json
npm · 57- @ai-sdk/anthropic
- @ai-sdk/openai
- @ai-sdk/react
- @heygen/streaming-avatar
- @hookform/resolvers
- @radix-ui/react-accordion
- @radix-ui/react-alert-dialog
- @radix-ui/react-aspect-ratio
- @radix-ui/react-avatar
- @radix-ui/react-checkbox
- @radix-ui/react-collapsible
- @radix-ui/react-context-menu
- @radix-ui/react-dialog
- @radix-ui/react-slider
- @radix-ui/react-slot
- @radix-ui/react-toast
- @vercel/analytics
- @vercel/blob
- +39 more
Declared in the repository’s manifests at the indexed commit. A declared package is not proof it is used, and runtime dependencies are listed first.
This project’s features have not been analysed yet.
Export this project's context (description, README, evidence, key source files) to chat with an AI agent elsewhere.