- Node.js 20+
- pnpm 10+ (
corepack enable) - Git
git clone https://github.com/<your-user>/mdma.git
cd mdma
pnpm install
pnpm build
pnpm testmr-mdma/
packages/
spec/ # Zod schemas, TypeScript types
parser/ # remark plugin: Markdown → MDMA AST
runtime/ # State management, event bus, policy engine
attachables-core/ # Component handlers (form, button, tasklist, …)
renderer-react/ # React renderer
prompt-pack/ # AI authoring prompts
validator/ # MDMA document validation
evals/ # LLM evaluation suite (promptfoo)
demo/ # Demo application
blueprints/ # Domain-specific MDMA documents
Managed with pnpm workspaces + Turborepo.
# Create a branch
git checkout -b feat/my-feature
# Build a single package
pnpm --filter @mobile-reality/mdma-runtime build
# Run tests for a single package
pnpm --filter @mobile-reality/mdma-runtime test
# Lint / typecheck / format
pnpm lint
pnpm typecheck
pnpm formatLLM evaluation suite using promptfoo:
# Base eval suite (25 tests)
pnpm eval
# Custom system prompt tests (10 tests)
pnpm eval:custom
# Multi-turn conversation tests (25 turns across 11 conversations)
pnpm eval:conversation
# All suites
pnpm eval:all
# View results in browser
pnpm eval:viewEvery config defaults to openai:gpt-4.1-mini (openai:gpt-4.1 for the fixer-flow / prompt-builder suites). Override the provider for a single run via EVAL_PROVIDER:
# OpenAI models — uses OPENAI_API_KEY
EVAL_PROVIDER=openai:gpt-4o pnpm eval
# Anthropic / Google / Meta via OpenRouter — uses OPENROUTER_API_KEY
EVAL_PROVIDER=openrouter:anthropic/claude-sonnet-4 pnpm eval
EVAL_PROVIDER=openrouter:google/gemini-2.5-pro pnpm eval
EVAL_PROVIDER=openrouter:meta-llama/llama-3.3-70b-instruct pnpm evalAdd OPENROUTER_API_KEY=... to evals/.env alongside OPENAI_API_KEY to enable the OpenRouter route. You can also pin a default provider in evals/.env (e.g. EVAL_PROVIDER=openrouter:anthropic/claude-sonnet-4); inline EVAL_PROVIDER=... pnpm eval still overrides it for one-off runs.
Create packages/spec/src/schemas/components/<name>.ts:
import { z } from 'zod';
import { ComponentBaseSchema } from '../component-base.js';
export const RatingComponentSchema = ComponentBaseSchema.extend({
type: z.literal('rating'),
maxStars: z.number().int().positive().default(5),
onRate: z.string().optional(),
});Register it in packages/spec/src/schemas/components/index.ts (discriminated union, COMPONENT_TYPES, componentSchemaRegistry).
Create packages/attachables-core/src/<name>/<name>-handler.ts and register it in src/_shared/register-all.ts.
Add a component in packages/renderer-react/ if the component has UI.
Add tests alongside your handler and schema. Run pnpm test to verify.
Blueprints live in blueprints/<name>/ and contain:
| File | Purpose |
|---|---|
package.json |
Workspace metadata |
manifest.yaml |
Blueprint metadata (name, version, maturity, domain) |
document.md |
The MDMA document |
demo-data/ |
Sample JSON fixtures |
Use an existing blueprint as reference.
<type>(<scope>): <description>
Types: feat, fix, docs, refactor, test, chore, ci
Scopes: package names without @mobile-reality/mdma- prefix — spec, parser, runtime, attachables-core, renderer-react, prompt-pack, validator, evals
pnpm changeset- Prettier for formatting (
pnpm format) - ESLint with
typescript-eslint - TypeScript strict mode, ESM-only
- Prefix unused parameters with
_
Contributor Covenant v2.1. Be welcoming and inclusive.
Open a Discussion or file an issue.