LikeC4 Workspace and Navigation Research
Date: 2026-08-04
Question
Can criv split one LikeC4 architecture workspace into many files and folders, and can users navigate between its focused views?
Answer
Yes. Keep one LikeC4 project at docs/architecture/. Split its model and views
into as many .c4 files and folders as needed. LikeC4 merges the files into one
model. Use named scoped views and explicit navigateTo rules for drill-down.
Criv must also connect LikeC4’s onNavigateTo event to its selected view. The
current criv renderer does not do this. Moving files will make each opened file
more useful, but moving files alone will not enable diagram navigation.
This research applies to LikeC4 1.59.2, which criv pins. The reviewed official
source is commit
67b696e77ef8f97f43e435819a019ff8cc637cec.
One project can use many files
A likec4.config.json file makes its folder a project root. LikeC4 includes
.c4 files in that folder and its subfolders. See the official
project configuration documentation, the
workspace scanner,
and the
file-system filter.
All source files in one project are merged into one architecture model. An element can be declared in one file and extended in another file. This is the intended way to keep one large model in small files. See Extending model.
Files in the same project do not need import statements. The import keyword
is for separate LikeC4 projects. A nested likec4.config.json starts a separate
project, and its files stop being part of the parent project. Cross-project
imports currently support only top-level elements. Therefore, criv must not use
nested projects only to organize C4 levels. See
Multi-projects.
Criv already gives the complete docs/architecture/ path to
LikeC4.fromWorkspace, so a recursive file split fits the current compiler
bridge. See
assets/likec4-bridge.mjs and
src/c4/likec4.rs.
Source folders and view folders are different
Physical folders organize .c4 source. The official LikeC4 site can also group
its diagram tree by source file or source folder because every view has a
sourcePath. See the official
diagram tree implementation.
The portable DSL feature for navigation folders is the view title. A / in a
title creates a folder path. A views 'Folder name' block supplies a common
folder for all views in the block. See
Organize views.
For example:
views 'CLI' {
view cliComponents of criv.cli {
title 'Components'
include *
}
}
The source folder and the title folder should agree. This gives useful organization in both the official LikeC4 tools and criv hosts.
Navigation between views
All navigation targets must be named views. A named view has a stable identifier that LikeC4 can reference and use in a URL. See Views.
Automatic drill-down with scoped views
A view declared as view <id> of <element> becomes a scoped view for that
element. When another view shows the element, LikeC4 can navigate to its default
scoped view. If an element has more than one scoped view, their source order
selects the default. See the official
scoped-view documentation and
assignNavigateTo.
This is a good fit for the main C4 drill-down path:
System Context -> Containers -> Components
The containers view should be of criv. Each Component view should be of
its container. A click on criv, criv.cli, criv.vscodeExtension, or
criv.obsidianPlugin can then open the next level.
Explicit navigation
A view can override an element’s target:
include criv.cli.refreshPipeline with {
navigateTo codeRefreshPipeline
}
This is useful when one component has many Code views, or when the desired view is not its first scoped view. See custom view navigation.
A model relationship can navigate to a dynamic view. A relationship included
in one view can also get a view-specific navigateTo target. See
relationship navigation
and
relationship customization.
Dynamic-view steps can navigate to other dynamic views. This supports a high-level scenario followed by a detailed scenario. See Dynamic view navigation.
Dynamic views are not required for the normal C4 level path. Scoped element views are the simpler mechanism for Context, Container, Component, and Code drill-down.
What the renderer must do
LikeC4 computes navigateTo targets in the layout model, but embedded hosts must
handle the navigation event. ReactLikeC4 accepts onNavigateTo. LikeC4 enables
node and relationship navigation only when this callback exists. It also enables
history buttons only when both showNavigationButtons and onNavigateTo are
active. See the official
LikeC4Diagram implementation
and its
feature setup.
The official VS Code extension sends navigation from the webview to the host. The host updates the current view and sends that view back to the webview. See the official VS Code preview and panel state update.
Criv uses ReactLikeC4, but it passes no onNavigateTo callback. It passes a
browser property through an unsafe type cast, but browser belongs to
LikeC4View, not ReactLikeC4. Thus, this property does not provide navigation.
See
packages/criv-likec4/src/renderer.ts
and the official
ReactLikeC4 properties.
The shared criv renderer needs these changes:
- Pass
onNavigateTotoReactLikeC4. - Select the requested view and render it.
- Enable LikeC4 navigation buttons.
- Notify the host when the selected view changes, so the host view selector stays correct.
- Keep the current source-link action separate from drill-down navigation.
The VS Code host already selects a view from the opened file’s sourcePath.
This makes one view per source file the safest initial layout. See
previewModel.ts.
The Obsidian adapter currently opens the first view in the model and does not
select by the opened file’s sourcePath. It must supply the file-owned view when
the workspace is split. See
main.ts.
Recommended file layout
Keep one project and use one primary view per view file:
docs/architecture/
specification.c4
model/
landscape.c4
cli.c4
vscode.c4
obsidian.c4
relationships.c4
views/
overview/
system-context.c4
containers.c4
components/
cli.c4
vscode.c4
obsidian.c4
code/
cli-vault-loading.c4
cli-refresh-pipeline.c4
cli-architecture-exporter.c4
cli-state-publication.c4
vscode-preview.c4
obsidian-adapter.c4
shared-likec4-renderer.c4
Use these title folders:
Overview / System contextOverview / ContainersComponents / CLIComponents / VS CodeComponents / ObsidianCode / CLI / Vault loadingCode / CLI / Refresh pipelineCode / CLI / Architecture exporterCode / CLI / State publicationCode / VS Code / PreviewCode / Obsidian / AdapterCode / Shared / LikeC4 renderer
Recommended implementation order
- Split the current
.c4source into the single-project folder structure. - Put one primary named view in each view file.
- Make the Container and Component views scoped.
- Add explicit Component-to-Code navigation where one target is clear.
- Add
onNavigateTosupport to the shared renderer. - Keep the VS Code and Obsidian selectors synchronized with renderer navigation.
- Select Obsidian’s initial view by the opened file’s
sourcePath. - Validate the complete workspace with
criv watch --onceandcriv check.
Conclusion
The split is supported and is the correct design. Use one LikeC4 project, many
small source files, one primary view per view file, scoped views for C4
drill-down, and explicit navigateTo rules for Component-to-Code links. Do not
use nested LikeC4 projects for this purpose.
The split and renderer navigation belong in the same change. Without the renderer callback, the new view links will exist in the model but will not work in criv’s VS Code or Obsidian previews.