An adaptive learning platform — the user states a goal, the agent runs itself: it builds a project-based curriculum, teaches just-in-time, evaluates code, and reshapes the next ten days at every checkpoint.
Live: https://dex-web-276675702209.us-central1.run.app — sign in with Google or "Walk through as a guest" to land in a course already in progress.
Hexagonal — each layer is its own package, dependency arrows point one way only.
@dex/domain ◄──── @dex/ports ◄──── @dex/application
▲ ▲ ▲
│ │ │
└─── @dex/adapter-mongodb ◄─┐ │
└─── @dex/adapter-gemini ◄──┤ │
└─── @dex/adapter-cloud-run ┤ │
└─── @dex/adapter-firebase ─┘ │
▲ │
│ │
└───── @dex/api ┘ ──► Cloud Run (dex-api)
@dex/domain ◄── @dex/web ──► Cloud Run (dex-web)
(types only)
| Package | Purpose | Deps |
|---|---|---|
packages/domain |
@dex/domain — types + errors (immutable core) |
— |
packages/ports |
@dex/ports — interfaces |
@dex/domain |
packages/application |
@dex/application — use cases (the adaptive loop) |
@dex/domain, @dex/ports |
packages/adapter-mongodb |
@dex/adapter-mongodb — Mongo repos + memory log |
@dex/domain, @dex/ports, mongodb |
packages/adapter-gemini |
@dex/adapter-gemini — Vertex AI + MongoDB MCP client |
@dex/domain, @dex/ports, @google/genai, @modelcontextprotocol/sdk |
packages/adapter-cloud-run |
@dex/adapter-cloud-run — sandbox |
@dex/domain, @dex/ports, google-auth-library |
packages/adapter-firebase |
@dex/adapter-firebase — auth (Admin SDK) |
@dex/domain, @dex/ports, firebase-admin |
apps/api |
@dex/api — Hono server + middleware + routes + composition root |
all @dex/* + hono |
apps/web |
@dex/web — Next.js frontend |
@dex/domain, firebase (client), next |
SDK confinement is enforced by package.json dependencies, not ESLint — domain/ports/application don't list any vendor SDKs, so TypeScript can't resolve them. Each adapter package lists exactly one vendor SDK.
The persona system instruction is injected at composition time, not read by the adapter — apps/api/src/container.ts reads apps/api/prompts/persona.md once at startup and passes it into GeminiAgentAdapter via config. The adapter has no file-read side effects on import.
- Node 22.x (uses
--env-file; native ESM/TS) andpnpm9.x - A MongoDB cluster (Atlas, or local via
docker run -d -p 27017:27017 mongo:7— both JSON-schema validators and time-series collections work on stockmongo:7) - A GCP project with Vertex AI enabled, and
gcloud auth application-default loginrun once (Vertex auth uses Application Default Credentials, not a key in env) - A Firebase project (Auth) linked to the same GCP project
pnpm installTwo apps, two env files (gitignored via .env*).
apps/api/.env.local
# ── Mongo ──
ATLAS_URI=mongodb+srv://dex-app:<pw>@<cluster>/?retryWrites=true # or mongodb://localhost:27017
MONGO_DB_NAME=dex
# ── Firebase Admin (server token verification) ──
# Minified service-account JSON on ONE line — the code does JSON.parse(...).
FIREBASE_ADMIN_KEY={"type":"service_account","project_id":"...", ... }
# ── Vertex AI / Gemini ──
GCP_PROJECT_ID=<your project id>
GCP_REGION=us-central1
# Optional model overrides (defaults: gemini-2.5-flash / gemini-2.5-pro)
# GEMINI_FLASH_MODEL=gemini-2.5-flash
# GEMINI_PRO_MODEL=gemini-2.5-pro
# ── Agentic read path (read-only MongoDB MCP server, see step 3) ──
MCP_MONGODB_URL=http://localhost:3001/mcp
# ── Server ──
WEB_ORIGIN=http://localhost:3000 # CORS allow-list
PORT=8080apps/web/.env.local
NEXT_PUBLIC_API_BASE_URL=http://localhost:8080
NEXT_PUBLIC_FIREBASE_API_KEY=<from Firebase web config>
NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN=<from Firebase web config>
NEXT_PUBLIC_FIREBASE_PROJECT_ID=<from Firebase web config>Only ATLAS_URI (api) and the four web vars are strictly required to boot.
FIREBASE_ADMIN_KEY is required the moment an authenticated request arrives;
MCP_MONGODB_URL only when an agentic call (materialise/evaluate/replan/⌘K) runs.
pnpm --filter @dex/api db:applyIdempotent — creates all 13 collections with validators + indexes (see
infra/mongodb/schema.md). Uses the project's own
mongodb driver; mongosh is not required.
This is the agent's read path (materialise / evaluate / replan / ⌘K) and
the Partner-MCP integration for this hackathon. Run it via npx — no install
required — Streamable HTTP transport on /mcp:
MDB_MCP_CONNECTION_STRING="<your mongo URI>" \
npx -y mongodb-mcp-server@latest --readOnly --transport http --httpPort 3001--readOnly strips every create/update/delete/drop and atlas-* tool — the
agent literally cannot mutate through this server. (Verified against
mongodb-mcp-server 1.12.0.) The agent connects via
@google/genai's mcpToTool() wrapping an MCP Client
(@modelcontextprotocol/sdk, StreamableHTTPClientTransport) — see
packages/adapter-gemini/src/agent.adapter.ts.
Skipping this is fine while working on UI or non-agentic endpoints — the agent throws a clear
MCP_MONGODB_URL not setonly when an agentic call runs.
pnpm dev # both apps in parallel
# or individually:
pnpm dev:api # Hono on :8080
pnpm dev:web # Next on :3000Open http://localhost:3000. Verify the api is wired with curl localhost:8080/health.
- Design handoff (dossier + prototype + components) →
design_handoff/ - MongoDB schema →
infra/mongodb/schema.md - Agent persona (system instruction) →
apps/api/prompts/persona.md - MCP + Vertex AI integration →
packages/adapter-gemini/src/agent.adapter.ts
MIT — see LICENSE.