Aller au contenu principal

1. Scaffold the site and add LikeC4

This guide reproduces the site you are reading: a Docusaurus site that renders LikeC4 architecture diagrams, FINOS CALM models, and Slidev decks, deployed to GitHub Pages.

:::info Versions Written against Docusaurus 3.10, React 19, LikeC4 1.59, CALM CLI 1.59, and Slidev 52. Newer versions may differ — the APIs below are what these versions actually expose. :::

Scaffold Docusaurus​

npx create-docusaurus@latest workspaces/docusaurus classic --typescript
cd workspaces/docusaurus
npm start

This gives you the classic template (blog + docs + homepage) in TypeScript.

Add LikeC4​

Install the diagram runtime and the CLI (for code generation):

npm install @likec4/core @likec4/diagram
npm install --save-dev likec4

Create a model at likec4/model.c4:

specification {
element actor { style { shape person } }
element system
element component
element database { style { shape cylinder } }
}

model {
customer = actor 'Customer'
website = system 'Website' {
// Built-in icon; rendered by the renderIcon function below.
style { icon tech:docusaurus }
ui = component 'Web UI'
api = component 'Content API'
store = database 'Content Store'
ui -> api 'requests content'
api -> store 'reads/writes'
}
customer -> website.ui 'browses'
}

views {
view index {
title 'System Context'
include *
}
// Give views an explicit id (view <id> of <element>), otherwise LikeC4
// auto-generates ids like `view_xxxxx` that are awkward to reference.
view website of website {
title 'Website — Containers'
include website, website.*, customer
autoLayout LeftRight
}
}

Generate the model​

LikeC4 compiles the DSL into a TypeScript model your components import. Add a script to package.json:

{
"scripts": {
"likec4:codegen": "likec4 codegen model ./likec4 --use-core-package --outfile ./src/likec4/likec4-model.ts"
}
}

Run npm run likec4:codegen to produce src/likec4/likec4-model.ts.

The React component​

Diagrams use browser APIs, so render them client-side only with <BrowserOnly>. Two gotchas that cost real time:

  • The model is passed to LikeC4ModelProvider via the likec4model prop (not model).
  • Import from @likec4/diagram (the /bundle entry the online docs mention does not exist in 1.59), and import styles yourself (next step).

Create src/components/LikeC4/index.tsx:

import React from 'react';
import BrowserOnly from '@docusaurus/BrowserOnly';

export default function LikeC4({
viewId,
height = 480,
}: {
viewId: string;
height?: number | string;
}) {
return (
<BrowserOnly fallback={<div style={{ height }} />}>
{() => {
const { LikeC4ModelProvider, ReactLikeC4 } = require('@likec4/diagram');
const { likec4model } = require('@site/src/likec4/likec4-model');

// Import only the single icon you use. Importing the whole
// @likec4/icons bundle crashes the production bundler.
const DocusaurusIcon = require('@likec4/icons/tech/docusaurus').default;
const renderIcon = ({ node }: { node: { icon?: string | null } }) =>
node.icon === 'tech:docusaurus' ? <DocusaurusIcon /> : null;

return (
<div style={{ height, width: '100%' }}>
<LikeC4ModelProvider likec4model={likec4model}>
<ReactLikeC4
viewId={viewId}
pannable
zoomable
renderIcon={renderIcon}
/>
</LikeC4ModelProvider>
</div>
);
}}
</BrowserOnly>
);
}

Diagram styles​

@likec4/diagram uses Mantine. Add the styles (with the correct CSS layer order) to src/css/custom.css:

@layer reset, base, mantine, xyflow, tokens, recipes, utilities;
@import '@mantine/core/styles.layer.css';
@import '@likec4/diagram/styles.css';
@import '@likec4/diagram/styles-font.css';

Use it in a page​

import LikeC4 from '@site/src/components/LikeC4';

<LikeC4 viewId="index" />
<LikeC4 viewId="website" />