This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Mango is a native MongoDB GUI built with Perry (TypeScript-to-native compiler). It produces ~7 MB cross-platform binaries targeting macOS (AppKit), iOS (UIKit), Android (Views), Linux (GTK4), and Windows (Win32) from a single TypeScript codebase. It also compiles to a single self-contained HTML+WebAssembly file via --target web for in-browser use.
# Development
npm run dev # Run with hot reload (default: macOS)
npm run dev:macos # Platform-specific dev mode
npm run dev:linux # Build and run on Linux (GTK4)
npm run check # Type-check via Perry
# Build
npm run build # All platforms
npm run build:macos # Platform-specific builds
npm run build:linux
npm run build:windows
# Web (WebAssembly + DOM bridge in a single self-contained HTML file)
perry compile src/app.ts --target web -o dist/mango.html
# Serve over HTTP so fetch() works (file:// hits CORS)
python3 -m http.server 8765 -d dist
open http://localhost:8765/mango.html
# Testing (uses Bun, not Node)
npm test # All tests
npm run test:unit # Unit tests only
npm run test:integration # MongoDB integration tests
bun test tests/connection-store.test.ts # Run a single test fileThree-layer design:
-
UI Layer (
src/app.ts) — Single-file UI using Perry's native widget bindings (VStack, HStack, TextField, etc.). Uses manual screen indexing and global state arrays for navigation, not a reactive framework. All UI updates are direct Perry API calls. -
Data Layer (
src/data/) — Class-based stores:ConnectionStore— SQLite CRUD for connection profiles; passwords stored in platform Keychain, never SQLiteMangoClient— MongoDB driver wrapper with query, document CRUD, stats, and index operationsPreferencesStore— SQLite-backed user settings with in-memory cachedatabase.ts— SQLite singleton viagetDatabase()
-
Theme Layer (
src/theme/) — RGBA-based color system with light/dark themes and platform-specific typography (SF Mono on macOS, JetBrains Mono on Linux, etc.)
- Perry, not Electron: UI uses Perry's native bindings, not DOM/HTML. No
document,window, or CSS — use Perry widget types and RGBA colors. (On the--target webbuild, Perry's WASM runtime maps every widget to a DOM element under the hood, but the source code stays the same — you never write HTML.) - Path alias:
@/*maps tosrc/*in imports. - External editor widget:
@honeide/editoris a local dependency (file:../hone/hone-editor) used for document editing. - Test mocks: Perry APIs and MongoDB are mocked in
tests/mocks/. Tests preloadtests/preload.tsvia bunfig.toml. Usereset-database.tsto clear state between tests. - Connection URI building:
ConnectionStore.buildConnectionUri()handles auth mechanisms (SCRAM-SHA-256, etc.) and TLS options. Always use this rather than constructing URIs manually.
perry compile src/app.ts --target web produces a single ~4 MB self-contained HTML file with the WebAssembly binary, the JS bridge for DOM widgets, and all string/data sections embedded. It's the same backend as --target wasm; both flags produce identical output.
Platform branches with __platform__ === 5 cover the web case:
- Connection storage:
connection-store.tsfalls back to an in-memorywebTransientstore on web instead of SQLite (which doesn't compile to WASM). Connection profiles are not persisted across reloads in the browser. - Keychain: maps to
localStorage(Perry's web bridge). Fine for connection metadata but not for production secrets — anything in localStorage is readable by other scripts in the same origin. - Hone code editor: requires native FFI (
hone_editor_*) that has no browser implementation. Perry's WASM bridge auto-stubs these to no-ops via aProxy, so the editor area shows up but key/mouse handling is inactive. Document editing works with the plain<textarea>fallback. - MongoDB driver: native MongoDB doesn't run in the browser. The web build needs to talk to a Mango Server proxy (
web-mongo-client.tsoverfetch). For local testing, run mongod + mango-server alongside the served HTML and update the connection string. - fetch / CORS: any third-party URL (telemetry, public APIs) must allow your origin. Mango's
trackEventwill silently fail with a CORS error fromfile://and from origins not whitelisted byapi.chirp247.com— this is expected and the catch intrackEventswallows it. - Serving: must be served over HTTP, not opened directly via
file://(browsers rejectfetch()from file URLs). Any static server works (python3 -m http.server,npx serve, etc.).