← Về thư mục
📄 / / projects / tech / OpenMAIC / app / skills / openmaic / references / extend-cookbook.md

Extend The OpenMAIC Product (Cookbook)

Scope

You are working inside a fork of the OpenMAIC product (the Next.js app at the repo root), customizing it in place. If instead you want to consume @openmaic/* in a separate app, use extend-sdk.md instead.

Entry points below are given as file + symbol name (not line numbers — they drift). Read the file, then jump to the symbol. The @/* path alias is anchored at the repo root.

Task 1 — Swap Or Add An AI Provider

Goal: route generation to a different provider, or register a brand-new one.

Two distinct cases:

Gotcha: OpenMAIC has no hardcoded model fallback. If DEFAULT_MODEL is unset, generation fails rather than picking a default — always set it.

Task 2 — Enable Server-Side Persistence (PostgreSQL / S3)

Goal: persist documents, runtime state, and assets beyond the browser.

Accurate topology (there is no local-file backend):

Gotcha: bootstrap is client-side and gated on NEXT_PUBLIC_PERSISTENCE; restart the dev server after changing .env.local. S3 additionally needs @aws-sdk/client-s3 (optional peer of @openmaic/storage) installed in the app, and PG needs a reachable Postgres + the package's schema-ensure step.

Task 3 — Branding / UI / Theme

Goal: change title, fonts, color tokens, or preset themes.

Entry points:

Gotcha: This is Tailwind v4 — config lives in CSS via @theme/@source, not in tailwind.config.js. The renderer's class names are discovered through the @source scans of its dist; keep token names consistent across @theme and the renderer or styles silently drop.

Task 4 — Add A Page Or API Route

Goal: ship a new screen or a new server endpoint.

Entry points:

Gotcha: Any route that fetches a user-supplied URL must go through lib/server/ssrf-guard.ts and lib/server/proxy-fetch.ts — do not call fetch() directly with attacker-controlled hosts. LLM error responses should go through llm-error-response.ts to stay consistent with the rest of the API.

Task 5 — Embed The Renderer Or Editor

Goal: drop a slide canvas (read-only) or the full editable slide surface into a component.

Entry points (real usage examples to copy):

Gotcha (CSS is mandatory): The renderer renders unstyled/broken without its fonts and Tailwind classes. In the consuming layout/globals: @import '@openmaic/renderer/fonts.css'; (or the JS import form), and ensure the renderer's classes are in Tailwind v4's content scan (an @source directive pointing at the renderer's dist). Note fonts.css is generated (regen via the renderer's genfonts script) and self-hosts CJK faces by fetching woff2 on demand from https://file.maic.chat/fonts/<name>.woff2 — relevant for offline/custom-font operation. The editor transitively requires the renderer's full peer stack (Tailwind v4, motion, optionally echarts/shiki) — not just react/react-dom.

After Your Edits — Run And Verify

This product still runs like the stock app; don't reinvent the startup steps:

Rebuild sequence when you touch packages/@openmaic/* source: consumers resolve to the built dist/, not src/, so rebuild the changed package (dependency order: dsl → generation → storage → importer → renderer → editor). pnpm install's postinstall already does this in order; for a single package use its pnpm run build.