Getting started
CLI and registry
How widgets land in your project, and why they are copied rather than installed.
Heavyweight widgets are not installed as a package — they are copied into your project's code with a single command, and from then on they live as ordinary files of yours.
Why by copying
A board or a chart almost always needs edits for a particular domain: a different card body, different permissions, a different set of actions. A component you cannot open and edit grows props instead — renderCardHeader, hideAssignees, cardClassName — and six months later its API is larger than the component itself.
init
npx @toimetdev/pathlogs-ui initThe command creates the config and the widget directory, and appends the style imports:
Setting up PathLogs UI
widget directory src/components/ui
import alias @/components/ui
stylesheet src/app/globals.css
Tailwind yes
+ pathlogs.json
+ src/components/ui/
~ src/app/globals.css (style imports added)The imports are inserted after @import "tailwindcss" if it is present: order matters in CSS. Running it again duplicates nothing. If there is no stylesheet, the command does not invent a structure it knows nothing about — it simply prints what to paste.
add
npx @toimetdev/pathlogs-ui add kanban
npx @toimetdev/pathlogs-ui add gantt filter-bar
npx @toimetdev/pathlogs-ui add kanban --dry-runFiles are copied into the directory from your config, and the imports between them are rewritten to use your alias:
// in the registry
import { columnItems } from "./kanbanOrder";
// in your project
import { columnItems } from "@/components/ui/kanban/kanbanOrder";At the end the command prints which packages the widget needs — that list is baked into its metadata rather than guessed.
list
npx @toimetdev/pathlogs-ui listShows everything the registry contains, with a description of each widget.
pathlogs.json
{
"componentsDir": "src/components/ui",
"alias": "@/components/ui",
"css": "src/app/globals.css",
"tailwind": true
}| Prop | Type | Default | Description |
|---|---|---|---|
componentsDir | string | "src/components/ui" | Where to put widgets, relative to the project root. |
alias | string | "@/components/ui" | The alias widgets use to import one another. An empty string keeps relative paths. |
css | string | "src/app/globals.css" | The file init appends the style imports to. |
tailwind | boolean | true | Whether the project uses Tailwind. If not, add warns that widgets will arrive unstyled. |
componentsDirstringdefaults to: "src/components/ui"
Where to put widgets, relative to the project root.
aliasstringdefaults to: "@/components/ui"
The alias widgets use to import one another. An empty string keeps relative paths.
cssstringdefaults to: "src/app/globals.css"
The file init appends the style imports to.
tailwindbooleandefaults to: true
Whether the project uses Tailwind. If not, add warns that widgets will arrive unstyled.
The values can be set during setup: init --dir src/ui --alias @/ui --no-tailwind.
Updating
There is no in-place update for widgets, and that is deliberate: the file in your project may already differ from the original, and automatically merging someone else's edits is a source of quiet breakage.
If you do want to pull in a newer version:
# see what would change
npx @toimetdev/pathlogs-ui add kanban --dry-run
# overwrite and sort the conflicts out in git
npx @toimetdev/pathlogs-ui add kanban --force
git diffThis is why widgets are worth committing right after copying — then git diff shows exactly your edits on top of the original.
Your own widget
The registry is just a directory of files plus a description. To add your own:
{
"name": "my-widget",
"title": "My widget",
"description": "What it does and why it is useful",
"type": "widget",
"dependencies": ["@xyflow/react"],
"registryDependencies": ["filter-bar"],
"packageDependencies": ["@toimetdev/pathlogs-core"],
"tailwind": true,
"files": [
{ "path": "MyWidget.tsx", "target": "my-widget/MyWidget.tsx" }
]
}dependencies— third-party npm packages;registryDependencies— other registry widgets, installed first;packageDependencies— packages of the framework itself.
The CLI expands dependencies in installation order and prints a single npm install command for everything that is missing.