Argue real landmark cases against an AI judge, prosecutor, and witness. Get scored on every argument. Built for the 1.8 million law students who can't afford a $500/hr moot court coach.
Moot court is how law students learn to argue. The problem:
- A professional coach costs $500 per hour
- Most law schools offer fewer than 12 practice sessions per year
- Students who cannot afford coaching lose more cases
- There is no free intelligent alternative — until now
LexAI puts you in a real courtroom simulation. You argue as the defense. Three AI personas respond to every argument you make:
| Persona | Role | Behavior |
|---|---|---|
| Judge | Presiding | Evaluates arguments, asks follow-up questions, issues rulings |
| Prosecution | Opposing counsel | Counters every argument aggressively |
| Witness | On the stand | Answers questions, stays consistent, stumbles on contradictions |
| You | Defense | Argue your case, cite precedents, cross-examine the witness |
After each session a replay timeline shows:
- Your score on every single argument
- Where your score went up and where it dropped
- Your best argument highlighted with a badge
- A full argument-by-argument breakdown with score delta
- 3 real landmark cases included — Miranda, contract breach, self-defense
- AI judge and prosecutor respond dynamically to your exact arguments
- Real-time argument scoring from 0 to 100 on logic, precedent, and persuasiveness
- Live coaching feedback after every turn
- Switch to cross-examination mode inside any case with one click
- AI witness stays consistent with original testimony across the entire session
- Contradiction detection — catch the witness in a lie and get a score bonus
- Contradiction banner flashes when you successfully expose an inconsistency
- Green color system clearly separates witness mode from defense mode
- Coaching feedback after every question
- Every session saved automatically to Supabase
- Visual score progression bar chart showing every turn
- Defense turns and witness turns tracked and labeled separately
- Best argument highlighted with a star badge
- Full argument timeline with score delta per turn
- Replay any past session at any time from session history
- Beautiful share page generated for every completed session
- Dynamic OG image generated using Next.js Edge Runtime
- One-click copy share link
- LinkedIn and Twitter share buttons with pre-filled text
- Preview the share image before posting
- Professors activate a dedicated dashboard with one click
- Create classes and get auto-generated join codes
- Students join classes using the join code
- Assign specific cases to a class with optional due dates
- Track every student's sessions, scores, and completion rate
- Class overview shows assignment completion progress per case
- Average score per assignment calculated automatically
- Global error boundary catches unexpected crashes and shows a friendly message
- AI-specific error component shows when OpenAI or API calls fail
- Retry button lets users try again without refreshing the page
- Session load error component for database fetch failures
- All errors logged to console for debugging without exposing internals to users
- Shimmer skeleton cards on dashboard while cases load
- Shimmer skeleton cards on sessions page while history loads
- React Suspense boundaries for streaming server components
- Zero layout shift — skeletons match exact dimensions of real content
- Clerk authentication with email and Google
- Role-based access — student and professor roles
- Every session tied to the signed-in user
- Sessions ordered by date and accessible from the dashboard
- FAANG-level dark design system
- Framer Motion animations on landing page
- Color-coded personas — Judge yellow, Prosecution red, Witness green, Defense blue
- Fully responsive across all screen sizes
- Blur backdrop navigation bars
| Layer | Technology | Why |
|---|---|---|
| Framework | Next.js 15 App Router | Server components, API routes, file-based routing |
| Language | TypeScript | Type safety across the entire codebase |
| Styling | Tailwind CSS and inline styles | Utility-first with custom design tokens |
| Auth | Clerk | Production-grade authentication with zero config |
| Database | Supabase PostgreSQL | Real-time, scalable, generous free tier |
| AI | OpenAI GPT-4o-mini | Fast, cost-efficient, structured JSON outputs |
| OG Images | Vercel OG | Dynamic social share images on the edge |
| Animations | Framer Motion | Smooth page and component transitions |
| Deployment | Vercel | Edge network, instant deploys from GitHub |
create table sessions (
id uuid default gen_random_uuid() primary key,
user_id text not null,
case_title text not null,
messages jsonb default '[]',
score integer default 0,
score_history jsonb default '[]',
best_argument text default '',
completed boolean default false,
created_at timestamp with time zone default timezone('utc', now())
);
create table profiles (
id text primary key,
email text,
role text default 'student',
created_at timestamp with time zone default timezone('utc', now())
);
create table classes (
id uuid default gen_random_uuid() primary key,
professor_id text not null,
name text not null,
join_code text unique not null,
created_at timestamp with time zone default timezone('utc', now())
);
create table class_members (
id uuid default gen_random_uuid() primary key,
class_id uuid references classes(id) on delete cascade,
student_id text not null,
joined_at timestamp with time zone default timezone('utc', now())
);
create table assignments (
id uuid default gen_random_uuid() primary key,
class_id uuid references classes(id) on delete cascade,
case_id text not null,
case_title text not null,
due_date text,
created_at timestamp with time zone default timezone('utc', now())
);- Node.js 20 or higher
- Accounts on Clerk, Supabase, and OpenAI
git clone https://github.com/naimakader/Lexai.git
cd Lexai
npm install
cp .env.example .env.local
npm run dev# Clerk
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_test_...
CLERK_SECRET_KEY=sk_test_...
NEXT_PUBLIC_CLERK_SIGN_IN_URL=/sign-in
NEXT_PUBLIC_CLERK_SIGN_UP_URL=/sign-up
NEXT_PUBLIC_CLERK_AFTER_SIGN_IN_URL=/dashboard
NEXT_PUBLIC_CLERK_AFTER_SIGN_UP_URL=/dashboard
# Supabase
NEXT_PUBLIC_SUPABASE_URL=https://xxx.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=eyJ...
# OpenAI
OPENAI_API_KEY=sk-...Run this in your Supabase SQL editor:
create table sessions (
id uuid default gen_random_uuid() primary key,
user_id text not null,
case_title text not null,
messages jsonb default '[]',
score integer default 0,
score_history jsonb default '[]',
best_argument text default '',
completed boolean default false,
created_at timestamp with time zone default timezone('utc', now())
);
create table profiles (
id text primary key,
email text,
role text default 'student',
created_at timestamp with time zone default timezone('utc', now())
);
create table classes (
id uuid default gen_random_uuid() primary key,
professor_id text not null,
name text not null,
join_code text unique not null,
created_at timestamp with time zone default timezone('utc', now())
);
create table class_members (
id uuid default gen_random_uuid() primary key,
class_id uuid references classes(id) on delete cascade,
student_id text not null,
joined_at timestamp with time zone default timezone('utc', now())
);
create table assignments (
id uuid default gen_random_uuid() primary key,
class_id uuid references classes(id) on delete cascade,
case_id text not null,
case_title text not null,
due_date text,
created_at timestamp with time zone default timezone('utc', now())
);lexai/
├── app/
│ ├── api/
│ │ ├── courtroom/
│ │ │ └── route.ts
│ │ ├── witness/
│ │ │ └── route.ts
│ │ ├── professor/
│ │ │ └── route.ts
│ │ └── og/
│ │ └── route.tsx
│ ├── case/
│ │ └── [id]/
│ │ ├── page.tsx
│ │ └── CourtroomClient.tsx
│ ├── dashboard/
│ │ ├── page.tsx
│ │ └── DashboardClient.tsx
│ ├── professor/
│ │ ├── page.tsx
│ │ └── ProfessorClient.tsx
│ ├── sessions/
│ │ ├── page.tsx
│ │ └── [id]/
│ │ ├── page.tsx
│ │ └── share/
│ │ ├── page.tsx
│ │ └── ShareClient.tsx
│ ├── sign-in/[[...sign-in]]/
│ │ └── page.tsx
│ ├── sign-up/[[...sign-up]]/
│ │ └── page.tsx
│ ├── clerk-theme.ts
│ ├── globals.css
│ ├── layout.tsx
│ └── page.tsx
├── lib/
│ └── supabase.ts
├── middleware.ts
├── .env.example
└── README.md
- Core courtroom simulator
- 3 AI personas — judge, prosecution, defense
- Real-time argument scoring
- Session history page
- Session replay with score timeline and bar chart
- AI witness cross-examination with contradiction detection
- Shareable session cards with dynamic OG image generation
- Professor dashboard with class management and student analytics
- Real-time multiplayer battle mode with Supabase Realtime
- Loading skeletons with shimmer animation on all data pages- [x] 10 landmark cases across Criminal, Civil, Constitutional, and IP law
- Error boundaries with friendly AI failure messages and retry logic
- Row Level Security on all Supabase tables
- API rate limiting — 50 requests per hour per user
- Input sanitization — 1000 character limit on all AI inputs
- Mobile responsive design with CSS media queries
- Mobile app
Most portfolio projects are todo apps or weather dashboards. LexAI is different.
Real problem. 1.8 million law students globally have no affordable way to practice oral arguments. This solves that directly.
Technical depth. Multi-persona AI state management, structured JSON outputs, real-time scoring, session persistence, replay timelines, witness contradiction detection, dynamic OG image generation, and role-based professor dashboard. This is not a tutorial project.
Product thinking. Every feature was designed around user behavior. The replay timeline exists because students need to know which argument won or lost the case. The witness mode exists because cross-examination is a completely different skill. The professor dashboard exists because adoption happens through institutions not individuals.
Scalable architecture. Server components for data fetching, client components for interactivity, API routes for AI calls, Supabase for persistence, edge runtime for OG images, role-based access control throughout. Clean separation of concerns.
Naima — Frontend developer building products that matter.
GitHub: @naimakader
MIT — use it, learn from it, build on it.