A handwriting-first AI study whiteboard. You write on an infinite board; Slate reads your handwriting, solves or explains the problem with a tool loop (a language model plus a real calculator and computer-algebra engine), and writes the working back in your own handwriting.
This repository is the open-source edition of Slate. It is the same web app, API server, Android shell and desktop shell that power the hosted product, with the commercial parts removed (see What this edition leaves out).
- What it does
- What this edition leaves out
- Repository layout
- Requirements
- Quick start
- Commands
- How it fits together
- Security and privacy
- Licence and trademark
- Contributing
- Status
- An infinite whiteboard with pen, highlighter, shapes, diagrams, images and multiple boards (each with rough-work sub-boards), stored on the device and synced to the account.
- Handwriting recognition that turns written answers into structured text.
- Solving and explaining with a tool loop: the model reads the board, calls a calculation engine, checks its own result, and writes the answer back in handwriting. Systems of equations, calculus, units and significant figures are verified where possible.
- Study notes — a set of notes planned section by section, with questions asked along the way.
- Diagrams and molecules drawn on the board from a description.
- Search, videos and images to look things up without leaving the board.
- Collaboration rooms — six-character room codes, live board sharing, cursors, voice, and per-person boards, backed by Firebase Realtime Database.
- Public share links — a read-only snapshot of a board at
/s/<id>. - Android and Windows shells that wrap the hosted web app (Capacitor and Electron).
The hosted commercial product includes paid plans, a trial, Razorpay subscriptions, an admin panel with encrypted provider keys and model routing, coupon codes, usage billing, and a legacy Python API. All of that is removed here, not merely disabled:
- no pricing, checkout, subscription, invoice or plan-gate code;
- no admin panel, no provider-key store, no runtime model routing (AI configuration is environment variables only);
- no billing documents in Firestore (
/billing/**is denied by the shipped rules); - no legacy
services/apiPython service.
Quotas remain, but only as abuse protection: every signed-in account gets the same daily
per-feature caps and AI token budget, configurable by the operator. They are not a commercial
feature and never return HTTP 402. The seam for building an edition with different entitlements is
services/server/src/entitlements.ts.
The Slate name and logo ship with the app but are not licensed to you by the AGPL grant; see TRADEMARK.md.
apps/
web/ React 19 + Vite web app, Capacitor Android project, PWA assets
desktop/ Electron shell for Windows (loads your deployment over HTTPS)
services/
server/ Node 22 + Express 5 API: auth, limits, AI routes, static web serving
firebase.json, firestore.rules, database.rules.json, firestore.indexes.json
docs/legal/ DRAFT Terms and Privacy Policy templates
There is no Python service and no admin client in this tree.
- Node.js 22.18 or newer (the server and tests run TypeScript directly).
- A Firebase project with:
- Google sign-in enabled (Firebase Authentication);
- Cloud Firestore;
- Realtime Database (for collaboration rooms);
- optionally Analytics;
- a service account key for the Admin SDK (the server verifies ID tokens and writes counters).
- An AI provider: Groq (default) and/or Anthropic, or any OpenAI-compatible gateway you point
EXPLABS_BASE_URLat. Only the provider(s) you configure are called. - For the Android build: Android Studio / the Android SDK, and your own
google-services.json. - For the desktop build: Windows, or Electron's cross-platform packaging.
-
Clone and install
git clone <your-fork-url> slate cd slate npm ci --prefix services/server npm ci --prefix apps/web npm ci --prefix apps/desktop
-
Configure Firebase
Follow docs/DEVELOPMENT.md. In short: create a project, enable Google sign-in and Firestore, copy the web config into
apps/web/.env, create a service account and base64 it intoFIREBASE_SERVICE_ACCOUNTfor the server, then deploy the rules:npx firebase-tools deploy --only firestore:rules,database --project <your-project-id>
The server's
FIREBASE_PROJECT_IDmust match the web app's project. -
Configure the AI provider
cp services/server/.env.example services/server/.env # set GROQ_API_KEYS and/or ANTHROPIC_API_KEY -
Run it
npm run dev --prefix services/server # API on http://127.0.0.1:8787 npm run dev --prefix apps/web # web app on http://127.0.0.1:5173 (proxies /api)
Open
http://127.0.0.1:5173and sign in with Google. The Google account must be allowed by Firebase Auth's authorised domains (addlocalhostfor development). -
Build for production
npm run build --prefix apps/web npm run build --prefix services/server NODE_ENV=production SLATE_SERVE_WEB=1 npm start --prefix services/server
The server serves
apps/web/distand the API from one origin — see docs/DEPLOYMENT.md.
| Where | Command | What it does |
|---|---|---|
services/server |
npm run dev |
Watch-mode API server |
npm test |
Full API test suite (node --test, about 25 s) |
|
npm run typecheck |
TypeScript check, no output | |
npm run build |
Compile to dist/ |
|
apps/web |
npm run dev |
Vite dev server with /api proxy |
npm test |
Board/geometry/biology/chemistry test suite | |
npm run build |
Typecheck plus production bundle | |
npm run lint |
oxlint | |
apps/desktop |
SLATE_URL=https://your.site npm start |
Run the Electron shell |
npm run dist |
Build the Windows NSIS installer | |
apps/web/android |
npx cap sync android |
Copy the web build into the Android project |
./gradlew assembleDebug |
Build a debug APK |
┌────────────┐ /api (Bearer Firebase ID token) ┌──────────────────────┐
│ web / PWA │ ──────────────────────────────────▶ │ Node API (Express) │
│ Android │ │ auth · quotas · AI │
│ Electron │ ◀── Firestore sync, RTDB rooms ───▶ │ static web serving │
└────────────┘ └──────────┬───────────┘
│ │
▼ ▼
Firebase Auth / Firestore / RTDB Groq, Anthropic, or your gateway
- The browser talks to Firebase directly for auth, board sync and collaboration.
- Everything AI-related goes through the API, which verifies the ID token, enforces per-account and per-IP limits, and calls the configured provider.
- The same origin serves the built web app, so the app calls
/apirelatively.
More detail: docs/ARCHITECTURE.md.
- Firebase ID tokens are verified on every API call, with revocation checks.
SLATE_AUTH_DISABLEDexists for local development and is ignored whenNODE_ENV=production. - Firestore rules restrict boards and profile data to their owner;
/usage/**,/devices/**and entitlement fields are server-written only; everything else is denied.billing/**does not exist in this edition. - The API sets a strict Content-Security-Policy, CORS allow-list, body-size limits and per-IP rate
limits. See
services/server/src/http.ts. - AI requests send the relevant part of the board to the operator's chosen AI provider. Operators must disclose and govern that in their own privacy policy — the shipped policy is a DRAFT template.
- Recognition records (a picture of the student's writing plus what was read from it) are not
kept by default.
SLATE_SAVE_SAMPLES=1turns that on for measuring accuracy; an operator who enables it must disclose the retention, because the files are personal data. - The open-source edition ships no production Firebase project, signing keys, service-account JSON, release signing configuration, customer data or deployment scripts.
Report vulnerabilities per SECURITY.md. Never open a public issue with exploit details.
The code is licensed under the GNU Affero General Public License v3.0 only
(AGPL-3.0-only). See LICENSE and NOTICE. If you run a modified version as a
network service, AGPL section 13 requires you to offer its users the corresponding source.
The Slate name and logo are trademarks of the project maintainers and are not granted by the code licence. Forks that are not the official project must use a different name and icon, or comply with TRADEMARK.md.
Read CONTRIBUTING.md and CODE_OF_CONDUCT.md. By contributing you agree your contribution is licensed under AGPL-3.0-only (inbound = outbound).
This edition is derived from a working production application and its core test suites pass (see CHANGELOG.md for numbers). It is not a hardened multi-tenant distribution: you supply your own Firebase project, AI keys, hosting, privacy notices and legal documents. The in-app Terms and Privacy Policy are DRAFT templates that require review by a qualified lawyer in your jurisdiction before you operate a public deployment. There is no support or uptime commitment; see SUPPORT.md.
