Skip to main content
mf² is a monorepo: multiple packages in a single repository, managed by Turborepo and Bun workspaces. The structure is predictable by design. Humans and AI agents find what they need in the same places every time.

Apps

Each app in apps/ is self-contained and deployable independently. Apps should not depend on other apps. Each has an env.ts file at the root that composes environment variables from the packages it uses. Add your deployment URLs to your environment variables under NEXT_PUBLIC_APP_URL, NEXT_PUBLIC_WEB_URL, and NEXT_PUBLIC_DOCS_URL.
AppPortSubdomainPurpose
app3000app.{yourdomain}.comMain SaaS application
web3001www.{yourdomain}.comMarketing website
api3002api.{yourdomain}.comWebhooks and cron jobs
email3003Email templates
docs3004docs.{yourdomain}.comDocumentation site
storybook6006Component workshop

Packages

Each package in packages/ wraps a single concern behind a typed interface. This makes swapping implementations easy. For example, the backend package contains everything related to Convex (schema, functions, agents). Swap the backend without touching the rest of the app. Packages export everything the apps need: middleware, hooks, components, and environment variables. Every package is scoped under @repo/:
Example imports
import { auth } from "@repo/auth";
import { Button } from "@repo/design-system/components/ui/button";
import { analytics } from "@repo/analytics";

Why this structure matters for agents

An AI agent reads one package, follows the typed exports, and makes a change. The type checker validates the result. To add a feature that touches auth and payments, the agent reads @repo/auth and @repo/payments: two focused directories, not files scattered across the tree. The apps/ and packages/ split limits blast radius. An agent modifying a package runs turbo build --filter=<package>... to verify only the affected code. Fast feedback, fewer mistakes.