Initial commit — AI-powered coding tutor (Professor)

Next.js 16, React 19, Monaco editor, Anthropic SDK, multi-provider AI,
Wandbox Python execution, iframe HTML preview, SQLite auth + session persistence.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Aodhan Collins
2026-03-04 21:48:34 +00:00
commit f644937604
56 changed files with 14012 additions and 0 deletions

62
app/api/session/route.ts Normal file
View File

@@ -0,0 +1,62 @@
import { NextRequest, NextResponse } from 'next/server';
import { db } from '@/db';
import { savedSessions } from '@/db/schema';
import { getAuthUser } from '@/lib/auth';
import { eq } from 'drizzle-orm';
export async function GET() {
const authUser = await getAuthUser();
if (!authUser) return NextResponse.json({ session: null }, { status: 401 });
const row = await db
.select()
.from(savedSessions)
.where(eq(savedSessions.userId, authUser.userId))
.get();
if (!row) return NextResponse.json({ session: null });
return NextResponse.json({
session: {
topicId: row.topicId,
task: row.taskJson ? JSON.parse(row.taskJson) : null,
code: row.code,
messages: row.messagesJson ? JSON.parse(row.messagesJson) : [],
executionResult: row.executionResultJson ? JSON.parse(row.executionResultJson) : null,
},
});
}
export async function PUT(req: NextRequest) {
const authUser = await getAuthUser();
if (!authUser) return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
const { topicId, task, code, messages, executionResult } = await req.json();
const existing = await db
.select()
.from(savedSessions)
.where(eq(savedSessions.userId, authUser.userId))
.get();
const data = {
userId: authUser.userId,
topicId: topicId ?? null,
taskJson: task ? JSON.stringify(task) : null,
code: code ?? null,
messagesJson: messages ? JSON.stringify(messages) : null,
executionResultJson: executionResult ? JSON.stringify(executionResult) : null,
updatedAt: new Date().toISOString(),
};
if (existing) {
await db
.update(savedSessions)
.set(data)
.where(eq(savedSessions.userId, authUser.userId));
} else {
await db.insert(savedSessions).values({ id: crypto.randomUUID(), ...data });
}
return NextResponse.json({ ok: true });
}