This version has breaking changes - APIs, conventions, and file structure may all differ from your training data. Read the relevant guide in node_modules/next/dist/docs/ before writing any code. Heed deprecation notices.
Mongui is a lightweight, self-hosted web UI for browsing and editing MongoDB. The full product plan lives in PLAN.md and the detailed requirements in REQUIREMENTS.md. Read both before making feature decisions.
| Layer | Choice | Version |
|---|---|---|
| Framework | Next.js (App Router, Turbopack) | 16.2.6 |
| Runtime | React | 19.2.4 |
| Language | TypeScript | 5.x |
| DB driver | mongodb (official Node driver) |
7.2.0 |
| Styling | Tailwind CSS | 4.x |
| Lint | ESLint + eslint-config-next |
9.x / 16.2.6 |
Planned additions (not yet installed): shadcn/ui, @tanstack/react-table, @tanstack/react-query, CodeMirror 6 (@codemirror/lang-json), iron-session, bcryptjs, zod.
src/
app/
login/page.tsx
(dashboard)/
layout.tsx # sidebar + auth guard
page.tsx # DB/collection overview
[db]/[collection]/page.tsx # document browser
api/
health/route.ts # DONE - ping + server version
auth/login/route.ts
auth/logout/route.ts
databases/route.ts
databases/[db]/collections/route.ts
databases/[db]/[collection]/docs/route.ts
databases/[db]/[collection]/docs/[id]/route.ts
databases/[db]/[collection]/aggregate/route.ts # POST aggregation pipeline (capped, READ_ONLY-aware)
databases/[db]/[collection]/indexes/route.ts # list/create/drop indexes
lib/
mongo.ts # DONE - cached MongoClient singleton + getCollection + MAX_TIME_MS
session.ts # iron-session config + auth guard helper
auth.ts # bcrypt credential verification
http.ts # error envelope + ValidationError -> 400 / MongoServerError -> 400 / else 500
rate-limit.ts # in-memory login brute-force limiter
api-client.ts # browser fetch helper + encodeDocId (client-safe, no driver import)
ejson.ts # safe EJSON parse/serialize (ObjectId, Date, ...)
validate.ts # filter/body validation (zod) + parsePipeline/pipelineWrites
- Single connection model. The app connects to exactly one MongoDB defined by
MONGODB_URI. Do not add multi-connection logic; it is explicitly out of MVP scope (seePLAN.mdsection 4). - Reuse the client singleton. Never call
new MongoClient(...)outsidesrc/lib/mongo.ts. ImportgetClient/getDbinstead. The singleton is cached onglobalThisto survive hot reloads. - EJSON end to end. All document data crossing the API boundary must use Extended JSON via the driver's
BSON.EJSON. PlainJSON.stringifysilently corruptsObjectId,Date,Decimal128, etc. Centralize parse/serialize insrc/lib/ejson.tsand route all document I/O through it. - Auth on every API route. Every route under
src/app/api/exceptauth/loginmust verify the session first and return 401 when absent. Use the shared guard fromsrc/lib/session.ts. - Honor READ_ONLY. When
READ_ONLY=true, all POST/PUT/DELETE handlers must reject writes with 403 before touching the database. Enforce this in one shared place, not per route. - Validate and cap user input. Run user-supplied filters, sorts, and projections through
src/lib/validate.ts(zod). Always caplimit(max 200) and reject unparseable filters with 400. - Confirm destructive actions. Drop collection and delete document require explicit confirmation in the UI (typed name for drops).
- TypeScript strict mode; no
anyin committed code (useunknown+ narrowing). - API routes return
NextResponse.json(...); error shape is{ status: "error", message: string }with an appropriate HTTP code. Success health shape is{ status: "ok", ... }. - Mark DB-touching routes
export const dynamic = "force-dynamic"so they are never statically cached. - Server Components by default; add
"use client"only for interactive pieces (tables, editors, forms). - Keep secrets in
.env.local(gitignored)..env.exampledocuments every variable.
npm run dev # dev server (Turbopack) on :3000
npm run build # production build
npm run start # serve production build
npm run lint # eslint
npm test # vitest unit tests (src/**/*.test.ts)A MongoDB 7 instance is reachable at mongodb://localhost:27017 on this machine (a djp-mongo container publishes 27017; it has no auth, so credentials in the URI will fail). If .env.local still carries credentials from an older container, override with MONGODB_URI=mongodb://localhost:27017 when testing. Verify connectivity with:
curl -s http://localhost:3000/api/health
# -> {"status":"ok","ping":true,"serverVersion":"7.0.34"}See PLAN.md section 6. Status:
- Phase 1 - Scaffold + Mongo singleton +
/api/health(verified) - Phase 2 - Auth (login, iron-session, guards) (verified)
- Phase 3 - Navigation (list dbs + collections) (verified)
- Phase 4 - Browse (paginated document table) (verified)
- Phase 5 - Query (filter/sort/projection) (verified)
- Phase 6 - Read doc (CodeMirror detail view) (verified)
- Phase 7 - Mutations (insert/edit/delete) (verified)
- Phase 8 - Collection ops (create/drop) (verified)
- Phase 9 - Polish (status badge, toasts, empty/loading states)
- Phase 10 - Open-source prep (Docker, README, license, CI)
Post-MVP additions (beyond the phase list): aggregation runner and index
management, both under [db]/[collection] (see project layout above).
Note: auth uses a plaintext ADMIN_PASSWORD (hashed by the app at runtime),
not a precomputed ADMIN_PASSWORD_HASH.
Implement phases in order; each should leave the app runnable.