Project layout
A freshly scaffolded project:
my-extension/├── src/│ ├── extension/│ │ ├── extension.ts # bootstrap(registry) — wires VS Code on activate│ │ └── _registry.ts # AUTO-GENERATED by `bun run gen`│ ├── panels/<name>.ts # one file = one webview panel (definePanel)│ ├── commands/<name>.ts # one file = one palette command (defineCommand)│ ├── menus/<name>.ts # activity-bar container + items (defineMenu)│ ├── treeViews/<name>.ts # data-driven tree view (defineTreeView)│ ├── subpanels/<name>.ts # inline webview section inside a menu│ ├── statusBars/<name>.ts # status bar item (defineStatusBar)│ ├── webview/│ │ ├── panels/<name>/ # React UI per panel (App.tsx, main.tsx)│ │ └── components/ # shared themed components (after `components add`)│ ├── services/ # business logic (e.g. <Model>Service.ts)│ ├── models/ # typed entities (after `model add`)│ ├── helpers/ # db.ts, secrets.ts, … (after `db init` / `helper add`)│ └── shared/│ ├── api.ts # RPC contracts (interface per panel)│ └── vsceasy/ # framework runtime — synced via `vsceasy upgrade`├── scripts/gen.ts # registry + contributes generator├── .vscode/launch.json # Extension Development Host launch├── vite.config.ts # webview build└── package.json # esbuild for extension, vite for UIOwned vs generated
- You own everything under
panels/,commands/,webview/,services/,models/,helpers/, andshared/api.ts. Edit freely. - Generated —
src/extension/_registry.tsandpackage.json#contributesare rewritten bygen. Don’t hand-edit them. - Framework runtime —
src/shared/vsceasy/*andscripts/gen.tsare owned by vsceasy. Keep them current withvsceasy upgrade; don’t edit them.
Build pipeline
- Extension code → esbuild →
dist/extension.js(CJS, node target). - Each panel/subpanel UI → vite →
dist/webview/<kind>/<name>/. bun run devruns both in watch; F5 launches the dev host.bun run package→.vsixvia@vscode/vsce.