🛠️ MoT Software Overview (Developer)
This document explains how MoT is organized, how authentication and user scoping work, and where to extend behavior safely.
If you are onboarding, read this once front-to-back, then keep it open while navigating the codebase.
Table of Contents
- System at a Glance
- Architecture
- Repository Map
- Authentication and Identity
- Data Scoping and Persistence
- Capture and Template Pipelines
- Rules Engine
- Deep Linking (iOS Shortcuts)
- Storage Backends
- Testing and Validation
- CI/CD and Infrastructure
- Extension Playbook
- Operational Pitfalls
- Related Docs
System at a Glance
MoT has three primary surfaces:
- Backend API (
src/): source of truth for auth, Notion integration, capture/commit flows, rules, summaries, and backups. - Web console (
web/index.html): lightweight, static, operator-focused interface. - Mobile app (
mobile/): Expo/React Native client for day-to-day capture and template usage.
At runtime, both web and mobile call the same backend domain logic. The backend then orchestrates Notion + local persistence.
Architecture
Core topology
[Web UI] ----\
\ +-------------------+
[Mobile App] -----> HTTP ->| MoT Backend (TS) |-----> [Notion API]
+-------------------+
|
v
[File Storage (data/) or DB]
Runtime modes
- Local/dev mode: backend + static local web + file-backed storage.
- Production mode: AWS ALB/Cognito front door + ECS service + production API domain.
Design characteristics
- API-first backend with shared behavior across clients.
- Explicit user scoping via
userIdto isolate data and tokens. - Controlled write surface via allowlisted Notion databases.
Repository Map
| Path | Responsibility |
|---|---|
src/api/handlers.ts | Main HTTP handlers (auth, capture, rules, templates, summaries, backup, gamification). |
src/api/server.ts | Route wiring + server setup. |
src/notion/ | Notion API client utilities + schema helpers. |
src/capture/ | Propose/commit logic and routing heuristics. |
src/storage/ | File store adapters for allowlist, schema cache, rules, templates, and related state. |
src/whisper/ | OpenAI-based audio transcription integration. |
web/index.html | Minimal local web control panel. |
mobile/ | React Native + Expo app and screens. |
infra/terraform/ | AWS infrastructure as code. |
tests/ | Backend unit/integration tests. |
Authentication and Identity
MoT uses layered auth; exact behavior differs by entrypoint.
Production web (motapps.com + api.motapps.com)
- AWS ALB + Cognito + Google OAuth authenticates browser sessions.
- Backend may additionally require:
APP_ACCESS_TOKENbearer tokenALLOWED_USER_EMAILSallowlist
- Backend reads OIDC identity from ALB-injected headers and exposes session data at:
GET /auth/session
Mobile (/mobile/* style usage)
Mobile traffic is built to work even when ALB OIDC headers are not present.
- Uses
Authorization: Bearer <APP_ACCESS_TOKEN>when configured. - Sends explicit
userIdchosen in mobile settings. - If
ALLOWED_USER_EMAILSis active, backend constrains valid mobileuserIdvalues.
Notion OAuth
- Always stored per
userId. - Can be encrypted at rest when
MOT_DATA_ENCRYPTION_KEYis configured.
Identity bugs are usually userId consistency bugs—not Notion bugs.
Data Scoping and Persistence
Most durable state is keyed by userId:
- Notion OAuth credentials
- Allowlist entries
- Cached schema metadata
- Capture and summary rules
- Template definitions
- Backup cursors
- Audit artifacts
Why this matters
- Web and mobile can appear “out of sync” if they use different
userIdvalues. - Rotating
userIdin testing can produce ghost states that look like missing data.
Debug checklist for missing data
- Confirm current
userIdin client settings/session payload. - Confirm Notion OAuth exists for that same
userId. - Confirm allowlist and schema cache are populated under that
userId.
Capture and Template Pipelines
MoT supports two primary commit styles.
1) Deterministic template commits
Best for predictable, repeated workflows.
- Source: template schema + defaults + required directives
- Output: stable Notion property mapping
- Used by: form entry and template-scoped voice entry
2) AI-assisted capture commits
Best for freeform notes and quick thoughts.
- Source: text or voice transcript
- Processing: propose âžś optional follow-up âžś commit
- Constraints: allowlist + schema + rules + optional template context
Important endpoints
GET /shortcuts/templatesPOST /shortcuts/templates/upsertPOST /shortcuts/templates/install-logging-corePOST /capture/proposePOST /capture/commitPOST /notion/pages/update(post-commit edits)
Template-to-capture bridge
Templates can also be referenced by capture through generated shortcut ids:
mot-tmpl-<templateId>
This allows voice flows to inherit template constraints without duplicating config.
Rules Engine
Rules are applied in layered precedence:
- Global defaults
- Per-table capture rules
- Per-table summary rules (summary path)
Typical rule concerns
- Date column preference and fallback behavior
- Include-time toggles and default-time assumptions
- Prompt hints for extraction/formatting bias
- Property-level directives
Code touchpoints
- Mobile UI:
mobile/src/screens/RulesScreen.tsx - Web UI: rules panel in
web/index.html
Deep Linking (iOS Shortcuts)
MoT supports deep links to launch directly into:
- Template form mode
- Voice capture mode with template shortcut context
Link variants
- Expo Go links: require active dev server.
- Custom scheme app links (
mot://...): intended for installed builds.
Implementation area
mobile/src/shortcuts/handles deep link parsing and navigation wiring.
Storage Backends
Default storage is file-backed under data/ (gitignored), optimized for local and single-instance environments.
For a deeper dive, read Storage Architecture.
Production caution
File storage is risky in multi-instance deployments unless you provide:
- shared durable volume semantics,
- consistency controls, and
- robust locking/serialization.
If scaling horizontally, move toward a transactional shared datastore.
Testing and Validation
Standard commands
- Backend tests:
npm test - Mobile tests:
npm --prefix mobile test - Mobile type checks:
npm --prefix mobile run typecheck
Suggested developer rhythm
- Run focused backend tests after logic changes.
- Run mobile typecheck for any API contract / screen changes.
- Validate end-to-end flows against a known
userIdand allowlist.
CI/CD and Infrastructure
| Component | Location |
|---|---|
| CI pipeline | .github/workflows/ci.yml |
| Container release | .github/workflows/container-release.yml |
| ECS deployment | .github/workflows/deploy-ecs.yml |
| Terraform stack | infra/terraform/ |
Terraform drift note
Once CI/CD owns task definition rollouts, avoid having Terraform continuously rewrite ECS service task definition revisions. Otherwise, deployments can fight each other (“tug-of-war”).
Extension Playbook
Use this section when adding features.
Add a new API route
- Implement handler in
src/api/handlers.ts. - Register route in
src/api/server.ts. - Add client call:
- web: relevant API client module
- mobile:
mobile/src/api/motApi.ts
- Add/update tests for handler + route behavior.
Add a new template field type
- Extend schema parsing in
src/notion/schema.ts. - Update template renderer paths (web + mobile).
- Ensure mapping to Notion property payload is deterministic.
- Add tests covering field parse, form handling, and commit mapping.
Add a new rules capability
- Define precedence behavior (global vs table-level).
- Update storage model and API surface.
- Expose controls in mobile/web UIs.
- Add tests for conflict resolution and fallback logic.
Operational Pitfalls
- Mismatched
userIdcreates most “data vanished” reports. - Unshared Notion databases cause 404/permission-style errors.
- Stale schema cache causes property mapping surprises after Notion schema edits.
- Overly broad global rules can degrade extraction quality across unrelated tables.
Related Docs
- User guide: Guidebook
- Storage details: Storage Architecture
- Ops visibility: Operational Dashboards & Alerts
- AWS planning notes: AWS Deployment Plan