7.4 KiB
CODEBUDDY.md
This file provides guidance to CodeBuddy Code when working with code in this repository.
Overview
G3Soft frontend infrastructure — a pnpm monorepo holding a self-built Vue 3 component library plus a Docus documentation site.
packages/ui(@g3soft/ui) — component library, published to a private npm registry. One directory per component undersrc/<name>/.packages/tokens(@g3soft/tokens) — design tokens as plain CSS (--g3-*variables), shared by the library and the docs site.docs(@g3soft/docs) — Docus/Nuxt docs site.private: true, never published.scripts/gen-api.mjs— generates component API data from source.
Requires Node >= 20.19 and pnpm 11 (see packageManager in root package.json).
Commands
pnpm install
pnpm dev # start docs site (http://localhost:3000); live-reloads packages/ui via alias
pnpm build # build all packages under packages/** (component lib -> dist)
pnpm build:docs # build docs static site -> docs/.output/public
pnpm preview:docs # preview the built docs site
pnpm gen:api # regenerate docs/data/api/*.json from component source (REQUIRED after changing props/events/slots)
Deploying docs to a subpath:
NUXT_APP_BASE_URL=/docs/ pnpm build:docs
Releasing the component library (changesets):
pnpm changeset # record the change
pnpm version # bump versions + generate CHANGELOG
pnpm release # build + publish to the private registry
packages/ui runs publint via prepublishOnly to validate package structure (exports/files consistency).
Testing: there is no test runner configured in this repo (no vitest/jest, no test files). Do not assume pnpm test exists.
Running a single component's checks
There is no per-component test/lint script. The closest equivalent is pnpm --filter @g3soft/ui build (runs vite build, which type-checks declarations via vite-plugin-dts), and pnpm gen:api to verify the docgen extraction still parses a component.
Architecture
Two independent pipelines
The docs site and the component library are deliberately decoupled:
| Docs site | Component package | |
|---|---|---|
| Published | No (private: true) |
Yes (private npm registry) |
| Versioning | None | changesets (ignore: ["@g3soft/docs"]) |
| Build | pnpm build:docs |
pnpm build |
| Output | docs/.output/public (static) |
packages/ui/dist (ESM + d.ts) |
| Dep boundary | Docus/Nuxt/Tailwind live only in the docs package |
only vue (peer) + @g3soft/tokens |
Nuxt-related deps appear only in docs/package.json; the library's dependency tree has none of it. changesets' ignore keeps the docs site out of version tags.
Component library build (packages/ui)
vite.config.ts builds ESM + type declarations. Critical points:
vueis markedexternal— never bundle Vue, or consumers get duplicate instances.preserveModuleskeeps thesrcstructure so consumers can tree-shake.vite-plugin-dtswithrollupTypesemits a singledist/index.d.ts, matched byexports.types.src/index.tsis the public entry: it re-exports every component plus its types, and exports the optionalG3UIinstall plugin for whole-library registration.
Docs site (docs)
extends: ['docus']— all navigation/search/theme comes from the Docus Nuxt Layer.vite.resolve.aliaspoints@g3soft/uiand@g3soft/tokensdirectly atpackages/*/src, so the docs site can develop against the library without building it. Editingpackages/uihot-reloads the docs immediately.site.urlis required (sitemap, llms.txt, OG images) — missing it breaks prerender with a 500.- Deploy base path comes from
NUXT_APP_BASE_URL(Nuxt's env override forapp.baseURL), never hardcoded. docs/app/components/content/holds components usable directly inside Markdown:Demo.vue(renders a runnable example + source) andApiTable.vue(renders the generated API tables).
API generation pipeline
scripts/gen-api.mjs uses vue-docgen-api to parse every .vue under packages/ui/src, extracts props/events/slots and their JSDoc comments, and writes docs/data/api/<dirName>.json. ApiTable.vue reads those JSON files by component name.
Consequence: API tables are generated from source and must never be hand-written. The component directory name is the doc key (src/button/Button.vue → button). After any change to a component's props/events/slots, run pnpm gen:api.
Design tokens (packages/tokens)
src/index.cssimportstokens.css(light/default) anddark.css. Consumed asimport '@g3soft/tokens'.- Dark theme activates via
html[data-g3-theme='dark'](document.documentElement.dataset.g3Theme = 'dark'). - Re-theming/customer customization = overriding same-named
--g3-*variables, no component changes.
Windows: dev-server port selection
docs/package.json runs node scripts/dev.mjs for dev (not nuxt dev directly). On Windows, Node sets SO_REUSEADDR, so two processes can bind the same host:port. Nuxt's built-in "is the port free?" check works by trying to bind a probe socket — which therefore succeeds even when another service already listens on 3000, so pnpm dev silently lands on 3000 (no 3000→3001 fallback). scripts/dev.mjs sidesteps this by testing the port with a real TCP connection (connect to 127.0.0.1/::1) and walking upward from DOCS_PORT/PORT/3000 until it finds a free one, then passing --port. devServer.host: '' (empty string — deliberately not '0.0.0.0') makes listhen listen on all interfaces and print a usable Local: http://localhost:<port>/ plus the LAN Network: URL; with '0.0.0.0' the Local line would be an unopenable http://0.0.0.0:<port>/.
Conventions (must follow)
- No
scopedin component<style>. Isolate with theg3-prefix + BEM naming so consumers can override. - Never hardcode colors or sizes — always reference
--g3-*variables, and give every variable a fallback value (e.g.var(--g3-color-primary, #1677ff)) so components render correctly even when@g3soft/tokensis not loaded. - Component API docs are generated, not authored — changes to props/events/slots require
pnpm gen:api. - Examples live at
docs/examples/<component>/<example>.vueand are referenced in Markdown as::demo{name="<component>/<example>"}. API tables use<ApiTable name="<component>" />. - New components get a
src/<name>/directory (component.vue,types.ts,index.ts) and must be re-exported fromsrc/index.ts.
Version constraints (do not relax)
pnpm-workspace.yaml documents these deliberately — read it before touching dependency versions:
nuxtis pinned to exactly4.4.8indocs/package.json. Do not widen to^4.4.8or upgrade to 4.5+. Nuxt 4.5+ pulls Vite 8 (Rolldown), which cannot resolve Nitro'sfile:///D:/...virtual modules on Windows, breaking#nitro-internal-virtual/*and causing every page to 500 (Either manifest or precomputed data must be provided). 4.4.8 → Vite 7 (Rollup) and matches Docus's official starter.pnpm 11uses theallowBuildsmap form inpnpm-workspace.yaml— the v10onlyBuiltDependenciesarray form is inert.better-sqlite3(Docus FTS5 search native module),vue-demi, andesbuildmust stay allowed.vueandtypescriptversions are centralized in the workspacecatalog:; each package references"vue": "catalog:"to avoid version drift.