legalos

legalOS: CLAUDE.md

Project Overview

legalOS — an operating system for legal departments. A multi-department, AI-native web app that gives lawyers and legal-ops staff a single, welcoming entry point to the agents and tools they use day-to-day — whether external (Gemini Gems, watsonX Orchestrate, custom links) or natively hosted inside the app.

legalOS is built to serve one corporate legal department at a time (single-tenant), with a multi-tenant-ready schema so the same codebase can later support a SaaS version for multiple legal departments. It ships with eight departments — Commercial, Public Sector, Mergers & Acquisitions, Privacy, Product, Compliance, Operations, General Tools — and is designed so adding more (Litigation, IP, etc.) is mostly configuration.

Adoption is a first-class concern. The UI is deliberately simple, clean, modern, and welcoming. Behind that simple front end is real infrastructure: role-based access, native chat with prompt caching, web search, attached references, per-message Word export, soft-delete with 30-day undo, Supabase-backed analytics, a productivity gains calculator, support flows, and an admin area.

Current Phase

Phase 2 — Agent product surface. Native agents fully wired (chat, attachments, caching, web search, exports); agent CRUD + soft delete + trash + 8-department launchpad behind RBAC.


Architecture

Tech Stack

Layer Technology Deployment
Frontend Next.js 16 (App Router), TypeScript, Tailwind CSS v4, shadcn/ui Vercel
Backend Next.js API routes + server actions Vercel (same deploy)
Database Supabase (PostgreSQL) with Row-Level Security Supabase Cloud
Auth Supabase Auth (magic link) Supabase Cloud
AI / LLM Anthropic API (Claude) for native agents; external links for Gemini Gems, watsonX, etc. Server-side only
Analytics Supabase tables; localStorage fallback in Phase 1 Supabase Cloud

Directory Structure

legalos/
├── app/                          # Next.js App Router
│   ├── (public)/                 # Unauthenticated routes (login, landing)
│   ├── (app)/                    # Authenticated routes
│   │   ├── departments/[slug]/   # Per-department launchpad page
│   │   ├── agents/[id]/          # Native agent chat page
│   │   └── admin/                # Admin dashboard (role-gated)
│   ├── api/                      # Route handlers (chat proxy, webhooks)
│   └── layout.tsx                # Root layout (theme provider, auth provider)
├── components/                   # Reusable React components
│   ├── ui/                       # shadcn/ui primitives
│   ├── launchpad/                # Agent cards, dept grids
│   ├── chat/                     # Chat UI for native agents
│   └── admin/                    # Admin dashboard components
├── styles/                       # Global CSS and theme preset files (imported from app/globals.css)
├── lib/                          # Shared utilities
│   ├── supabase/                 # Supabase clients (server, browser, middleware)
│   ├── anthropic/                # Anthropic API client wrappers
│   ├── auth/                     # Auth helpers, role checks
│   ├── actions/                  # Server actions (promote to top-level when >~8 files)
│   ├── hooks/                    # Custom React hooks (promote to top-level when >~8 files)
│   └── analytics/                # Event tracking helpers
├── config/                       # Site configuration
│   ├── site.ts                   # Branding, company name, theme preset
│   ├── departments.ts            # Department metadata (seed/override)
│   └── theme.ts                  # Theme token definitions
├── supabase/                     # Supabase config
│   ├── migrations/               # SQL migrations
│   ├── seed.sql                  # Seed data
│   └── policies/                 # RLS policy SQL (organized by table)
├── .claude/
│   └── skills/                   # Skill files copied from claude-templates
├── public/                       # Static assets
├── CLAUDE.md                     # This file
├── PROJECT_OUTLINE.md            # Phases, architecture, roadmap
├── DECISION_LOG.md               # Architecture decisions with reasoning
├── SETUP.md                      # Setup guide for new forks
├── CHANGELOG.md                  # Version history
├── README.md                     # Project overview for GitHub
├── .env.example                  # Env var template
└── proxy.ts                      # Auth proxy (Next.js 16 file convention, formerly middleware.ts)

Data Flow

External agent click (launchpad → third-party platform): User → Launchpad page → Click card → Log analytics event to Supabase → Open external URL in new tab.

Native agent click (launchpad → in-app chat): User → Launchpad page → Click card → Navigate to /agents/[id] → Chat UI loads conversation history from Supabase → User sends message → Next.js server action → Anthropic API → Stream response to UI → Persist messages to Supabase.

Critical constraints:


Coding Conventions

TypeScript (Frontend + Backend)

SQL (Supabase)

Git

Commit Consistency

Every commit must leave the codebase in an internally consistent state. No commit may reference symbols — ADR IDs, function names, files, modules, doc cross-links — that don’t exist until a later commit.

When two changes are coupled by reference, either bundle them into one commit or order the commits so the referenced target lands first.

Why: broken intermediate states make git bisect unreliable, complicate PR review, and turn future readers of the history into archaeologists. A commit should build, lint, and read coherently when checked out in isolation.


Environment & Configuration


Testing


Security Non-Negotiables


AI Integration Rules

This app handles attorney work product, and in some future deployments may handle privileged or confidential information. Treat every AI integration accordingly.


What Not to Do


Reference Ports (Constraint C)

