# Foundation MVP > Build and deploy apps with auth, billing, data, AI, and integrations — configured, not coded. ## Agent Views - Foundation App Builder: https://docs.foundationmvp.com/agents/foundation-app-builder.md - Foundation Deploy Contract: https://docs.foundationmvp.com/agents/foundation-deploy-contract.md - Foundation SDK Reference: https://docs.foundationmvp.com/agents/foundation-sdk-reference.md - Page Contract: https://docs.foundationmvp.com/agents/page-contract.md --- # Foundation App Builder Canonical agent workflow for frontend apps that consume the Foundation backend through `foundation-sdk`. Last updated: 2026-06-29 ## Use This When - Creating a new Foundation-backed web app. - Adding Foundation SDK integration to an existing React, Vue, Svelte, Next, or plain web app. - Adding Foundation-backed features such as auth, database CRUD, files, integrations, account screens, OAuth consent, or config-driven UI. - Reviewing a consumer app before Foundation deployment. ## Required References - SDK reference: https://docs.foundationmvp.com/agents/foundation-sdk-reference.md - Deploy contract: https://docs.foundationmvp.com/agents/foundation-deploy-contract.md - Full docs bundle: https://docs.foundationmvp.com/llms-full.txt ## Workflow Classify the request first: - New app: create or adapt a frontend app that consumes Foundation. - Existing app: add Foundation SDK initialization, auth, services, or deployment files without rewriting unrelated code. - Feature: add one Foundation-backed workflow to an app that already has SDK initialization. - Review: audit SDK usage and deploy readiness. ## New App Or Retrofit 1. Inspect the existing repo before editing. Preserve framework, routing, styling, and state-management conventions. 2. Install `foundation-sdk` plus the selected auth peer: `aws-amplify` for Cognito or `@auth0/auth0-spa-js` for Auth0. 3. Create one SDK initialization module or provider. Await `createFoundation(...)` once and share the instance through app context/state. 4. Support local development with explicit `configUrl`, `tenantId`, `appId`, and optional dev-only `baseUrl`. 5. Support production by allowing `createFoundation({ auth })` to read `/foundation-env.json`. 6. Implement login, registration, auth callback, logout, and guarded routes as requested. 7. Build the requested core workflow with `foundation.db`, `foundation.files`, `foundation.integration`, `foundation.account`, `foundation.oauth`, `foundation.config`, or `foundation.log`. 8. Add `mvp.config.json` at the app repo root and verify its output directory and entry file. 9. Run available typecheck, lint, tests, and build scripts. ## Feature Additions Reuse the existing Foundation instance. Do not introduce a second `createFoundation()` call. Keep service calls in the app's established data layer, hook, store, or route loader pattern. Add loading, empty, success, and error states. Handle unauthenticated users before calling authenticated services. Use pagination for lists that can grow, compute `sha256` before file upload, refresh integration status after connect/disconnect, and respect `foundation.config` for backend-provided theme, features, plans, connectors, and resources. ## Review Mode Use a code-review stance. Lead with findings ordered by severity and include file/line references. Prioritize: - Missing or invalid `mvp.config.json`. - Build output mismatch with `files` or `entry`. - Missing SDK or auth peer dependency. - Wrong auth provider entry point. - Un-awaited or duplicated SDK initialization. - Production code that depends on dev-only `baseUrl`. - Sign-in or sign-up flows that ignore result objects. - Missing hosted-login callback handling. - Unguarded authenticated routes. - File uploads without `sha256`. - Integration flows that only handle one connect response shape. - Frontend secrets or hardcoded user tokens. If no major issues are found, say so and list remaining test gaps or backend assumptions. ## Default `mvp.config.json` ```json { "build": "npm install && npm run build", "files": "dist", "entry": "index.html", "sdk": "^1.0.0" } ``` Adjust `files` and `entry` only when the chosen framework uses a different build output. ## Starter User Prompt ```text Use https://docs.foundationmvp.com/agents/foundation-app-builder.md to build a production-ready frontend app that consumes the Foundation backend. App goal: Framework and router: Styling system: Auth provider: Cognito or Auth0 Foundation config URL for local development: Foundation tenant ID for local development: Foundation app ID for local development: Optional local API proxy base URL: Entities to use through foundation.db: File workflows to support through foundation.files: Integrations to support through foundation.integration: Account/profile fields: Deployment output directory: Deployment entry file: ``` --- # Foundation Deploy Contract For Agents Canonical deployment reference for Foundation consumer app repositories. Last updated: 2026-06-29 ## Required File Consumer app repositories need `mvp.config.json` at the repo root. Default: ```json { "build": "npm install && npm run build", "files": "dist", "entry": "index.html", "sdk": "^1.0.0" } ``` Fields: - `build`: command Foundation runs before deployment. - `files`: build output directory to upload. - `entry`: app entry file inside `files`. - `sdk`: SDK compatibility hint. - `node`: optional Node major version. ## Deployment Flow Foundation reads `mvp.config.json` from GitHub, downloads the repo, runs the build command, uploads the configured output directory, and writes `/foundation-env.json` next to the built assets. The app should not create `/foundation-env.json` itself for production deployment. Foundation writes it. ## Runtime Identity `foundation-env.json` contains runtime identity: ```json { "applicationId": "app-id", "applicationTenant": "tenant-id", "applicationVersion": "1.0.0", "configUrl": "https://backend.example.com/api/v1/public/init" } ``` The SDK reads this file automatically in production. When it is present, values from the file override local options and `baseUrl` is cleared. ## Local Development Local development should pass explicit SDK config: ```ts await createFoundation({ configUrl: import.meta.env.VITE_FOUNDATION_CONFIG_URL, tenantId: import.meta.env.VITE_FOUNDATION_TENANT_ID, appId: import.meta.env.VITE_FOUNDATION_APP_ID, baseUrl: import.meta.env.VITE_FOUNDATION_API_BASE_URL, auth }) ``` `baseUrl` is optional and dev-only. Use it for local proxies to avoid CORS while developing against a remote backend. ## Verification Checklist - `mvp.config.json` exists at the repo root. - `mvp.config.json` has `build`, `files`, and `entry`. - The configured `build` command succeeds. - The configured `files` directory exists after build. - The configured `entry` file exists inside `files`. - SDK initialization works with explicit local config. - Production code can initialize from `/foundation-env.json`. - Production code does not require `baseUrl`. - Built frontend assets do not include private secrets or service credentials. --- # Foundation SDK Reference For Agents Canonical integration reference for apps that use `foundation-sdk`. Last updated: 2026-06-29 ## Install ```bash npm install foundation-sdk npm install aws-amplify ``` Use `aws-amplify` only for Cognito apps. For Auth0 apps, install `@auth0/auth0-spa-js` instead. ## Initialize Cognito: ```ts import { createFoundation } from 'foundation-sdk' import { cognitoAuth } from 'foundation-sdk/cognito' const foundation = await createFoundation({ configUrl: import.meta.env.VITE_FOUNDATION_CONFIG_URL, tenantId: import.meta.env.VITE_FOUNDATION_TENANT_ID, appId: import.meta.env.VITE_FOUNDATION_APP_ID, baseUrl: import.meta.env.VITE_FOUNDATION_API_BASE_URL, auth: cognitoAuth }) ``` Auth0: ```ts import { createFoundation } from 'foundation-sdk' import { auth0Auth } from 'foundation-sdk/auth0' const foundation = await createFoundation({ configUrl: import.meta.env.VITE_FOUNDATION_CONFIG_URL, tenantId: import.meta.env.VITE_FOUNDATION_TENANT_ID, appId: import.meta.env.VITE_FOUNDATION_APP_ID, baseUrl: import.meta.env.VITE_FOUNDATION_API_BASE_URL, auth: auth0Auth }) ``` Production may omit identity values: ```ts const foundation = await createFoundation({ auth: cognitoAuth }) ``` `/foundation-env.json` overrides `configUrl`, `tenantId`, `appId`, and clears `baseUrl`. ## Critical Rules 1. Always await `createFoundation(...)`. 2. Initialize the SDK once and share it through app context/state. 3. Use exactly one auth provider entry point unless building separate variants. 4. Do not put private secrets in frontend code. 5. Set `window.__foundation = foundation` only when using `foundation-sdk/components`. 6. Treat `baseUrl` as dev-only. ## Auth Available methods: ```ts foundation.auth.user foundation.auth.isAuthenticated foundation.auth.getToken() foundation.auth.login(options?) foundation.auth.logout(options?) foundation.auth.handleCallback(url?) foundation.auth.signIn(email, password) foundation.auth.signUp(email, password, metadata?) foundation.auth.confirmSignUp(email, code) foundation.auth.resendSignUpCode(email) foundation.auth.forgotPassword(email) foundation.auth.resetPassword(code, newPassword) foundation.auth.onChange(callback) ``` Sign-in pattern: ```ts const result = await foundation.auth.signIn(email, password) if (result.isSignedIn) { router.push('/dashboard') } else if (result.nextStep?.signInStep === 'CONFIRM_SIGN_UP') { router.push({ path: '/confirm', query: { email } }) } ``` Sign-up pattern: ```ts const result = await foundation.auth.signUp(email, password, { name }) if (result.isSignUpComplete) { showCheckEmail() } else if (result.nextStep?.signUpStep === 'CONFIRM_SIGN_UP') { showCodeConfirmation() } ``` Call `foundation.auth.handleCallback()` on hosted-login callback routes. Subscribe with `foundation.auth.onChange()` or refresh auth state after login, logout, callback, and registration. ## Database ```ts foundation.db.list(entity, options?) foundation.db.get(entity, id) foundation.db.create(entity, data) foundation.db.update(entity, id, updates) foundation.db.save(entity, data) foundation.db.delete(entity, id) ``` List options: ```ts { filters?: Record limit?: number cursor?: string orderBy?: string orderDir?: 'asc' | 'desc' } ``` Paginated list: ```ts let cursor: string | undefined const all = [] do { const { items, nextCursor } = await foundation.db.list('projects', { limit: 50, cursor }) all.push(...items) cursor = nextCursor } while (cursor) ``` ## Files ```ts foundation.files.upload({ name, contentType, file, sha256 }) foundation.files.initiate({ name, contentType, contentLength, sha256, metadata? }) foundation.files.get(fileId) foundation.files.delete(fileId) foundation.files.list({ limit?, cursor? }?) ``` Compute SHA-256 before upload: ```ts const result = await foundation.files.upload({ name: file.name, contentType: file.type, file, sha256 }) ``` Use `initiate` only when the app needs manual control of the signed upload. ## Integrations ```ts foundation.integration.all() foundation.integration.list() foundation.integration.connections() foundation.integration.status(source) foundation.integration.connect(source) foundation.integration.disconnect(source, configurationId) ``` Use `foundation.integration.all()` for catalog plus current connection state. Use `foundation.integration.connect(source)`. If the result includes a `url`, open a popup or redirect and refresh connection status after completion. Also handle immediate success/configuration responses. Use `disconnect(source, configurationId)` only after clear user confirmation. ## Account ```ts foundation.account.get() foundation.account.update(data) foundation.account.usage() foundation.account.resendVerification() ``` ## OAuth Consent For apps acting as OAuth authorization servers: ```ts const client = await foundation.oauth.getClient(clientId) const { code } = await foundation.oauth.authorizeConsent({ client_id, redirect_uri, scope, state, code_challenge, code_challenge_method }) ``` Only call `authorizeConsent` after explicit user approval, then redirect back with `code` and `state`. ## Config ```ts foundation.config.app foundation.config.features foundation.config.plans foundation.config.theme foundation.config.connectors foundation.config.resources foundation.config.auth foundation.config.raw ``` Use backend config to hide unavailable UI and apply theme or plan-aware behavior. ## Logging ```ts foundation.log.info(message, context?) foundation.log.warn(message, context?) foundation.log.error(message, context?) foundation.log.event(eventName, data?) ``` Logging is fire-and-forget. Do not block UI on logging. ## Web Components ```ts import 'foundation-sdk/components' ;(window as any).__foundation = foundation ``` ```html ``` Events: `success`, `error`, `close`. For Vue, configure `isCustomElement` for `foundation-*` tags. --- # Foundation Docs Page Contract How feature documentation is structured, so humans and agents can navigate it predictably. Last updated: 2026-06-29 ## Why This Exists Every platform feature page (`/platform/*`) follows a fixed section structure. Because the structure is fixed, an agent can fetch the page's raw Markdown twin and reliably locate a section by a heading it already knows — no per-page guessing. Each rendered page is also available as raw Markdown by appending `.md` to its path: ```text https://docs.foundationmvp.com/platform/billing (HTML, for humans) https://docs.foundationmvp.com/platform/billing.md (Markdown, for agents) ``` ## Required Sections Every feature page has these H2 headings, in this order: ```markdown ## Configure — set the feature up on the platform. No code. Reads for non-developers. ## Use in your app — wire the feature into a frontend built on foundation-sdk. Real SDK calls. ## Reference — thin list of links to deeper references (SDK, API, related features). ``` Feature-specific H2s may appear between `Configure` and `Reference`, but the three above are always present and always in this order. ## Anchors Are Predictable Heading slugs follow the GitHub algorithm: lowercase, spaces to hyphens, punctuation dropped. The same slug is used for the HTML anchor and the Markdown heading, so: - `## Use in your app` → anchor `#use-in-your-app` (in both surfaces) - An agent can split a fetched `.md` on lines matching `^## ` and select a block by its known heading. A URL fragment (`...billing.md#use-in-your-app`) is **not** sent to the server — fetching always returns the whole file. "Hop to a section" means: fetch the page, then seek the known heading. For section-level *retrieval* (just one block returned), use the MCP `get_docs` tool, which slices the same source on this contract. ## Authoring Rules 1. Pure Markdown only — no VitePress containers (`:::tip`), no `