Crate Web v0.1.0: Full workspace with AI research, OpenUI, and team features#2
Crate Web v0.1.0: Full workspace with AI research, OpenUI, and team features#2tmoody1973 wants to merge 472 commits intorelease/v0.1.0from
Conversation
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
…pty embeds - SaveTinyDeskButton now searches YouTube for each connected artist - Carries over pullQuote, sonicElements, keyWorks to companion nodes - VideoInfluenceChain skips iframe embed when videoId is empty
…client-side YouTube scrape
…companion save - 30s max duration on enrich API for Vercel - 5s timeout per YouTube scrape to prevent hanging - Block save when influence chain has zero connections
- New /api/tinydesk/save endpoint handles all enrichment + Convex write - SaveTinyDeskButton simplified to thin POST caller - Convex mutation rejects empty nodes
- Empty companion pages show "Generate Musical DNA in Crate" link - Added deleteBySlug mutation for companion cleanup - Deleted broken Nora Brown companion (empty nodes)
Shows what Crate is doing based on the last completed step: "Analyzing influence connections...", "Reading reviews and citations...", "Building playlist...", etc.
- Before/after split screen: "What You See" (YouTube) vs "What Crate Reveals" (influence chain) - Split screen is dominant element, heading reduced to label - Mobile: cards first, video second - How It Works 3-step strip - DNA-Ready artists horizontal scroll section - Renamed from "Tiny Desk Catalog" to "Tiny Desk DNA" - Updated OG metadata and copy
- Extract resolveYoutubeId/resolveGenre/resolveConnectionVideos to src/lib/tinydesk-enrichment.ts (was duplicated in save + enrich routes) - Extract TinyDeskPicker to src/components/workspace/tinydesk-picker.tsx (was inline in chat-panel) - Move getThinkingLabel to src/lib/tool-labels.ts (co-located with getToolLabel) - chat-panel.tsx: 1471 → 1269 lines - save/route.ts: 208 → 124 lines - enrich/route.ts: 108 → 41 lines
- Header: Crate logo × Tiny Desk DNA logo side by side - Hero: SVG logo replaces text heading, sr-only h1 for accessibility
- Companion pages show "Watch on NPR" link when sourceUrl exists in catalog - Header: Tiny Desk DNA logo 70px, hero logo 120px
- New section between DJ Showcase and Pricing with before/after preview - Shows Beth Gibbons influence chain preview with source badges + sonic tags - "EXPLORE TINY DESK DNA" CTA linking to /tinydesk - Added "TINY DESK DNA" to landing page nav
- New feature section with companion pages, /tinydesk command, community catalog - Updated project structure with tinydesk components, API routes, and lib
Every research session now silently captures tool results into per-artist wiki pages. Session-end synthesis via Haiku merges data, deduplicates, and flags contradictions between sources. - convex/schema.ts: wikiPages, wikiIndexEntries, wikiLogEntries tables - convex/wiki.ts: CRUD mutations, access-controlled queries, Haiku synthesis action with retry, internal query/mutation bridge - src/lib/wiki-ingest.ts: per-tool extractors for 9 data sources - src/lib/agentic-loop.ts: onToolComplete callback for wiki ingestion - src/app/api/chat/route.ts: wire wiki upserts + session-end synthesis - src/app/wiki/[username]/[slug]/page.tsx: V2-C split layout detail page - src/app/wiki/page.tsx: bold editorial index with empty state - src/components/sidebar/wiki-section.tsx: sidebar badge with entry count - src/lib/slug.ts: shared canonical slugify utility Security: getBySlug uses Convex auth (ctx.auth.getUserIdentity()) for access control. Private pages only visible to authenticated owner.
ConvexHttpClient in server components doesn't carry Clerk JWT tokens, so ctx.auth.getUserIdentity() was always null. Private pages returned null → 404 for the owner. Fix: pass viewerClerkId from Clerk auth() in the server component to the Convex query, which checks it against the page owner's clerkId.
…ty toggle
- Index page title: "{First Name}'s Music Wiki" instead of generic "Your Music Wiki"
- Crate logo in header matching /tinydesk pattern (sticky, dark blue bg)
- Interactive visibility segmented control (Private | Unlisted | Public) on detail page
- Owner sees toggle, visitors see read-only badge
- Public entries show green badge on index page
- "Back to Chat" link in index header
Previous extractors tried to parse specific JSON shapes per tool but missed most data. New approach: find artist name via common field patterns, pass the FULL tool result content through to Haiku synthesis. The synthesis step structures everything. Also set ANTHROPIC_API_KEY in Convex env so synthesis actually runs.
…, lastfm, discogs, etc)
…r display Synthesis was failing with ArgumentValidationError because Haiku returns extra fields (snippet, type, name) that the strict Convex validators reject. Now sanitizes all fields to match validator shapes exactly. Detail page now formats raw JSON sections into readable text — extracts influence connections, review snippets, and readable fields instead of dumping raw JSON.
Three performance and UX improvements: 1. Shared wiki: getSharedBySlug query finds the richest wiki page for an artist across ALL users. Everyone's research compounds. 2. Wiki-first response: before running the full agentic loop for /influence, /story, /prep commands, check if wiki data exists. Inject existing knowledge as system prompt context so the LLM builds on prior research instead of starting from scratch. 3. Parallel tool execution: executeTools now fires all tools with Promise.all instead of running them sequentially. When Claude requests 3 tools in one turn, they run concurrently. Before: tool1 (3s) → tool2 (2s) → tool3 (4s) = 9s After: tool1 + tool2 + tool3 = 4s (max of three)
- toggleVisibility/archivePage: verify ownership via Convex auth (ctx.auth.getUserIdentity) instead of trusting client-supplied userId - getSharedBySlug: filter out private pages to prevent leaking private research into other users' wiki-first context - Cap wiki-first context injection to 3000 chars to prevent context window bloat - Remove userId prop from VisibilityToggle component
Remaining items from code review:
1. usernameSlug: added field + by_username_slug index to users table.
getBySlug now queries by index instead of scanning all users.
Computed on user create/update in users.upsert mutation.
2. Scheduled synthesis: replaced fire-and-forget convex.action()
from serverless route with scheduleSynthesis mutation that uses
ctx.scheduler.runAfter(). Synthesis survives function termination.
synthesizeWikiPage is now an internalAction.
3. Test suite: 30 tests across 2 files.
- 21 tests for wiki-ingest.ts extractors (all tool servers,
edge cases, JSON→readable conversion, special characters)
- 9 tests for slug.ts (spaces, ampersands, unicode, empty)
- Added vitest as dev dependency + config
Also fixed: Last.fm tag objects vs Bandcamp tag strings, Discogs year
extraction, items array handling, text pattern matching for influence
chain content.
What changed
Complete Crate Web workspace implementation — from bare Next.js scaffold to a fully functional AI music research platform with persistent chat, dynamic UI components, team key sharing, multi-model support, and AgentMail integration.
Why
Building the web companion to Crate CLI so Radio Milwaukee team members and external users can access AI-powered music research through a browser without needing a terminal.
Changes
Core Workspace
OpenUI Dynamic Components
Multi-Model Support
ANTHROPIC_BASE_URLto OpenRouter endpoint for non-Anthropic modelsTeam Features
@domainteammatesy3v9l8q1c8s3d4n6@88nine.slack.com) or any emailBug Fixes
Testing
tsc --noEmit)next build)Notes for CodeRabbit
OpenUI Lang) — thesplitContent()parser is intentionally simple.@x402/fetchpeer dependency (installed explicitly).AGENTMAIL_API_KEYenv var fallback in/api/emailis intentional for team usage where not every user needs their own key.Related
6ed38df(initial Next.js scaffold)🤖 Generated with Claude Code