When a feature is being ported from an upstream reference (currently the prior agent-launchpad-template, located at ../agent-launchpad-template/ relative to this repo, and any future reference repos this project draws from), you must read the original first and replicate it field-for-field, formula-for-formula, interaction-for-interaction.

Why: paraphrased descriptions of UX leak content. Ports built against a description rather than the source drift in subtle, compounding ways — field labels shift, formulas get “simplified,” interactions get “improved.” The reference is the source of truth for behavior; only the visual style is allowed to drift (per Constraint B — shadcn defaults, no theme port).

How to apply:

  1. Locate the original file(s) in the reference repo before writing any code. Read them verbatim — do not skim.
  2. Replicate every input, every formula, every derived value, every storage key, every CSV column, every modal copy string, exactly. Number-format strings (e.g., locale + minimum/maximum fraction digits) match the original.
  3. Visual style follows Constraint B: shadcn defaults, no port of the original’s color palette, fonts, gradients, or brand styling. Layout structure (grids, ordering, button placement) does follow the original.
  4. Any deviation from the original’s behavior must be explicitly documented in DECISION_LOG.md as an exception, with the reason. “I thought this was cleaner” is not a reason.
  5. If the original has a feature this project has decided not to port (e.g., the original’s password gate, replaced here by middleware-based RBAC), call that out in the relevant DECISION_LOG entry so future reviewers can match the source against the port.

This applies to every reference port from this point forward. Sessions that port functionality begin with a verbatim read of the source; the plan presented to the user names the specific source files and line ranges read.


Documentation Rules

When making any product change (new feature, renamed component, new page, architectural change, design system change, or brand update), the following files must be checked and updated if affected:

This is not optional. Documentation updates are part of the definition of done for every change.

At the end of every phase or significant feature completion, sync generalized lessons back to the portable claude-templates library. Extract the universal principle, not the project-specific detail. If a new rule or convention is added to this project’s CLAUDE.md, evaluate whether it belongs in the template CLAUDE.md as well.

Session Close Protocol

Before declaring a session done, triple-check that what was reported shipped is actually in origin/main:

  1. git status — must show working tree clean. Anything modified or untracked is unshipped work.
  2. git log --oneline — recent commits must include the session’s deliverables.
  3. git rev-parse HEAD vs git rev-parse origin/main — must match. A local-only commit is not a shipped commit.

Why: Session 5 closed with the entire admin shell uncommitted, despite reporting “done.” The Session 5 fix audit caught the gap by running this triple-check explicitly; adopting it as session-close discipline prevents recurrence.


Skill Routing Rules (Mandatory)

Before performing any of the following types of work, you MUST read the specified skill file(s) in .claude/skills/ and follow their conventions. Do not rely on memory from previous sessions; re-read the skill file every time.

Task Type Read First Examples
Any frontend work nextjs.md + react-patterns.md + tailwind.md Components, pages, layouts, styling
Any UI/UX decision ui-patterns.md + responsive-design.md + ux-writing.md Component design, error copy, empty states
Any accessibility concern web-accessibility.md Forms, navigation, modals, keyboard flows
Any backend/API work api-security.md + backend-security.md Route handlers, server actions, proxy (proxy.ts)
Any database work supabase.md + database-patterns.md + database-security.md Schema changes, migrations, queries, RLS policies
Any auth work supabase.md + backend-security.md + api-security.md Login, role checks, session handling
Any AI/prompt work anthropic-api.md + prompt-engineering.md System prompts, Claude API calls, streaming
Any deployment/env work vercel-deployment.md + environment-management.md + infra-security.md Build config, env vars, preview deploys
Any frontend security concern frontend-security.md CSP, XSS prevention, cookie handling
Any analytics or cost work analytics.md + cost-tracking.md Event tracking, dashboards, token logging
Any model provider change model-abstraction.md Adding OpenAI, Google, or other providers
Any eval or quality work eval-framework.md + observability.md Regression tests, tracing, monitoring
Any CI/CD work ci-cd.md GitHub Actions, PR checks, deploy gates
Any work touching multiple domains Read ALL relevant skills Full-stack features, new phases

If you are unsure whether a skill applies, read it anyway. It is always better to over-consult than to miss a convention.

If a task requires a skill that does not exist in .claude/skills/ yet but exists in the claude-templates library, copy it into the project first, then read it.


Skill Template Sync Convention

At the end of every phase or sub-phase, after completing the standard documentation updates above, you MUST also sync any new patterns, lessons, or gotchas discovered during that phase to the portable skill templates at <claude-templates>/skills/.

Sync Process

  1. Review every project-specific skill file in .claude/skills/ that was referenced or updated during this phase.
  2. Extract the generalized principle. Strip out project-specific details (project names, specific API keys, specific database tables, specific design tokens) and keep the universal best practice.
  3. Update the corresponding portable template skill file with the generalized version.
  4. Create new templates. If a new skill file was created for this project that doesn’t have a portable template equivalent yet, create one in the appropriate subdirectory of <claude-templates>/skills/.
  5. Version bump. Add a version bump and “Last updated” date to any modified template skill files.

Example

If during a phase you discover that Supabase RLS policies behave differently when a service-role key is used on joined tables, the project skill gets the specific fix. The portable template gets: “When using admin/service role keys that bypass row-level security, verify behavior on queries involving joins, as RLS policies may not propagate across joined tables as expected.”

This is not optional. No phase is complete until both project-specific skills AND portable templates are current.