mike-ai-legal-platform
```markdown
What this skill does
```markdown
---
name: mike-ai-legal-platform
description: OSS AI legal platform with Next.js frontend and Express backend for document processing and legal workflows
triggers:
- set up mike legal platform
- add mike to my project
- configure mike backend
- mike document processing
- mike supabase integration
- mike frontend setup
- deploy mike legal AI
- mike API endpoints
---
# Mike AI Legal Platform
> Skill by [ara.so](https://ara.so) — Daily 2026 Skills collection.
Mike is an open-source AI legal platform consisting of a Next.js frontend and an Express backend. It supports document processing (including DOC/DOCX to PDF via LibreOffice), Supabase Auth and Postgres, S3-compatible object storage, and multiple AI model providers.
---
## Project Structure
```
mike/
├── frontend/ # Next.js application
├── backend/ # Express API, Supabase access, document processing
│ └── migrations/
│ └── 000_one_shot_schema.sql # Fresh DB schema
```
---
## Installation
```bash
# Clone the repository
git clone https://github.com/willchen96/mike.git
cd mike
# Install dependencies for both services
npm install --prefix backend
npm install --prefix frontend
# Copy environment files
cp backend/.env.example backend/.env
cp frontend/.env.local.example frontend/.env.local
```
### Database Setup
Run the one-shot schema in the Supabase SQL editor:
```
backend/migrations/000_one_shot_schema.sql
```
---
## Environment Configuration
### Backend (`backend/.env`)
```env
# Supabase
SUPABASE_URL=https://your-project.supabase.co
SUPABASE_SERVICE_ROLE_KEY=$SUPABASE_SERVICE_ROLE_KEY
# S3-compatible storage (e.g. Cloudflare R2)
S3_ENDPOINT=$S3_ENDPOINT
S3_BUCKET=$S3_BUCKET
S3_ACCESS_KEY_ID=$S3_ACCESS_KEY_ID
S3_SECRET_ACCESS_KEY=$S3_SECRET_ACCESS_KEY
S3_REGION=$S3_REGION
# AI Model Provider(s) — enable at least one
OPENAI_API_KEY=$OPENAI_API_KEY
ANTHROPIC_API_KEY=$ANTHROPIC_API_KEY
# Server
PORT=4000
```
### Frontend (`frontend/.env.local`)
```env
NEXT_PUBLIC_SUPABASE_URL=https://your-project.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=$NEXT_PUBLIC_SUPABASE_ANON_KEY
NEXT_PUBLIC_API_URL=http://localhost:4000
```
---
## Running the Platform
```bash
# Start backend (Express API on port 4000)
npm run dev --prefix backend
# Start frontend (Next.js on port 3000)
npm run dev --prefix frontend
```
Open `http://localhost:3000`.
---
## Key Commands
```bash
# Build checks
npm run build --prefix backend
npm run build --prefix frontend
# Lint
npm run lint --prefix frontend
```
---
## Required Services
| Service | Purpose |
|---|---|
| Supabase | Auth + Postgres database |
| S3-compatible storage | Document/file storage (e.g. Cloudflare R2) |
| AI model provider | At least one (OpenAI, Anthropic, etc.) |
| LibreOffice | DOC/DOCX → PDF conversion |
### Installing LibreOffice (Ubuntu/Debian)
```bash
sudo apt-get install -y libreoffice
```
---
## Common Patterns
### Supabase Client (Backend)
```typescript
import { createClient } from '@supabase/supabase-js';
const supabase = createClient(
process.env.SUPABASE_URL!,
process.env.SUPABASE_SERVICE_ROLE_KEY!
);
// Fetch documents for a user
const { data, error } = await supabase
.from('documents')
.select('*')
.eq('user_id', userId);
```
### Supabase Auth (Frontend)
```typescript
import { createClientComponentClient } from '@supabase/auth-helpers-nextjs';
const supabase = createClientComponentClient();
// Sign in
const { data, error } = await supabase.auth.signInWithPassword({
email: process.env.NEXT_PUBLIC_USER_EMAIL,
password: process.env.NEXT_PUBLIC_USER_PASSWORD,
});
// Get current session
const { data: { session } } = await supabase.auth.getSession();
```
### Uploading a Document (Frontend → Backend)
```typescript
// frontend/lib/api.ts
export async function uploadDocument(file: File, token: string) {
const formData = new FormData();
formData.append('file', file);
const res = await fetch(`${process.env.NEXT_PUBLIC_API_URL}/documents/upload`, {
method: 'POST',
headers: {
Authorization: `Bearer ${token}`,
},
body: formData,
});
if (!res.ok) throw new Error(await res.text());
return res.json();
}
```
### Express Route with Auth Middleware (Backend)
```typescript
// backend/src/routes/documents.ts
import { Router, Request, Response } from 'express';
import { requireAuth } from '../middleware/auth';
import { supabase } from '../lib/supabase';
const router = Router();
router.get('/', requireAuth, async (req: Request, res: Response) => {
const userId = (req as any).user.id;
const { data, error } = await supabase
.from('documents')
.select('id, name, created_at, status')
.eq('user_id', userId)
.order('created_at', { ascending: false });
if (error) return res.status(500).json({ error: error.message });
return res.json(data);
});
export default router;
```
### S3 File Upload (Backend)
```typescript
// backend/src/lib/storage.ts
import { S3Client, PutObjectCommand } from '@aws-sdk/client-s3';
import { randomUUID } from 'crypto';
const s3 = new S3Client({
endpoint: process.env.S3_ENDPOINT,
region: process.env.S3_REGION,
credentials: {
accessKeyId: process.env.S3_ACCESS_KEY_ID!,
secretAccessKey: process.env.S3_SECRET_ACCESS_KEY!,
},
});
export async function uploadToStorage(
buffer: Buffer,
mimeType: string,
originalName: string
): Promise<string> {
const key = `documents/${randomUUID()}/${originalName}`;
await s3.send(
new PutObjectCommand({
Bucket: process.env.S3_BUCKET!,
Key: key,
Body: buffer,
ContentType: mimeType,
})
);
return key;
}
```
### DOC/DOCX to PDF Conversion (Backend)
```typescript
// backend/src/lib/convert.ts
import { exec } from 'child_process';
import { promisify } from 'util';
import path from 'path';
import fs from 'fs/promises';
const execAsync = promisify(exec);
export async function convertDocToPdf(inputPath: string): Promise<string> {
const dir = path.dirname(inputPath);
await execAsync(
`libreoffice --headless --convert-to pdf --outdir ${dir} ${inputPath}`
);
const baseName = path.basename(inputPath, path.extname(inputPath));
const outputPath = path.join(dir, `${baseName}.pdf`);
// Verify output exists
await fs.access(outputPath);
return outputPath;
}
```
### Calling an AI Model (Backend)
```typescript
// backend/src/lib/ai.ts
import OpenAI from 'openai';
const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });
export async function summarizeDocument(text: string): Promise<string> {
const response = await openai.chat.completions.create({
model: 'gpt-4o',
messages: [
{
role: 'system',
content: 'You are a legal assistant. Summarize the following document concisely.',
},
{ role: 'user', content: text },
],
});
return response.choices[0].message.content ?? '';
}
```
---
## Next.js API Route Pattern (Frontend)
```typescript
// frontend/app/api/documents/route.ts
import { createRouteHandlerClient } from '@supabase/auth-helpers-nextjs';
import { cookies } from 'next/headers';
import { NextResponse } from 'next/server';
export async function GET() {
const supabase = createRouteHandlerClient({ cookies });
const {
data: { session },
} = await supabase.auth.getSession();
if (!session) {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
}
const res = await fetch(`${process.env.NEXT_PUBLIC_API_URL}/documents`, {
headers: { Authorization: `Bearer ${session.access_token}` },
});
const data = await res.json();
return NextResponse.json(data);
}
```
---
## Troubleshooting
### LibreOffice not found
```bash
which libreoffice
# If missing:
sudo apt-get install -y libreoffice # Debian/Ubuntu
brew install --cask libreoffice # macOS
```
### Supabase connection errors
- Verify `SUPABASE_URL` includes `https://` prefix.
- Service role key must be used on the backend (neRelated in Writing & Docs
jax-development
IncludedUse this skill when the user is writing, debugging, profiling, refactoring, reviewing, benchmarking, parallelising, exporting, or explaining JAX code, or when they mention JAX, jax.numpy, jit, grad, value_and_grad, vmap, scan, lax, random keys, pytrees, jax.Array, sharding, Mesh, PartitionSpec, NamedSharding, pmap, shard_map, Pallas, XLA, StableHLO, checkify, profiler, or the JAX repo. It helps turn NumPy or PyTorch-style code into pure functional JAX, fix tracer/control-flow/shape/PRNG bugs, remove recompiles and host-device syncs, choose transforms and sharding strategies, inspect jaxpr/lowering/IR, and benchmark compiled code correctly.
nature-article-writer
IncludedDrafts, rewrites, diagnostically critiques, and style-calibrates primary research manuscripts for Nature and Nature Portfolio journals. Use when the user wants a Nature-style title, summary paragraph or abstract, introduction, results, discussion, methods, figure legends, presubmission enquiry, cover letter, reviewer response, or when a scientific draft sounds generic, jargon-heavy, structurally weak, or AI-ish and needs precise, broad-reader-friendly prose without inventing data, analyses, or references. Best for primary research articles and letters rather than reviews or press releases unless explicitly adapting one.
deckrd
IncludedDocument-driven framework that derives requirements, specifications, implementation plans, and executable tasks from goals through structured AI dialogue. Use when user says "write requirements", "create spec", "plan implementation", "derive tasks", "structure this feature", "break down into tasks", or "document this module". Also use for reverse engineering existing code into docs (/deckrd rev). Do NOT use for direct code writing — use /deckrd-coder after tasks are generated. Do NOT use when the user only wants to run or fix existing code without planning.
clinical-decision-support
IncludedGenerate professional clinical decision support (CDS) documents for pharmaceutical and clinical research settings, including patient cohort analyses (biomarker-stratified with outcomes) and treatment recommendation reports (evidence-based guidelines with decision algorithms). Supports GRADE evidence grading, statistical analysis (hazard ratios, survival curves, waterfall plots), biomarker integration, and regulatory compliance. Outputs publication-ready LaTeX/PDF format optimized for drug development, clinical research, and evidence synthesis.
handling-sf-data
IncludedSalesforce data operations with 130-point scoring. Use this skill to create, update, delete, bulk import/export, generate test data, and clean up org records using sf CLI and anonymous Apex. TRIGGER when: user creates test data, performs bulk import/export, uses sf data CLI commands, needs data factory patterns for Apex tests, or needs to seed/clean records in a Salesforce org. DO NOT TRIGGER when: SOQL query writing only (use querying-soql), Apex test execution (use running-apex-tests), or metadata deployment (use deploying-metadata).
accelint-ac-to-playwright
IncludedConvert and validate acceptance criteria for Playwright test automation. Use when user asks to (1) review/evaluate/check if AC are ready for automation, (2) assess if AC can be converted as-is, (3) validate AC quality for Playwright, (4) turn AC into tests, (5) generate tests from acceptance criteria, (6) convert .md bullets or .feature Gherkin files to Playwright specs, (7) create test automation from requirements. Handles both bullet-style markdown and Gherkin syntax with JSON test plan generation and validation.