Function bodies 245 total
middleware function · typescript · L4-L55 (52 LOC)middleware.ts
export async function middleware(request: NextRequest) {
let supabaseResponse = NextResponse.next({
request,
});
const supabase = createServerClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
{
cookies: {
getAll() {
return request.cookies.getAll();
},
setAll(cookiesToSet) {
cookiesToSet.forEach(({ name, value }) =>
request.cookies.set(name, value)
);
supabaseResponse = NextResponse.next({
request,
});
cookiesToSet.forEach(({ name, value, options }) =>
supabaseResponse.cookies.set(name, value, options)
);
},
},
}
);
const {
data: { user },
} = await supabase.auth.getUser();
// Redirect unauthenticated users to login (except for auth pages)
const isAuthPage =
request.nextUrl.pathname === "/login" ||
request.nextUrl.pathname === "/signup";
if (!usePOST function · typescript · L19-L86 (68 LOC)src/app/api/analysis/summarize/route.ts
export async function POST(request: Request) {
try {
const { analysisId, analysis, title } = await request.json();
if (!analysis || !analysisId) {
return Response.json({ error: "Missing analysis data" }, { status: 400 });
}
const NOTE_NAMES = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"];
function midiToNote(midi: number): string {
return `${NOTE_NAMES[midi % 12]}${Math.floor(midi / 12) - 1}`;
}
// Build chord progression string
const chordProgression = (analysis.chords ?? [])
.map((c: { chord: string; time: number; duration: number }) =>
`${c.chord} (${formatTime(c.time)}, ${c.duration.toFixed(1)}s)`
)
.join(" | ");
// Note range
const notes = analysis.notes ?? [];
const midiValues = notes.map((n: { midi: number }) => n.midi);
const minNote = midiValues.length > 0 ? midiToNote(Math.min(...midiValues)) : "N/A";
const maxNote = midiValues.length > 0 ? midiToNote(Math.max(.midiToNote function · typescript · L28-L30 (3 LOC)src/app/api/analysis/summarize/route.ts
function midiToNote(midi: number): string {
return `${NOTE_NAMES[midi % 12]}${Math.floor(midi / 12) - 1}`;
}formatTime function · typescript · L88-L92 (5 LOC)src/app/api/analysis/summarize/route.ts
function formatTime(seconds: number): string {
const m = Math.floor(seconds / 60);
const s = Math.floor(seconds % 60);
return `${m}:${s.toString().padStart(2, "0")}`;
}resolveFfmpegPath function · typescript · L9-L17 (9 LOC)src/app/api/audio/[id]/route.ts
function resolveFfmpegPath(): string {
if (process.env.FFMPEG_PATH) return process.env.FFMPEG_PATH;
try {
// eslint-disable-next-line @typescript-eslint/no-require-imports
const p = require("ffmpeg-static");
if (p) return p;
} catch { /* ignore */ }
return "ffmpeg";
}isALAC function · typescript · L21-L29 (9 LOC)src/app/api/audio/[id]/route.ts
function isALAC(bytes: Uint8Array): boolean {
const searchLen = Math.min(bytes.length, 500000);
for (let i = 0; i < searchLen - 3; i++) {
if (bytes[i] === 0x61 && bytes[i+1] === 0x6c && bytes[i+2] === 0x61 && bytes[i+3] === 0x63) {
return true;
}
}
return false;
}transcodeToAAC function · typescript · L31-L63 (33 LOC)src/app/api/audio/[id]/route.ts
async function transcodeToAAC(inputBuffer: ArrayBuffer): Promise<Buffer> {
const dir = await mkdtemp(join(tmpdir(), "audio-"));
const inputPath = join(dir, "input.m4a");
const outputPath = join(dir, "output.m4a");
try {
await writeFile(inputPath, Buffer.from(inputBuffer));
await access(ffmpegPath).catch(() => {
throw new Error(`ffmpeg not found at: ${ffmpegPath}`);
});
await new Promise<void>((resolve, reject) => {
execFile(
ffmpegPath,
["-i", inputPath, "-c:a", "aac", "-b:a", "192k", "-movflags", "+faststart", "-y", outputPath],
{ timeout: 120000 },
(error, _stdout, stderr) => {
if (error) {
console.error("[TRANSCODE] ffmpeg error:", error.message, stderr);
reject(error);
} else {
resolve();
}
}
);
});
return await readFile(outputPath);
} finally {
await unlink(inputPath).catch(() => {});
await unlink(outputPath).catchPowered by Repobility — scan your code at https://repobility.com
resolveRecording function · typescript · L74-L98 (25 LOC)src/app/api/audio/[id]/route.ts
async function resolveRecording(id: string) {
const supabase = await createClient();
const { data } = await supabase
.from("recordings")
.select(RECORDING_COLUMNS)
.eq("id", id)
.single();
if (data) return { recording: data as RecordingRow, client: supabase, owned: true };
// Fallback for shared recordings
const anonClient = createAnonClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!
);
const { data: shared } = await anonClient
.from("recordings")
.select(RECORDING_COLUMNS)
.eq("id", id)
.not("share_token", "is", null)
.single();
if (shared) return { recording: shared as RecordingRow, client: anonClient, owned: false };
return null;
}GET function · typescript · L102-L211 (110 LOC)src/app/api/audio/[id]/route.ts
export async function GET(
request: NextRequest,
{ params }: { params: Promise<{ id: string }> }
) {
const { id } = await params;
const result = await resolveRecording(id);
if (!result) {
return NextResponse.json({ error: "Recording not found" }, { status: 404 });
}
const { recording, client } = result;
// Check query param to know if client needs transcoded version
const needsTranscode = request.nextUrl.searchParams.get("transcode") === "1";
if (!needsTranscode) {
// If a persisted AAC transcode exists, serve that instead of the original
const fileToSign = recording.aac_file_name ?? recording.file_name;
const { data: signedData } = await client.storage
.from("recordings")
.createSignedUrl(fileToSign, 3600);
if (signedData?.signedUrl) {
return NextResponse.json({
url: signedData.signedUrl,
codec: recording.aac_file_name ? "aac" : (recording.audio_codec ?? null),
hasAac: !!recording.aac_file_name,
PATCH function · typescript · L213-L252 (40 LOC)src/app/api/audio/[id]/route.ts
export async function PATCH(
request: NextRequest,
{ params }: { params: Promise<{ id: string }> }
) {
const { id } = await params;
const supabase = await createClient();
// Verify the user owns this recording
const { data: recording } = await supabase
.from("recordings")
.select("id")
.eq("id", id)
.single();
if (!recording) {
return NextResponse.json({ error: "Recording not found" }, { status: 404 });
}
const body = await request.json();
// Save waveform peaks (and optionally duration)
if (body.waveform_peaks) {
const updates: Record<string, unknown> = { waveform_peaks: body.waveform_peaks };
if (typeof body.duration === "number" && body.duration > 0) {
updates.duration = body.duration;
}
const { error } = await supabase
.from("recordings")
.update(updates)
.eq("id", id);
if (error) {
return NextResponse.json({ error: error.message }, { status: 500 });
}
return NextResponse.json(POST function · typescript · L5-L22 (18 LOC)src/app/api/chat/compare/route.ts
export async function POST(request: Request) {
const { messages, analysisA, analysisB, titleA, titleB } = await request.json();
const systemPrompt = buildCompareSystemPrompt(
titleA,
analysisA,
titleB,
analysisB
);
const result = streamText({
model: defaultModel,
system: systemPrompt,
messages,
});
return result.toDataStreamResponse();
}POST function · typescript · L5-L24 (20 LOC)src/app/api/chat/insights/route.ts
export async function POST(request: Request) {
const { messages, analyses } = await request.json();
const systemPrompt = buildInsightsSystemPrompt(
analyses.map((a: { title: string; key_signature: string | null; tempo: number | null; chords: { chord: string }[] }) => ({
recording_title: a.title,
key_signature: a.key_signature,
tempo: a.tempo,
chords: a.chords,
}))
);
const result = streamText({
model: defaultModel,
system: systemPrompt,
messages,
});
return result.toDataStreamResponse();
}POST function · typescript · L6-L49 (44 LOC)src/app/api/chat/route.ts
export async function POST(request: Request) {
try {
const { messages, recordingId, analysis } = await request.json();
if (!messages || !Array.isArray(messages)) {
return new Response("Invalid messages format", { status: 400 });
}
const systemPrompt = buildRecordingSystemPrompt(analysis);
const result = streamText({
model: defaultModel,
system: systemPrompt,
messages: messages.map((m: { role: string; content: string }) => ({
role: m.role as "user" | "assistant",
content: m.content,
})),
});
// Fire-and-forget: save user message without blocking the stream
const lastUserMessage = messages[messages.length - 1];
if (lastUserMessage?.role === "user") {
createClient().then(async (supabase) => {
const { data: { user } } = await supabase.auth.getUser();
if (user) {
await supabase.from("chat_messages").insert({
recording_id: recordingId,
user_id: user.POST function · typescript · L19-L58 (40 LOC)src/app/api/insights/summarize/route.ts
export async function POST(request: Request) {
try {
const { analyses } = await request.json();
if (!analyses || !Array.isArray(analyses) || analyses.length === 0) {
return Response.json({ error: "No analyses provided" }, { status: 400 });
}
const recordingSummaries = analyses.map((a: {
title: string;
key_signature: string | null;
tempo: number | null;
chords: { chord: string }[];
}) => {
const uniqueChords = [...new Set(a.chords.map((c) => c.chord))];
return `- "${a.title}" — Key: ${a.key_signature ?? "?"}, Tempo: ${a.tempo ? `~${a.tempo} BPM` : "?"}, Chords: ${uniqueChords.slice(0, 10).join(", ")}`;
}).join("\n");
const prompt = `Analyze this library of ${analyses.length} piano voice memo recordings and generate insights.
## Recordings
${recordingSummaries}
Group similar recordings into clusters based on shared musical characteristics (key, chord vocabulary, tempo, style). Identify any standout recordings thgetCreationDate function · typescript · L6-L58 (53 LOC)src/app/api/recordings/fix-dates/route.ts
function getCreationDate(buf: ArrayBuffer): Date | null {
const view = new DataView(buf);
// Scan top-level atoms to find moov
let offset = 0;
while (offset + 8 <= view.byteLength) {
let size = view.getUint32(offset);
const type = String.fromCharCode(
view.getUint8(offset + 4), view.getUint8(offset + 5),
view.getUint8(offset + 6), view.getUint8(offset + 7)
);
// Handle 64-bit extended size (size field = 1)
let headerSize = 8;
if (size === 1 && offset + 16 <= view.byteLength) {
const hi = view.getUint32(offset + 8);
const lo = view.getUint32(offset + 12);
size = hi * 4294967296 + lo;
headerSize = 16;
}
if (size < 8) break;
if (type === "moov") {
const end = Math.min(offset + size, view.byteLength);
let inner = offset + headerSize;
while (inner + 20 <= end) {
const atomSize = view.getUint32(inner);
const atomType = String.fromCharCode(
view.getUint8(inner + 4), All rows above produced by Repobility · https://repobility.com
POST function · typescript · L60-L108 (49 LOC)src/app/api/recordings/fix-dates/route.ts
export async function POST() {
const supabase = await createClient();
const { data: { user } } = await supabase.auth.getUser();
if (!user) {
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
}
const { data: recordings, error } = await supabase
.from("recordings")
.select("id, file_name, recorded_at")
.eq("user_id", user.id);
if (error || !recordings) {
return NextResponse.json({ error: "Failed to fetch recordings" }, { status: 500 });
}
const results = [];
for (const rec of recordings) {
const { data: fileData, error: dlError } = await supabase.storage
.from("recordings")
.download(rec.file_name);
if (dlError || !fileData) {
results.push({ id: rec.id, file: rec.file_name, oldDate: rec.recorded_at, newDate: null, error: dlError?.message });
continue;
}
const buf = await fileData.arrayBuffer();
const creationDate = getCreationDate(buf);
if (creationDate) {
const newDate GET function · typescript · L4-L22 (19 LOC)src/app/api/recordings/[id]/analysis/route.ts
export async function GET(
_request: NextRequest,
{ params }: { params: Promise<{ id: string }> }
) {
const { id } = await params;
const supabase = await createClient();
const { data, error } = await supabase
.from("analyses")
.select("*")
.eq("recording_id", id)
.single();
if (error) {
return NextResponse.json({ error: error.message }, { status: 404 });
}
return NextResponse.json(data);
}POST function · typescript · L24-L49 (26 LOC)src/app/api/recordings/[id]/analysis/route.ts
export async function POST(
request: NextRequest,
{ params }: { params: Promise<{ id: string }> }
) {
const { id } = await params;
const supabase = await createClient();
const body = await request.json();
const { data, error } = await supabase
.from("analyses")
.upsert(
{
recording_id: id,
...body,
},
{ onConflict: "recording_id" }
)
.select()
.single();
if (error) {
return NextResponse.json({ error: error.message }, { status: 500 });
}
return NextResponse.json(data);
}CollectionDetailLoading function · typescript · L1-L25 (25 LOC)src/app/(app)/collections/[id]/loading.tsx
export default function CollectionDetailLoading() {
return (
<div className="space-y-6 animate-pulse">
<div>
<div className="h-8 w-48 rounded bg-muted" />
<div className="mt-2 h-4 w-32 rounded bg-muted" />
</div>
<div className="space-y-3">
{Array.from({ length: 4 }).map((_, i) => (
<div
key={i}
className="flex items-center gap-4 rounded-xl border bg-card px-6 py-4"
>
<div className="h-10 w-10 shrink-0 rounded-lg bg-muted" />
<div className="flex-1 space-y-2">
<div className="h-4 w-48 rounded bg-muted" />
<div className="h-3 w-32 rounded bg-muted" />
</div>
</div>
))}
</div>
</div>
);
}CollectionPage function · typescript · L5-L57 (53 LOC)src/app/(app)/collections/[id]/page.tsx
export default async function CollectionPage({
params,
}: {
params: Promise<{ id: string }>;
}) {
const { id } = await params;
const supabase = await createClient();
const { data: collection } = await supabase
.from("collections")
.select("*")
.eq("id", id)
.single();
if (!collection) notFound();
// Get recordings in this collection
const { data: items } = await supabase
.from("collection_recordings")
.select("position, recording:recordings(id, title, duration, created_at)")
.eq("collection_id", id)
.order("position");
const recordings = (items ?? [])
.map((item) => ({
position: item.position,
...(item.recording as unknown as { id: string; title: string; duration: number | null; created_at: string }),
}))
.filter((r) => r.id);
// Get ALL user recordings to power the "add recording" picker
const { data: allRecordings } = await supabase
.from("recordings")
.select("id, title, duration, created_at")CollectionsLoading function · typescript · L1-L19 (19 LOC)src/app/(app)/collections/loading.tsx
export default function CollectionsLoading() {
return (
<div className="space-y-6 animate-pulse">
<div className="flex items-center justify-between">
<div className="h-8 w-40 rounded bg-muted" />
<div className="h-9 w-32 rounded bg-muted" />
</div>
<div className="grid gap-4 sm:grid-cols-2 lg:grid-cols-3">
{Array.from({ length: 6 }).map((_, i) => (
<div key={i} className="rounded-xl border bg-card p-6 space-y-3">
<div className="h-5 w-32 rounded bg-muted" />
<div className="h-3 w-20 rounded bg-muted" />
</div>
))}
</div>
</div>
);
}CollectionsPage function · typescript · L7-L59 (53 LOC)src/app/(app)/collections/page.tsx
export default async function CollectionsPage() {
const supabase = await createClient();
const { data: collections } = await supabase
.from("collections")
.select("*, collection_recordings(count)")
.order("created_at", { ascending: false });
return (
<div className="space-y-6">
<div className="flex items-center justify-between">
<div>
<h1 className="text-2xl font-bold">Collections</h1>
<p className="text-muted-foreground">
Organize recordings into themed collections
</p>
</div>
<CreateCollectionDialog />
</div>
{collections && collections.length > 0 ? (
<div className="grid gap-4 sm:grid-cols-2 lg:grid-cols-3">
{collections.map((collection) => (
<Link key={collection.id} href={`/collections/${collection.id}`}>
<Card className="cursor-pointer transition-colors hover:bg-accent/50">
<CardHeader className="pb-2">
formatDuration function · typescript · L32-L36 (5 LOC)src/app/(app)/compare/page.tsx
function formatDuration(seconds: number): string {
const m = Math.floor(seconds / 60);
const s = Math.floor(seconds % 60);
return `${m}:${s.toString().padStart(2, "0")}`;
}Provenance: Repobility (https://repobility.com) — every score reproducible from /scan/
noteRange function · typescript · L38-L47 (10 LOC)src/app/(app)/compare/page.tsx
function noteRange(notes: { midi: number }[] | null): string {
if (!notes || notes.length === 0) return "--";
const NOTE_NAMES = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"];
const sorted = [...notes].sort((a, b) => a.midi - b.midi);
const lo = sorted[0].midi;
const hi = sorted[sorted.length - 1].midi;
const loName = `${NOTE_NAMES[lo % 12]}${Math.floor(lo / 12) - 1}`;
const hiName = `${NOTE_NAMES[hi % 12]}${Math.floor(hi / 12) - 1}`;
return `${loName} -- ${hiName}`;
}ComparisonRow function · typescript · L49-L82 (34 LOC)src/app/(app)/compare/page.tsx
function ComparisonRow({
label,
valueA,
valueB,
}: {
label: string;
valueA: string;
valueB: string;
}) {
const match = valueA === valueB && valueA !== "--";
return (
<div className="grid grid-cols-[1fr_auto_1fr] items-center gap-4 border-b border-border py-3 last:border-0">
<span className="text-right font-mono text-sm">{valueA}</span>
<div className="flex flex-col items-center gap-1">
<span className="text-xs uppercase tracking-widest text-muted-foreground">
{label}
</span>
{valueA !== "--" && valueB !== "--" && (
<Badge
variant={match ? "default" : "outline"}
className={
match
? "bg-neutral-800 text-neutral-100 dark:bg-neutral-200 dark:text-neutral-900"
: ""
}
>
{match ? "Match" : "Differs"}
</Badge>
)}
</div>
<span className="font-mono text-sm">{valueB}</span>
</div>
);
CompareChat function · typescript · L90-L185 (96 LOC)src/app/(app)/compare/page.tsx
function CompareChat({
titleA,
titleB,
analysisA,
analysisB,
}: {
titleA: string;
titleB: string;
analysisA: FullAnalysis;
analysisB: FullAnalysis;
}) {
const scrollRef = useRef<HTMLDivElement>(null);
const chatKey = `${titleA}-${titleB}`;
const { messages, input, handleInputChange, handleSubmit, isLoading, append } =
useChat({
api: "/api/chat/compare",
body: { analysisA, analysisB, titleA, titleB },
id: chatKey,
});
useEffect(() => {
if (scrollRef.current) {
scrollRef.current.scrollTop = scrollRef.current.scrollHeight;
}
}, [messages]);
return (
<Card>
<CardHeader className="pb-2">
<CardTitle className="text-base font-medium tracking-tight">
AI Comparison Chat
</CardTitle>
<p className="text-xs text-muted-foreground">
Ask about the relationship between these two recordings
</p>
</CardHeader>
<CardContent>
<div className="flex h-[300pxComparePage function · typescript · L187-L447 (261 LOC)src/app/(app)/compare/page.tsx
export default function ComparePage() {
const [recordings, setRecordings] = useState<Recording[]>([]);
const [loading, setLoading] = useState(true);
const [idA, setIdA] = useState<string>("");
const [idB, setIdB] = useState<string>("");
useEffect(() => {
async function fetchRecordings() {
const supabase = createClient();
const { data } = await supabase
.from("recordings")
.select(
"id, title, duration, analyses(key_signature, tempo, time_signature, chords, notes, summary, status)"
)
.order("created_at", { ascending: false });
if (data) {
const mapped: Recording[] = data.map((r) => ({
id: r.id,
title: r.title,
duration: r.duration,
analyses: Array.isArray(r.analyses)
? r.analyses[0] ?? null
: r.analyses,
}));
setRecordings(mapped);
}
setLoading(false);
}
fetchRecordings();
}, []);
const recA = recordifetchRecordings function · typescript · L194-L215 (22 LOC)src/app/(app)/compare/page.tsx
async function fetchRecordings() {
const supabase = createClient();
const { data } = await supabase
.from("recordings")
.select(
"id, title, duration, analyses(key_signature, tempo, time_signature, chords, notes, summary, status)"
)
.order("created_at", { ascending: false });
if (data) {
const mapped: Recording[] = data.map((r) => ({
id: r.id,
title: r.title,
duration: r.duration,
analyses: Array.isArray(r.analyses)
? r.analyses[0] ?? null
: r.analyses,
}));
setRecordings(mapped);
}
setLoading(false);
}InsightsLoading function · typescript · L1-L24 (24 LOC)src/app/(app)/insights/loading.tsx
export default function InsightsLoading() {
return (
<div className="space-y-6 animate-pulse">
<div className="h-8 w-40 rounded bg-muted" />
{/* Stats cards */}
<div className="grid gap-4 sm:grid-cols-2 lg:grid-cols-4">
{Array.from({ length: 4 }).map((_, i) => (
<div key={i} className="rounded-xl border bg-card p-6 space-y-2">
<div className="h-3 w-20 rounded bg-muted" />
<div className="h-7 w-16 rounded bg-muted" />
</div>
))}
</div>
{/* Content area */}
<div className="space-y-3">
{Array.from({ length: 4 }).map((_, i) => (
<div key={i} className="h-16 rounded-xl border bg-card" />
))}
</div>
</div>
);
}InsightsPage function · typescript · L6-L105 (100 LOC)src/app/(app)/insights/page.tsx
export default async function InsightsPage() {
const supabase = await createClient();
const { data: recordings, error } = await supabase
.from("recordings")
.select(
"id, title, duration, created_at, analyses(key_signature, tempo, time_signature, chords)"
);
if (error) {
console.error("Insights query error:", error);
}
const allRecordings = recordings ?? [];
const totalRecordings = allRecordings.length;
const analysesData = allRecordings
.filter((r) => {
if (!r.analyses) return false;
if (Array.isArray(r.analyses)) return r.analyses.length > 0;
return true; // single object means analysis exists
})
.map((r) => {
const analysis = Array.isArray(r.analyses) ? r.analyses[0] : r.analyses;
const a = analysis as {
key_signature: string | null;
tempo: number | null;
time_signature: string | null;
chords: { chord: string; time: number; duration: number }[];
};
return {
AppLayout function · typescript · L3-L12 (10 LOC)src/app/(app)/layout.tsx
export default function AppLayout({ children }: { children: React.ReactNode }) {
return (
<div className="flex h-screen overflow-hidden">
<Sidebar />
<main className="flex-1 overflow-y-auto pt-14 md:pt-0">
<div className="mx-auto max-w-5xl px-4 py-6 sm:px-6 sm:py-8">{children}</div>
</main>
</div>
);
}Methodology: Repobility · https://repobility.com/research/state-of-ai-code-2026/
LibraryLoading function · typescript · L1-L28 (28 LOC)src/app/(app)/library/loading.tsx
export default function LibraryLoading() {
return (
<div className="space-y-6 animate-pulse">
{/* Header with search */}
<div className="flex items-center justify-between">
<div className="h-8 w-32 rounded bg-muted" />
<div className="h-9 w-24 rounded bg-muted" />
</div>
<div className="h-10 w-full rounded-md bg-muted" />
{/* Recording cards */}
<div className="space-y-3">
{Array.from({ length: 5 }).map((_, i) => (
<div
key={i}
className="flex items-center gap-4 rounded-xl border bg-card px-6 py-4"
>
<div className="h-10 w-10 shrink-0 rounded-lg bg-muted" />
<div className="flex-1 space-y-2">
<div className="h-4 w-48 rounded bg-muted" />
<div className="h-3 w-32 rounded bg-muted" />
</div>
</div>
))}
</div>
</div>
);
}LibraryPage function · typescript · L4-L56 (53 LOC)src/app/(app)/library/page.tsx
export default async function LibraryPage() {
const supabase = await createClient();
const [{ data: recordings }, { data: tags }] = await Promise.all([
supabase
.from("recordings")
.select(
"id, title, duration, created_at, recorded_at, file_name, description, analyses(id, status, key_signature, tempo), recording_tags(tag_id, tags(id, name))"
)
.order("created_at", { ascending: false }),
supabase
.from("tags")
.select("id, name")
.order("name", { ascending: true }),
]);
const normalized = (recordings ?? []).map((rec) => {
// analyses can be an array or a single object depending on the relationship
const analysesList = Array.isArray(rec.analyses)
? rec.analyses
: rec.analyses
? [rec.analyses]
: [];
const completed = analysesList.find((a: { status?: string }) => a.status === "completed") as
| { key_signature?: string | null; tempo?: number | null }
| undefined;
retRecordingLoading function · typescript · L1-L38 (38 LOC)src/app/(app)/recording/[id]/loading.tsx
export default function RecordingLoading() {
return (
<div className="space-y-6 animate-pulse">
{/* Title area */}
<div>
<div className="h-8 w-64 rounded bg-muted" />
<div className="mt-2 h-4 w-48 rounded bg-muted" />
</div>
{/* Waveform player area */}
<div className="space-y-3">
<div className="h-[104px] rounded-lg border bg-card" />
<div className="flex items-center justify-between">
<div className="h-4 w-10 rounded bg-muted" />
<div className="flex gap-2">
<div className="h-9 w-9 rounded bg-muted" />
<div className="h-9 w-9 rounded bg-muted" />
<div className="h-9 w-9 rounded bg-muted" />
</div>
<div className="h-4 w-10 rounded bg-muted" />
</div>
</div>
{/* Tabs area */}
<div className="space-y-4">
<div className="flex gap-4 border-b pb-2">
<div className="h-5 w-20 rounded bg-muted" />
formatDuration function · typescript · L7-L11 (5 LOC)src/app/(app)/recording/[id]/page.tsx
function formatDuration(seconds: number): string {
const m = Math.floor(seconds / 60);
const s = Math.floor(seconds % 60);
return `${m}:${s.toString().padStart(2, "0")}`;
}RecordingPage function · typescript · L13-L83 (71 LOC)src/app/(app)/recording/[id]/page.tsx
export default async function RecordingPage({
params,
}: {
params: Promise<{ id: string }>;
}) {
const { id } = await params;
const supabase = await createClient();
// Run all queries in parallel to eliminate waterfall
const [recordingResult, analysisResult, messagesResult] = await Promise.all([
supabase.from("recordings").select("*").eq("id", id).single(),
supabase.from("analyses").select("*").eq("recording_id", id).single(),
supabase
.from("chat_messages")
.select("*")
.eq("recording_id", id)
.order("created_at", { ascending: true }),
]);
const recording = recordingResult.data;
if (!recording) notFound();
// Use proxy API route — it detects ALAC and transcodes to AAC for Chrome
const audioUrl = `/api/audio/${id}`;
const analysis = analysisResult.data;
const messages = messagesResult.data;
return (
<div className="space-y-6">
<div>
<h1 className="text-2xl font-bold">{recording.title}</h1>
{rUploadPage function · typescript · L23-L293 (271 LOC)src/app/(app)/upload/page.tsx
export default function UploadPage() {
const [files, setFiles] = useState<UploadingFile[]>([]);
const [isDragging, setIsDragging] = useState(false);
const fileInputRef = useRef<HTMLInputElement>(null);
const router = useRouter();
const addFiles = useCallback((newFiles: FileList | File[]) => {
const audioFiles = Array.from(newFiles).filter((f) =>
f.type.startsWith("audio/") || f.name.endsWith(".m4a") || f.name.endsWith(".mp3") || f.name.endsWith(".wav")
);
if (audioFiles.length === 0) {
toast.error("Please select audio files (M4A, MP3, WAV)");
return;
}
setFiles((prev) => {
const remaining = 100 - prev.length;
if (remaining <= 0) {
toast.error("Maximum 100 files per batch");
return prev;
}
const toAdd = audioFiles.slice(0, remaining);
if (toAdd.length < audioFiles.length) {
toast.warning(`Added ${toAdd.length} of ${audioFiles.length} files (100 file limit)`);
}
return [
handleDrop function · typescript · L54-L58 (5 LOC)src/app/(app)/upload/page.tsx
function handleDrop(e: React.DragEvent) {
e.preventDefault();
setIsDragging(false);
addFiles(e.dataTransfer.files);
}removeFile function · typescript · L60-L62 (3 LOC)src/app/(app)/upload/page.tsx
function removeFile(index: number) {
setFiles((prev) => prev.filter((_, i) => i !== index));
}Powered by Repobility — scan your code at https://repobility.com
uploadAll function · typescript · L64-L183 (120 LOC)src/app/(app)/upload/page.tsx
async function uploadAll() {
const supabase = createClient();
const { data: { user }, error: authError } = await supabase.auth.getUser();
if (!user) {
toast.error(authError?.message ?? "Not logged in. Please sign in first.");
return;
}
let successCount = 0;
let failCount = 0;
for (let i = 0; i < files.length; i++) {
if (files[i].status === "done") continue;
setFiles((prev) =>
prev.map((f, idx) => (idx === i ? { ...f, status: "uploading", progress: 10 } : f))
);
const file = files[i].file;
const fileName = `${user.id}/${Date.now()}-${file.name}`;
setFiles((prev) =>
prev.map((f, idx) => (idx === i ? { ...f, progress: 30 } : f))
);
const { error: uploadError } = await supabase.storage
.from("recordings")
.upload(fileName, file, {
contentType: file.type || "audio/mp4",
upsert: false,
});
if (uploadError) {
const msg = uplRootLayout function · typescript · L22-L39 (18 LOC)src/app/layout.tsx
export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
return (
<html lang="en" suppressHydrationWarning>
<body
className={`${geistSans.variable} ${geistMono.variable} antialiased`}
>
<Providers>
{children}
<Toaster />
</Providers>
</body>
</html>
);
}LoginPage function · typescript · L11-L102 (92 LOC)src/app/login/page.tsx
export default function LoginPage() {
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [error, setError] = useState<string | null>(null);
const [loading, setLoading] = useState(false);
const router = useRouter();
async function handleLogin(e: React.FormEvent) {
e.preventDefault();
setLoading(true);
setError(null);
const supabase = createClient();
const { error } = await supabase.auth.signInWithPassword({
email,
password,
});
if (error) {
setError(error.message);
setLoading(false);
} else {
router.push("/library");
router.refresh();
}
}
return (
<div className="relative flex min-h-screen items-center justify-center bg-background p-4">
<div className="pointer-events-none absolute inset-0 flex items-center justify-center">
<div className="h-[500px] w-[500px] rounded-full bg-primary/5 blur-3xl" />
</div>
<div className="relativhandleLogin function · typescript · L18-L36 (19 LOC)src/app/login/page.tsx
async function handleLogin(e: React.FormEvent) {
e.preventDefault();
setLoading(true);
setError(null);
const supabase = createClient();
const { error } = await supabase.auth.signInWithPassword({
email,
password,
});
if (error) {
setError(error.message);
setLoading(false);
} else {
router.push("/library");
router.refresh();
}
}Home function · typescript · L3-L5 (3 LOC)src/app/page.tsx
export default function Home() {
redirect("/library");
}createAnonClient function · typescript · L9-L14 (6 LOC)src/app/share/[token]/page.tsx
function createAnonClient() {
return createClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!
);
}formatDuration function · typescript · L16-L20 (5 LOC)src/app/share/[token]/page.tsx
function formatDuration(seconds: number): string {
const m = Math.floor(seconds / 60);
const s = Math.floor(seconds % 60);
return `${m}:${s.toString().padStart(2, "0")}`;
}generateMetadata function · typescript · L22-L43 (22 LOC)src/app/share/[token]/page.tsx
export async function generateMetadata({
params,
}: {
params: Promise<{ token: string }>;
}) {
const { token } = await params;
const supabase = createAnonClient();
const { data: recording } = await supabase
.from("recordings")
.select("title, description")
.eq("share_token", token)
.single();
if (!recording) {
return { title: "Recording Not Found" };
}
return {
title: `${recording.title} — Resonance`,
description: recording.description || "Shared recording on Resonance",
};
}All rows above produced by Repobility · https://repobility.com
SharedRecordingPage function · typescript · L45-L221 (177 LOC)src/app/share/[token]/page.tsx
export default async function SharedRecordingPage({
params,
}: {
params: Promise<{ token: string }>;
}) {
const { token } = await params;
const supabase = createAnonClient();
const { data: recording } = await supabase
.from("recordings")
.select("*, analyses(*)")
.eq("share_token", token)
.single();
if (!recording) notFound();
const analysis =
recording.analyses && recording.analyses.length > 0
? recording.analyses[0]
: null;
const audioUrl = `/api/audio/${recording.id}`;
const uniqueChords = analysis?.chords
? [...new Set((analysis.chords as { chord: string }[]).map((c) => c.chord))]
: [];
return (
<div className="min-h-screen bg-background text-foreground">
<div className="mx-auto max-w-2xl px-4 py-10 sm:px-6 sm:py-16">
{/* Header */}
<header className="mb-12">
<p className="text-xs font-mono uppercase tracking-widest text-muted-foreground mb-6">
Shared Recording
SignupPage function · typescript · L11-L104 (94 LOC)src/app/signup/page.tsx
export default function SignupPage() {
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [error, setError] = useState<string | null>(null);
const [loading, setLoading] = useState(false);
const router = useRouter();
async function handleSignup(e: React.FormEvent) {
e.preventDefault();
setLoading(true);
setError(null);
const supabase = createClient();
const { error } = await supabase.auth.signUp({
email,
password,
});
if (error) {
setError(error.message);
setLoading(false);
} else {
router.push("/library");
router.refresh();
}
}
return (
<div className="relative flex min-h-screen items-center justify-center bg-background p-4">
<div className="pointer-events-none absolute inset-0 flex items-center justify-center">
<div className="h-[500px] w-[500px] rounded-full bg-primary/5 blur-3xl" />
</div>
<div className="relative w-full mhandleSignup function · typescript · L18-L36 (19 LOC)src/app/signup/page.tsx
async function handleSignup(e: React.FormEvent) {
e.preventDefault();
setLoading(true);
setError(null);
const supabase = createClient();
const { error } = await supabase.auth.signUp({
email,
password,
});
if (error) {
setError(error.message);
setLoading(false);
} else {
router.push("/library");
router.refresh();
}
}page 1 / 5next ›