Package Exports
- @mandujs/core
- @mandujs/core/brain/adapters/base.ts
- @mandujs/core/brain/adapters/index.ts
- @mandujs/core/brain/adapters/ollama.ts
- @mandujs/core/brain/architecture/analyzer.ts
- @mandujs/core/brain/architecture/index.ts
- @mandujs/core/brain/architecture/types.ts
- @mandujs/core/brain/brain.ts
- @mandujs/core/brain/doctor/analyzer.ts
- @mandujs/core/brain/doctor/config-analyzer.ts
- @mandujs/core/brain/doctor/index.ts
- @mandujs/core/brain/doctor/patcher.ts
- @mandujs/core/brain/doctor/reporter.ts
- @mandujs/core/brain/index.ts
- @mandujs/core/brain/memory.ts
- @mandujs/core/brain/permissions.ts
- @mandujs/core/brain/types.ts
- @mandujs/core/bundler/build.test.ts
- @mandujs/core/bundler/build.ts
- @mandujs/core/bundler/css.ts
- @mandujs/core/bundler/dev.ts
- @mandujs/core/bundler/index.ts
- @mandujs/core/bundler/prerender
- @mandujs/core/bundler/prerender.ts
- @mandujs/core/bundler/types.ts
- @mandujs/core/change/history.ts
- @mandujs/core/change/index.ts
- @mandujs/core/change/integrity.ts
- @mandujs/core/change/snapshot.ts
- @mandujs/core/change/transaction.ts
- @mandujs/core/change/types.ts
- @mandujs/core/client
- @mandujs/core/client/Form.tsx
- @mandujs/core/client/Link.tsx
- @mandujs/core/client/__tests__/use-sse.test.ts
- @mandujs/core/client/globals.ts
- @mandujs/core/client/hooks.ts
- @mandujs/core/client/index.ts
- @mandujs/core/client/interaction.tsx
- @mandujs/core/client/island.ts
- @mandujs/core/client/router.ts
- @mandujs/core/client/rpc.ts
- @mandujs/core/client/runtime.ts
- @mandujs/core/client/serialize.ts
- @mandujs/core/client/use-fetch.ts
- @mandujs/core/client/use-head.ts
- @mandujs/core/client/use-sse.ts
- @mandujs/core/client/window-state.ts
- @mandujs/core/components/Image.tsx
- @mandujs/core/config/index.ts
- @mandujs/core/config/mandu.ts
- @mandujs/core/config/mcp-ref.ts
- @mandujs/core/config/mcp-status.ts
- @mandujs/core/config/metadata.test.ts
- @mandujs/core/config/metadata.ts
- @mandujs/core/config/symbols.ts
- @mandujs/core/config/validate.ts
- @mandujs/core/config/watcher.ts
- @mandujs/core/constants.ts
- @mandujs/core/content/content-layer.ts
- @mandujs/core/content/content.test.ts
- @mandujs/core/content/data-store.ts
- @mandujs/core/content/digest.ts
- @mandujs/core/content/index.ts
- @mandujs/core/content/loader-context.ts
- @mandujs/core/content/loaders/api.ts
- @mandujs/core/content/loaders/file.ts
- @mandujs/core/content/loaders/glob.ts
- @mandujs/core/content/loaders/index.ts
- @mandujs/core/content/loaders/types.ts
- @mandujs/core/content/meta-store.ts
- @mandujs/core/content/types.ts
- @mandujs/core/content/watcher.ts
- @mandujs/core/contract/client-safe.test.ts
- @mandujs/core/contract/client-safe.ts
- @mandujs/core/contract/client.test.ts
- @mandujs/core/contract/client.ts
- @mandujs/core/contract/contract.test.ts
- @mandujs/core/contract/define.ts
- @mandujs/core/contract/handler.ts
- @mandujs/core/contract/index.ts
- @mandujs/core/contract/infer.test.ts
- @mandujs/core/contract/integration.test.ts
- @mandujs/core/contract/normalize.test.ts
- @mandujs/core/contract/normalize.ts
- @mandujs/core/contract/protection.ts
- @mandujs/core/contract/registry.test.ts
- @mandujs/core/contract/registry.ts
- @mandujs/core/contract/route-helpers.test.ts
- @mandujs/core/contract/route-helpers.ts
- @mandujs/core/contract/schema.ts
- @mandujs/core/contract/types.ts
- @mandujs/core/contract/validator.ts
- @mandujs/core/contract/zod-utils.ts
- @mandujs/core/devtools/ai/context-builder.ts
- @mandujs/core/devtools/ai/index.ts
- @mandujs/core/devtools/ai/mcp-connector.ts
- @mandujs/core/devtools/client/catchers/error-catcher.ts
- @mandujs/core/devtools/client/catchers/index.ts
- @mandujs/core/devtools/client/catchers/network-proxy.ts
- @mandujs/core/devtools/client/components/index.ts
- @mandujs/core/devtools/client/components/kitchen-root.tsx
- @mandujs/core/devtools/client/components/mandu-character.tsx
- @mandujs/core/devtools/client/components/overlay.tsx
- @mandujs/core/devtools/client/components/panel/diff-viewer.tsx
- @mandujs/core/devtools/client/components/panel/errors-panel.tsx
- @mandujs/core/devtools/client/components/panel/guard-panel.tsx
- @mandujs/core/devtools/client/components/panel/index.ts
- @mandujs/core/devtools/client/components/panel/islands-panel.tsx
- @mandujs/core/devtools/client/components/panel/network-panel.tsx
- @mandujs/core/devtools/client/components/panel/panel-container.tsx
- @mandujs/core/devtools/client/components/panel/preview-panel.tsx
- @mandujs/core/devtools/client/filters/context-filters.ts
- @mandujs/core/devtools/client/filters/index.ts
- @mandujs/core/devtools/client/index.ts
- @mandujs/core/devtools/client/persistence.ts
- @mandujs/core/devtools/client/state-manager.ts
- @mandujs/core/devtools/design-tokens.ts
- @mandujs/core/devtools/hook/create-hook.ts
- @mandujs/core/devtools/hook/index.ts
- @mandujs/core/devtools/index.ts
- @mandujs/core/devtools/init.ts
- @mandujs/core/devtools/protocol.ts
- @mandujs/core/devtools/server/index.ts
- @mandujs/core/devtools/server/source-context.ts
- @mandujs/core/devtools/types.ts
- @mandujs/core/devtools/worker/index.ts
- @mandujs/core/devtools/worker/redaction-worker.ts
- @mandujs/core/devtools/worker/worker-manager.ts
- @mandujs/core/error
- @mandujs/core/error/classifier.ts
- @mandujs/core/error/domains.ts
- @mandujs/core/error/formatter.ts
- @mandujs/core/error/index.ts
- @mandujs/core/error/result.ts
- @mandujs/core/error/stack-analyzer.ts
- @mandujs/core/error/types.ts
- @mandujs/core/errors/extractor.ts
- @mandujs/core/errors/index.ts
- @mandujs/core/filling/auth.ts
- @mandujs/core/filling/context.ts
- @mandujs/core/filling/deps.ts
- @mandujs/core/filling/filling.ts
- @mandujs/core/filling/index.ts
- @mandujs/core/filling/session.ts
- @mandujs/core/filling/sse-catchup.test.ts
- @mandujs/core/filling/sse-catchup.ts
- @mandujs/core/filling/sse.test.ts
- @mandujs/core/filling/sse.ts
- @mandujs/core/filling/ws.ts
- @mandujs/core/generator/contract-glue.test.ts
- @mandujs/core/generator/contract-glue.ts
- @mandujs/core/generator/generate.ts
- @mandujs/core/generator/index.ts
- @mandujs/core/generator/templates.ts
- @mandujs/core/guard/analyzer.ts
- @mandujs/core/guard/ast-analyzer.ts
- @mandujs/core/guard/auto-correct.ts
- @mandujs/core/guard/check.ts
- @mandujs/core/guard/config-guard.ts
- @mandujs/core/guard/contract-guard.test.ts
- @mandujs/core/guard/contract-guard.ts
- @mandujs/core/guard/decision-memory.test.ts
- @mandujs/core/guard/decision-memory.ts
- @mandujs/core/guard/file-type.test.ts
- @mandujs/core/guard/healing.test.ts
- @mandujs/core/guard/healing.ts
- @mandujs/core/guard/index.ts
- @mandujs/core/guard/negotiation.test.ts
- @mandujs/core/guard/negotiation.ts
- @mandujs/core/guard/presets/atomic.ts
- @mandujs/core/guard/presets/clean.ts
- @mandujs/core/guard/presets/cqrs.test.ts
- @mandujs/core/guard/presets/cqrs.ts
- @mandujs/core/guard/presets/fsd.ts
- @mandujs/core/guard/presets/hexagonal.ts
- @mandujs/core/guard/presets/index.ts
- @mandujs/core/guard/reporter.ts
- @mandujs/core/guard/rules.ts
- @mandujs/core/guard/semantic-slots.test.ts
- @mandujs/core/guard/semantic-slots.ts
- @mandujs/core/guard/statistics.ts
- @mandujs/core/guard/suggestions.ts
- @mandujs/core/guard/types.ts
- @mandujs/core/guard/validator.ts
- @mandujs/core/guard/watcher.ts
- @mandujs/core/index.ts
- @mandujs/core/intent/index.ts
- @mandujs/core/island/index.ts
- @mandujs/core/kitchen/api/contract-api.ts
- @mandujs/core/kitchen/api/diff-parser.ts
- @mandujs/core/kitchen/api/file-api.ts
- @mandujs/core/kitchen/api/guard-api.ts
- @mandujs/core/kitchen/api/guard-decisions.ts
- @mandujs/core/kitchen/api/routes-api.ts
- @mandujs/core/kitchen/index.ts
- @mandujs/core/kitchen/kitchen-handler.ts
- @mandujs/core/kitchen/kitchen-ui.ts
- @mandujs/core/kitchen/stream/activity-sse.ts
- @mandujs/core/kitchen/stream/file-tailer.ts
- @mandujs/core/lockfile/generate.ts
- @mandujs/core/lockfile/index.ts
- @mandujs/core/lockfile/lockfile.test.ts
- @mandujs/core/lockfile/types.ts
- @mandujs/core/lockfile/validate.ts
- @mandujs/core/logging/index.ts
- @mandujs/core/logging/transports.ts
- @mandujs/core/middleware
- @mandujs/core/middleware/compress.ts
- @mandujs/core/middleware/cors.ts
- @mandujs/core/middleware/index.ts
- @mandujs/core/middleware/jwt.ts
- @mandujs/core/middleware/logger.ts
- @mandujs/core/middleware/timeout.ts
- @mandujs/core/observability/event-bus.ts
- @mandujs/core/observability/index.ts
- @mandujs/core/observability/logger-adapter.ts
- @mandujs/core/openapi/generator.ts
- @mandujs/core/openapi/index.ts
- @mandujs/core/openapi/openapi.test.ts
- @mandujs/core/paths.test.ts
- @mandujs/core/paths.ts
- @mandujs/core/plugins
- @mandujs/core/plugins/hooks.ts
- @mandujs/core/plugins/index.ts
- @mandujs/core/plugins/registry.ts
- @mandujs/core/plugins/types.ts
- @mandujs/core/report/build.ts
- @mandujs/core/report/index.ts
- @mandujs/core/resource/__tests__/backward-compat.test.ts
- @mandujs/core/resource/__tests__/edge-cases.test.ts
- @mandujs/core/resource/__tests__/fixtures.ts
- @mandujs/core/resource/__tests__/generator.test.ts
- @mandujs/core/resource/__tests__/performance.test.ts
- @mandujs/core/resource/__tests__/schema.test.ts
- @mandujs/core/resource/generator.ts
- @mandujs/core/resource/generators/client.ts
- @mandujs/core/resource/generators/contract.ts
- @mandujs/core/resource/generators/slot.ts
- @mandujs/core/resource/generators/types.ts
- @mandujs/core/resource/index.ts
- @mandujs/core/resource/parser.ts
- @mandujs/core/resource/schema.ts
- @mandujs/core/router/fs-patterns.ts
- @mandujs/core/router/fs-routes.ts
- @mandujs/core/router/fs-scanner.ts
- @mandujs/core/router/fs-types.ts
- @mandujs/core/router/index.ts
- @mandujs/core/runtime/adapter-bun.ts
- @mandujs/core/runtime/adapter.ts
- @mandujs/core/runtime/boundary.tsx
- @mandujs/core/runtime/cache.ts
- @mandujs/core/runtime/compose.ts
- @mandujs/core/runtime/cors.ts
- @mandujs/core/runtime/env.ts
- @mandujs/core/runtime/escape.ts
- @mandujs/core/runtime/handler.ts
- @mandujs/core/runtime/image-handler.ts
- @mandujs/core/runtime/index.ts
- @mandujs/core/runtime/lifecycle.ts
- @mandujs/core/runtime/logger.test.ts
- @mandujs/core/runtime/logger.ts
- @mandujs/core/runtime/middleware.ts
- @mandujs/core/runtime/ppr.ts
- @mandujs/core/runtime/react-renderer.ts
- @mandujs/core/runtime/router.test.ts
- @mandujs/core/runtime/router.ts
- @mandujs/core/runtime/security.ts
- @mandujs/core/runtime/server.ts
- @mandujs/core/runtime/session-key.ts
- @mandujs/core/runtime/shims.ts
- @mandujs/core/runtime/ssr.ts
- @mandujs/core/runtime/stable-selector.ts
- @mandujs/core/runtime/streaming-ssr.ts
- @mandujs/core/runtime/trace.ts
- @mandujs/core/seo/index.ts
- @mandujs/core/seo/integration/ssr.ts
- @mandujs/core/seo/render/basic.ts
- @mandujs/core/seo/render/index.ts
- @mandujs/core/seo/render/jsonld.ts
- @mandujs/core/seo/render/opengraph.ts
- @mandujs/core/seo/render/robots.ts
- @mandujs/core/seo/render/sitemap.ts
- @mandujs/core/seo/render/twitter.ts
- @mandujs/core/seo/resolve/index.ts
- @mandujs/core/seo/resolve/opengraph.ts
- @mandujs/core/seo/resolve/robots.ts
- @mandujs/core/seo/resolve/title.ts
- @mandujs/core/seo/resolve/twitter.ts
- @mandujs/core/seo/resolve/url.ts
- @mandujs/core/seo/routes/index.ts
- @mandujs/core/seo/types.ts
- @mandujs/core/slot/corrector.ts
- @mandujs/core/slot/index.ts
- @mandujs/core/slot/validator.test.ts
- @mandujs/core/slot/validator.ts
- @mandujs/core/spec/index.ts
- @mandujs/core/spec/load.ts
- @mandujs/core/spec/schema.ts
- @mandujs/core/testing
- @mandujs/core/testing/index.ts
- @mandujs/core/types/branded.ts
- @mandujs/core/types/index.ts
- @mandujs/core/utils/bun.ts
- @mandujs/core/utils/differ.test.ts
- @mandujs/core/utils/differ.ts
- @mandujs/core/utils/hasher.test.ts
- @mandujs/core/utils/hasher.ts
- @mandujs/core/utils/index.ts
- @mandujs/core/utils/lru-cache.ts
- @mandujs/core/utils/safe-io.ts
- @mandujs/core/utils/string-safe.ts
- @mandujs/core/watcher/index.ts
- @mandujs/core/watcher/reporter.ts
- @mandujs/core/watcher/rules.ts
- @mandujs/core/watcher/watcher.ts
Readme
@mandujs/core
Mandu Framework Core
Runtime, FS Routes, Guard, Bundler, Contract, Filling
English | 한국어
Installation
bun add @mandujs/coreTypically used through
@mandujs/cli. Direct usage is for advanced use cases.
Quick Start
Basic API Handler (Filling)
import { Mandu } from "@mandujs/core";
export default Mandu.filling()
.guard((ctx) => {
if (!ctx.get("user")) return ctx.unauthorized("Login required");
})
.get(async (ctx) => {
const users = await db.users.findMany();
return ctx.ok({ data: users });
})
.post(async (ctx) => {
const body = await ctx.body<{ name: string }>();
const user = await db.users.create({ data: body });
return ctx.created({ data: user });
});Type-Safe Contract
import { Mandu } from "@mandujs/core";
import { z } from "zod";
const userContract = Mandu.contract({
request: {
GET: { query: z.object({ id: z.string() }) },
POST: { body: z.object({ name: z.string() }) }
},
response: {
200: z.object({ data: z.any() }),
400: z.object({ error: z.string() })
}
});
const handlers = Mandu.handler(userContract, {
GET: (ctx) => ({ data: fetchUser(ctx.query.id) }),
POST: (ctx) => ({ data: createUser(ctx.body) })
});Module Overview
@mandujs/core
├── router/ # FS Routes - file-system based routing
├── guard/ # Mandu Guard - architecture enforcement
│ ├── healing # Self-Healing Guard with auto-fix
│ ├── decision-memory # ADR storage (RFC-001)
│ ├── semantic-slots # Constraint validation (RFC-001)
│ └── negotiation # AI-Framework dialog (RFC-001)
├── runtime/ # Server, SSR, streaming
├── filling/ # Handler chain API (Mandu.filling())
├── contract/ # Type-safe API contracts
├── content/ # Content Layer - build-time content loading 🆕
│ └── loaders # file(), glob(), api() loaders
├── bundler/ # Client bundling, HMR
├── client/ # Island hydration, client router
├── brain/ # Doctor, Watcher, Architecture analyzer
├── change/ # Transaction & history
└── spec/ # Manifest schema & validationFS Routes
File-system based routing system.
import { scanRoutes, generateManifest, watchFSRoutes } from "@mandujs/core/router";
// Scan routes from app/ directory
const result = await scanRoutes("/path/to/project");
console.log(result.routes);
// Generate manifest
const { manifest } = await generateManifest("/path/to/project", {
outputPath: ".mandu/manifest.json"
});
// Watch for changes
const watcher = await watchFSRoutes("/path/to/project", {
onChange: (result) => console.log("Routes updated!", result.routes.length)
});Route Patterns
import { pathToPattern, parseSegments } from "@mandujs/core/router";
// Convert path to URL pattern
pathToPattern("users/[id]/posts"); // → "/users/:id/posts"
pathToPattern("docs/[...slug]"); // → "/docs/:slug*"
pathToPattern("(auth)/login"); // → "/login" (group ignored)
// Parse segments
parseSegments("[id]"); // → [{ type: "dynamic", name: "id" }]
parseSegments("[...slug]"); // → [{ type: "catch-all", name: "slug" }]Mandu Guard
Real-time architecture enforcement with preset support.
import {
createGuardWatcher,
checkDirectory,
getPreset,
listPresets
} from "@mandujs/core/guard";
// One-time check
const report = await checkDirectory(
{ preset: "mandu" },
process.cwd()
);
console.log(`Violations: ${report.totalViolations}`);
// Real-time watching
const watcher = createGuardWatcher({
config: { preset: "mandu", srcDir: "src" },
rootDir: process.cwd(),
onViolation: (v) => console.log(`${v.filePath}: ${v.ruleDescription}`),
});
watcher.start();
// List available presets
listPresets().forEach(p => console.log(p.name, p.description));Presets
| Preset | Layers | Use Case |
|---|---|---|
mandu |
client/, shared/(contracts, types, utils/, schema, env), server/* | Fullstack (default) |
fsd |
app, pages, widgets, features, entities, shared | Frontend |
clean |
api, application, domain, infra, shared | Backend |
hexagonal |
adapters, ports, application, domain | DDD |
atomic |
pages, templates, organisms, molecules, atoms | UI |
AST-based Analysis
import { extractImportsAST, analyzeModuleAST } from "@mandujs/core/guard";
// Extract imports with AST (more accurate than regex)
const imports = extractImportsAST(code);
// → [{ path: "./utils", type: "static", line: 1, namedImports: ["foo"] }]
// Full module analysis
const analysis = analyzeModuleAST(code, "src/features/user/api.ts");Statistics & Trends
import {
createScanRecord,
addScanRecord,
analyzeTrend,
generateGuardMarkdownReport
} from "@mandujs/core/guard";
// Save scan for trend analysis
const record = createScanRecord(report, "mandu");
await addScanRecord(rootDir, record);
// Analyze improvement trend
const trend = analyzeTrend(records, 7); // 7 days
console.log(trend.trend); // "improving" | "stable" | "degrading"
// Generate reports
const markdown = generateGuardMarkdownReport(report, trend);Self-Healing Guard (RFC-001) 🆕
import { checkWithHealing, healAll, explainRule } from "@mandujs/core/guard";
// Detect violations with fix suggestions
const result = await checkWithHealing({ preset: "mandu" }, process.cwd());
// Auto-fix all fixable violations
if (result.items.length > 0) {
const healResult = await healAll(result);
console.log(`Fixed: ${healResult.fixed}, Failed: ${healResult.failed}`);
}
// Explain any rule
const explanation = explainRule("layer-dependency");
console.log(explanation.description, explanation.examples);Decision Memory (RFC-001) 🆕
import {
searchDecisions,
saveDecision,
checkConsistency,
getCompactArchitecture
} from "@mandujs/core/guard";
// Search past decisions
const results = await searchDecisions(rootDir, ["auth", "jwt"]);
// Save new decision (ADR)
await saveDecision(rootDir, {
id: "ADR-002",
title: "Use PostgreSQL",
status: "accepted",
context: "Need relational database",
decision: "Use PostgreSQL with Drizzle ORM",
consequences: ["Need to manage migrations"],
tags: ["database", "orm"]
});
// Check implementation consistency
const consistency = await checkConsistency(rootDir);Architecture Negotiation (RFC-001) 🆕
import { negotiate, generateScaffold } from "@mandujs/core/guard";
// AI negotiates with framework before implementation
const plan = await negotiate({
intent: "Add user authentication",
requirements: ["JWT based", "Refresh tokens"],
constraints: ["Use existing User model"]
}, projectRoot);
if (plan.approved) {
// Generate scaffold files
await generateScaffold(plan.structure, projectRoot);
}Filling API
Handler chain for business logic.
import { Mandu } from "@mandujs/core";
export default Mandu.filling()
// Lifecycle hooks
.onRequest((ctx) => {
ctx.set("requestId", crypto.randomUUID());
})
// Guard (return Response to block)
.guard((ctx) => {
if (!ctx.get("user")) return ctx.unauthorized("Login required");
})
// Handlers
.get(async (ctx) => {
return ctx.ok({ users: await fetchUsers() });
})
.post(async (ctx) => {
const body = await ctx.body();
return ctx.created({ user: await createUser(body) });
})
// After response
.afterResponse((ctx) => {
console.log("Request completed:", ctx.get("requestId"));
});Middleware (Compose-style)
export default Mandu.filling()
.middleware(async (ctx, next) => {
console.log("before");
await next();
console.log("after");
})
.get((ctx) => ctx.ok({ ok: true }));Context API
| Method | Description |
|---|---|
ctx.ok(data) |
200 OK |
ctx.created(data) |
201 Created |
ctx.noContent() |
204 No Content |
ctx.error(message) |
400 Bad Request |
ctx.unauthorized(message) |
401 Unauthorized |
ctx.forbidden(message) |
403 Forbidden |
ctx.notFound(message) |
404 Not Found |
ctx.fail(message) |
500 Internal Server Error |
ctx.body<T>() |
Parse request body |
ctx.params |
Route parameters |
ctx.query |
Query parameters |
ctx.set(key, value) |
Store in context |
ctx.get<T>(key) |
Retrieve from context |
Contract API
Type-safe API contracts with Zod.
import { Mandu } from "@mandujs/core";
import { z } from "zod";
// Define contract
const userContract = Mandu.contract({
request: {
GET: { query: z.object({ id: z.string() }) },
POST: { body: z.object({ name: z.string() }) }
},
response: {
200: z.object({ data: z.any() }),
400: z.object({ error: z.string() })
}
});
// Create typed handlers
const handlers = Mandu.handler(userContract, {
GET: (ctx) => ({ data: fetchUser(ctx.query.id) }),
POST: (ctx) => ({ data: createUser(ctx.body) })
});
// Type-safe client
const client = Mandu.client(userContract, { baseUrl: "/api/users" });
const result = await client.GET({ query: { id: "123" } });Client-safe Contract
Limit schemas exposed to client-side usage (forms/UI validation):
const clientContract = Mandu.clientContract(userContract, {
request: {
POST: { body: true },
},
response: [201],
includeErrors: true,
});
const client = Mandu.client(clientContract, { baseUrl: "/api/users" });Runtime
Server and SSR.
import { startServer, registerApiHandler, registerPageLoader } from "@mandujs/core";
// Register handlers
registerApiHandler("getUsers", async (req) => ({ users: [] }));
registerPageLoader("home", () => import("./pages/Home"));
// Start server
const server = startServer(manifest, { port: 3000 });Streaming SSR
import { renderToStream } from "@mandujs/core";
const stream = await renderToStream(<App />, {
bootstrapScripts: ["/client.js"],
onError: (err) => console.error(err)
});Client (Islands & Router)
Island Hydration
import { createIsland, partial } from "@mandujs/core/client";
// Define island
const CounterIsland = createIsland({
name: "counter",
component: Counter,
priority: "visible"
});
// Partial (smaller than island)
const ButtonPartial = partial("submit-btn", SubmitButton);Client Router
import { useRouter, useParams, Link, NavLink } from "@mandujs/core/client";
function Navigation() {
const router = useRouter();
const params = useParams();
return (
<nav>
<NavLink href="/users" activeClass="active">Users</NavLink>
<button onClick={() => router.push("/settings")}>Settings</button>
</nav>
);
}Content Layer 🆕
Astro-inspired build-time content loading system.
// content.config.ts
import { defineContentConfig, glob, file, api } from "@mandujs/core/content";
import { z } from "zod";
const postSchema = z.object({
title: z.string(),
date: z.coerce.date(),
tags: z.array(z.string()).default([]),
});
export default defineContentConfig({
collections: {
// Markdown files with frontmatter
posts: {
loader: glob({ pattern: "content/posts/**/*.md" }),
schema: postSchema,
},
// Single JSON/YAML file
settings: {
loader: file({ path: "data/settings.json" }),
},
// External API
products: {
loader: api({
url: "https://api.example.com/products",
headers: () => ({ Authorization: `Bearer ${process.env.API_KEY}` }),
cacheTTL: 3600,
}),
},
},
});Querying Content
import { getCollection, getEntry } from "@mandujs/core/content";
// Get all entries
const posts = await getCollection("posts");
posts.forEach(post => {
console.log(post.id, post.data.title);
});
// Get single entry
const post = await getEntry("posts", "hello-world");
console.log(post?.data.title, post?.body);Built-in Loaders
| Loader | Description | Example |
|---|---|---|
file() |
Single file (JSON, YAML, TOML) | file({ path: "data/config.json" }) |
glob() |
Pattern matching (Markdown, JSON) | glob({ pattern: "content/**/*.md" }) |
api() |
HTTP API with caching | api({ url: "https://...", cacheTTL: 3600 }) |
Features
- Digest-based caching: Only re-parse changed files
- Zod validation: Type-safe content with schema validation
- Frontmatter support: YAML frontmatter in Markdown files
- Dev mode watching: Auto-reload on content changes
- Incremental updates: Efficient builds with change detection
Brain (AI Assistant)
Doctor and architecture analyzer.
import {
initializeBrain,
getBrain,
analyzeViolations,
initializeArchitectureAnalyzer
} from "@mandujs/core";
// Initialize
await initializeBrain();
const brain = getBrain();
// Analyze violations with suggestions
const analysis = await analyzeViolations(violations, { useLLM: true });
console.log(analysis.patches); // Suggested fixes
// Architecture analyzer
const analyzer = initializeArchitectureAnalyzer(rootDir);
const locationResult = await analyzer.checkLocation({ path: "src/features/user.ts" });
const importResult = await analyzer.checkImports({
sourceFile: "src/features/user.ts",
imports: ["../entities/product"]
});Bundler
Client bundling with HMR.
import { buildClientBundle, createDevBundler } from "@mandujs/core/bundler";
// Production build
const result = await buildClientBundle(manifest, {
outDir: ".mandu/client",
minify: true,
sourcemap: true
});
// Development with HMR
const devBundler = await createDevBundler(manifest, {
rootDir: process.cwd(),
isDev: true
});Transaction API
Atomic changes with rollback.
import { beginChange, commitChange, rollbackChange } from "@mandujs/core";
// Start transaction
const { changeId, snapshotId } = await beginChange(rootDir, "Add user API");
// Make changes...
// Commit or rollback
await commitChange(rootDir);
// or
await rollbackChange(rootDir);Types
import type {
// Spec
RoutesManifest,
RouteSpec,
// Guard
GuardPreset,
GuardConfig,
Violation,
ViolationReport,
// Router
ScanResult,
FSRouteConfig,
// Contract
ContractDefinition,
ContractHandlers,
// Filling
ManduContext,
// Content Layer
DataEntry,
ContentConfig,
CollectionConfig,
Loader,
LoaderContext,
} from "@mandujs/core";Requirements
- Bun >= 1.0.0
- React >= 19.0.0
- Zod >= 3.0.0
Related Packages
- @mandujs/cli - CLI tool
- @mandujs/mcp - MCP server for AI agents
License
MIT