Imported from spupuz/music-ai-multi-tool-hub (
AGENTS.md). Install upstream withnpx skills add spupuz/music-ai-multi-tool-hub. Copyright stays with the author.
Music AI Multi-Tool Hub AI Agent Instructions
All AI agents must conform to CONTEXT.md
Music AI Multi-Tool Hub is a comprehensive web application built with React 19, Vite, and TypeScript. It provides a suite of tools for AI music creators, integrating with services like Suno, Riffusion, and Google Gemini.
Development Environment
# Install dependencies
npm install
# Run locally for development
npm run dev
- Frontend: http://localhost:3000 (Vite dev server)
- AI Features: Calls
gemini-proxy.spupuz.workers.dev(Cloudflare Worker) — requires internet connection.
Architecture Overview
Frontend Structure (/)
The application follows a tool-based modular architecture centered around a main layout.
/
├── Layout.tsx # Main application shell and tool registry
├── Sidebar.tsx # Navigation and tool categorization
├── services/ # API abstractions and external integrations
├── components/ # Reusable UI components (Spinner, Header, etc.)
├── hooks/ # Custom React hooks for tool logic
├── utils/ # Shared utility functions (math, music theory)
└── [ToolName]Tool.tsx # Individual tool components (e.g., SunoMusicPlayerTool.tsx)
Key patterns:
- Tool Registry: Tools are defined in
Layout.tsxand partitioned by categories. - Service Layer: External API calls are abstracted into
services/(e.g.,sunoService.ts,aiAnalysisService.ts). - Context: Global state like theme is managed via
ThemeContext.tsx. - Styling: TailwindCSS for utility-first styling.
Critical Patterns
Suno Audio Access (TOS-Compliant)
Suno's Terms of Service (rev. 2026-08-10, effective 2026-09-03) prohibit obtaining a copy of an Output "by any means other than a download channel made available by Suno (for example, recording or stream ripping)". The official download policy only permits streaming on/through Suno — its own player, links, and the official /embed/ player. This means loading a raw Suno CDN media file (audio_url .mp3, video_url .mp4, or the d2lwuy8qc234o3.cloudfront.net/1/clip/<id>.m4a bucket) into our own players/analysis tools is not TOS-compliant (equivalent to stream-ripping). Follow these rules:
- NEVER stream Suno CDN media (
.m4a,.mp3,.mp4) into Howler/WaveSurfer/<audio>. Thevideo_urlmp4 fallback is NOT compliant — only the official embed or a user-uploaded file is allowed. - Music Player (
useSunoAudioPlayer.ts+SunoMusicPlayerTool.tsx): Suno clips always render the official Suno iframehttps://suno.com/embed/<clipId>?autoplay=1(viaembedClipIdstate). EQ/Snippet/seek/volume are disabled in Embed Mode — ownership moves to Suno's player. Only Riffusion / Flow Music clips (song.source === 'riffusion') stream directly through Howler, using their own accessible GCS.m4aURLs fromriffusionService.ts. - Analysis tools (MP3 Cutter, BPM Tapper, Lyrics Synchronizer): never auto-fetch Suno audio. They populate the song's metadata (title/artist/cover) and instruct the user to download an MP3 via Suno's official button and upload it. Riffusion URLs still auto-load their accessible GCS audio.
- Compliance tool: preview via the Suno iframe embed, not an
<audio>tag. - Use
isAudioUrlBroken(url)(inservices/sunoService.ts) to detect theforbiddenmarker;getSunoEmbedUrl(clipId)builds the official embed URL.
Tool Component Pattern
Each tool is a React component receiving ToolProps. Navigation between tools should be handled via the onNavigate prop.
// Pattern: Tool Component
import React from 'react';
import { ToolProps } from './Layout';
const MyNewTool: React.FC<ToolProps> = ({ trackLocalEvent, onNavigate }) => {
const handleAction = () => {
trackLocalEvent('MyTool', 'ButtonClicked');
// ... logic
};
return <div className="...">...</div>;
};
Service Integration Pattern
API services should handle retries, rate limiting, and provide progress updates via callbacks where beneficial.
// Pattern: Async Service with Progress
export const fetchMyData = async (
id: string,
onProgress?: (msg: string) => void
) => {
if (onProgress) onProgress("Starting fetch...");
// Use try/catch with exponential backoff for rate limits (429)
// ...
};
State & Event Tracking
The application uses localStorage for data persistence and local statistics tracking via trackLocalEvent.
// Pattern: Local Event Tracking
trackLocalEvent('ToolCategory', 'ActionName', 'Label', value);
Mobile-First Responsiveness Patterns
The application prioritizes a seamless mobile experience (320px+). Follow these patterns to prevent horizontal overflow and maximize space:
- Aggressive Container Padding: On small screens, reduce or remove container padding to reclaim pixels. Use
p-0orp-1for mobile and scale up (sm:p-6) for larger viewports. - Responsive Tables:
- Abbreviate column headers on mobile using conditional rendering:
<span className="sm:hidden">Plays</span> <span className="hidden sm:inline">Avg Plays</span>. - Reduce font size (
text-[9px]ortext-[10px]) and cell padding (px-1) for narrow viewports. - Round large decimals or use
toLocaleString()to keep cell content compact.
- Abbreviate column headers on mobile using conditional rendering:
- Chart Optimization:
- Track
screenWidthto dynamically adjustChart.jsoptions (layout padding, tooltips, axis titles). - Hide non-essential axis titles on mobile (
display: screenWidth > 640). - Use
ticks.paddingandticks.font.sizeto prevent labels from hitting container edges.
- Track
- Text Scaling: Use responsive font sizes for titles (e.g.,
text-xl sm:text-2xl) and ensure single-line headers usetruncateortext-ellipsisto prevent wrapping.
UI/UX Design Standards
To maintain a consistent and professional look across all tools, follow these design rules:
- Icon Placement: Icons (including loading spinners) MUST always be placed before (to the left of) the text, never above or below it.
- Good:
[Icon] Processing... - Bad:
[Icon] Processing... - Use
flex-rowanditems-centerto ensure horizontal alignment. - When using the
Buttoncomponent, prefer thestartIconprop for loading indicators or action icons.
- Good:
Anti-Pattern 1: Direct Fetch in Components
Bad: Calling fetch() or heavy logic directly inside a useEffect or event handler in a UI component.
useEffect(() => {
fetch('https://api.suno.com/...'); // BAD! Not abstracted or reusable.
}, []);
Good: Abstract the logic into a service file in services/.
Anti-Pattern 2: Blocking the UI
Bad: Performing heavy data processing (like large array transformations) on the main thread without consideration.
Good: Use setTimeout chunks or ensure logic is optimized.
Anti-Pattern 3: Hardcoded Secrets
Bad: Using environment variables without checking for existence or exposing them in logs.
Good: Access via process.env and provide fallbacks or clear error messages.
Security & Data Privacy
- Cloudflare Worker: All Gemini API calls, password verification, and Suno API proxying go through
gemini-proxy.spupuz.workers.dev. Secrets live exclusively in the Worker — never in source code or the JS bundle. - Never commit secrets:
.env,.env.*,.dev.vars, and.wrangler/must stay untracked (already in.gitignore). Verify withgit ls-files | grep -E "\.env|dev\.vars|\.wrangler"(must be empty). If.envever becomes tracked,git rm --cached .envimmediately. wrangler.toml: must never contain secrets — only non-secret bindings (names, KV namespace IDs).GEMINI_API_KEY/COMMITTEE_PASSWORDare set viawrangler secret putor the Cloudflare dashboard, never committed.- Local Privacy: Sensitive user data should be kept in local state/storage and never leaked to external logs.
AI-Assisted Contributions
Contribution Template
## Summary
[Description of changes]
## Changes
- [Component/Service]: [Change details]
- [Logic]: [Implementation details]
## Verification
- [ ] `npm run build` successful
- [ ] Tool loads correctly in `Layout.tsx`
- [ ] Service calls handle errors/rate limits