A visual drag-and-drop application builder powered by Svelte 5, built as a VS Code extension and fully compatible with Antigravity IDE.
Application Builder is a visual, drag-and-drop UI builder that lives inside your IDE. Think of tools like Pinegrow, Figma, or Webflow — but directly inside Antigravity IDE or VS Code.
Instead of writing HTML/CSS by hand for every layout, you:
All components on the canvas are real Svelte 5 components — not static wireframes or screenshots.
| Feature | Status |
|---|---|
| Drag & Drop Svelte components onto canvas | ✅ Working |
| Live component rendering (Hero, Button, Card, etc.) | ✅ Working |
| Navigator / Layers Tree with hierarchy | ✅ Working |
| Nested components (parent → child) | ✅ Working |
| Select, move, resize nodes on canvas | ✅ Working |
| Zoom & pan canvas | ✅ Working |
| Right-click context menu (Delete, Duplicate, Bring to Front) | ✅ Working |
| Properties panel (X, Y, W, H inputs) | ✅ Working |
| Multi-device frames (Desktop / Tablet / Mobile) | ✅ Working |
| Navigator ↔ Canvas selection sync | ✅ Working |
| Antigravity IDE support | ✅ Working |
| VS Code support | ✅ Working |
Step 1 — Build the VSIX package
Open a terminal in the project folder and run:
npm install
npm run build
npx vsce package --no-dependencies --out app-builder.vsix
This creates app-builder.vsix in the project root.
Step 2 — Install via Antigravity CLI
& "C:\Users\<YourUsername>\AppData\Local\Programs\Antigravity\bin\antigravity" --install-extension "D:\Github\vscodeplugin-applicationbuilder\app-builder.vsix" --force
Replace <YourUsername> with your Windows username (e.g., Gellish).
Step 3 — Restart Antigravity IDE
Close and reopen Antigravity IDE. The extension will be loaded automatically.
Step 1 — Build the VSIX (same as above)
Step 2 — Install via VS Code CLI
code --install-extension app-builder.vsix --force
Step 3 — Reload VS Code
Press Ctrl+Shift+P → type "Developer: Reload Window" → press Enter.
After installing and restarting the IDE:
You can also open the canvas manually:
Ctrl+Shift+P → type "Application Builder: Open" → press Enter.The sidebar has two tabs:
Browse and add Svelte components. Components are grouped by category:
| Group | Components |
|---|---|
| Layout | Navbar, Hero, Footer |
| Basic | Button, Text, Card, Form |
| Media | Image |
To add a component:
Tip: If you have a component selected on the canvas when you click a component card in the sidebar, the new component is added as a child inside the selected one (nested component!).
The Navigator shows the live layer hierarchy of everything on the canvas — exactly like Figma's layers panel or Pinegrow's DOM tree.
The canvas is the main editing surface. It shows your components as draggable, resizable blocks rendered inside device frames.
Three device frames are always visible:
| Frame | Width |
|---|---|
| Desktop | 1000px |
| Tablet | 768px |
| Mobile | 375px |
Right-click any selected component to get:
| Action | Description |
|---|---|
| Duplicate | Creates a copy of the selected component (Ctrl+D) |
| Bring to Front | Moves the component above all others |
| Send to Back | Moves the component below all others |
| Delete | Removes the component (Delete or Backspace) |
The right side of the canvas panel shows the Design / Properties panel.
When a component is selected, it shows:
| Property | Description |
|---|---|
| X | Horizontal position on the canvas (in pixels) |
| Y | Vertical position on the canvas (in pixels) |
| W | Width of the component (in pixels) |
| H | Height of the component (in pixels) |
You can type new values directly into the fields to precisely position or resize a component.
Each component is a real Svelte 5 component file located in src/components/.
| Component | File | Description |
|---|---|---|
| Navbar | Navbar.svelte |
Top navigation bar with logo and links |
| Hero | Hero.svelte |
Full-width hero section with headline and CTA |
| Footer | Footer.svelte |
Page footer with copyright text |
| Button | Button.svelte |
Clickable button element |
| Text | Text.svelte |
Paragraph/text block |
| Card | Card.svelte |
Content card with title and body |
| Form | Form.svelte |
Input form with basic fields |
| Image | Image.svelte |
Image placeholder block |
To add a new component type, create a new .svelte file in src/components/ and register it in two places:
src/CanvasApp.svelte → add to componentMapsrc/SidebarPanel.svelte → add to the groups arrayThe Navigator mirrors how Pinegrow and Figma handle the DOM/layer hierarchy.
When you drop a component on top of another on the canvas, it is automatically assigned as a child of the component it was dropped onto (based on which component's bounding box contains the drop point).
When you click a component in the sidebar while another is selected on the canvas, the new component is placed inside the selected component.
The Navigator renders a recursive tree:
📦 Hero
🔘 Button
📝 Text
☰ Navbar
🎴 Card
📝 Text
🔘 Button
| Shortcut | Action |
|---|---|
V |
Switch to Select tool |
H |
Switch to Hand/Pan tool |
Space + Drag |
Pan the canvas |
Scroll Wheel |
Zoom in/out |
Ctrl + 0 |
Reset zoom to 100% and pan to origin |
Ctrl + D |
Duplicate selected component(s) |
Delete / Backspace |
Delete selected component(s) |
Shift + Click |
Add component to selection |
vscodeplugin-applicationbuilder/
├── src/
│ ├── extension.ts # VS Code extension entry point
│ ├── canvasMain.ts # Canvas webview entry (Svelte mount)
│ ├── sidebarMain.ts # Sidebar webview entry (Svelte mount)
│ ├── CanvasApp.svelte # Main canvas UI (drag, drop, zoom, pan)
│ ├── SidebarPanel.svelte # Sidebar UI (Components + Navigator tabs)
│ ├── canvasStore.ts # Svelte store — all canvas state
│ └── components/ # Real Svelte component files
│ ├── Button.svelte
│ ├── Card.svelte
│ ├── Footer.svelte
│ ├── Form.svelte
│ ├── Hero.svelte
│ ├── Image.svelte
│ ├── Navbar.svelte
│ └── Text.svelte
├── dist/ # Production build output
│ ├── extension.cjs # Bundled extension host code
│ └── assets/
│ ├── canvasMain.js # Bundled canvas webview
│ ├── sidebarMain.js # Bundled sidebar webview
│ ├── canvasMain.css # Canvas styles
│ └── sidebarMain.css # Sidebar styles
├── canvas.html # Vite HTML entry for the canvas
├── sidebar.html # Vite HTML entry for the sidebar
├── vite.config.ts # Vite build configuration
├── package.json # Extension manifest + npm scripts
└── app-builder.vsix # Packaged extension (after build)
This extension uses a three-part architecture:
┌─────────────────────────────────────────────────────────┐
│ Antigravity IDE / VS Code │
│ │
│ ┌───────────────┐ Messages ┌──────────────────┐ │
│ │ Sidebar │◄────────────►│ Extension Host │ │
│ │ Webview │ │ (extension.ts) │ │
│ │ (Svelte) │ │ │ │
│ └───────────────┘ └────────┬─────────┘ │
│ │ Messages │
│ ┌────────▼─────────┐ │
│ │ Canvas Webview │ │
│ │ (Svelte) │ │
│ └──────────────────┘ │
└─────────────────────────────────────────────────────────┘
| Part | Technology | Responsibility |
|---|---|---|
| Extension Host | TypeScript (Node.js) | Creates webview panels, routes messages between sidebar and canvas |
| Canvas Webview | Svelte 5 + canvasStore | Renders the canvas, handles drag/drop/zoom/pan, syncs state |
| Sidebar Webview | Svelte 5 | Renders component palette + Navigator tree |
All three parts communicate using VS Code's postMessage API:
canvas.postMessage({ command: 'syncNodes', nodes: [...], selectedIds: [...] })
Sent whenever the canvas state changes. The extension host relays this to the sidebar.
sidebar.postMessage({ command: 'syncNodes', nodes: [...], selectedIds: [...] })
Sidebar receives this and updates the Navigator tree.
When the user clicks a component in the Navigator or Component palette:
sidebar → { command: 'selectNode', id: '...' }
sidebar → { command: 'addComponent', type: 'Button' }
↓ extension host relays to canvas ↓
canvas receives and acts on it
Development mode uses Vite's Hot Module Replacement (HMR) for instant UI updates without rebuilding.
Step 1 — Install dependencies
npm install
Step 2 — Start the dev server + extension watcher
npm run dev
This runs two processes in parallel:
vite — Svelte dev server on http://localhost:5173watch:extension — esbuild watching extension.ts, rebuilding on changes with __DEV__=trueStep 3 — Launch in Extension Development Host
In VS Code / Antigravity IDE, press F5 (or go to Run → Start Debugging). This opens a new IDE window with the extension loaded in dev mode, pointing to the local Vite dev server.
Note: In dev mode, the sidebar and canvas webviews load from
localhost:5173. If the Vite server is not running, the webviews will be blank.
Production mode bundles everything into the dist/ folder. No dev server is needed.
npm run build
This runs two steps:
npm run build:webview — Vite bundles all Svelte code into dist/assets/npm run build:extension — esbuild bundles extension.ts into dist/extension.cjs with __DEV__=falseWith __DEV__=false, the extension loads webviews from the local dist/assets/ files, not from localhost.
A .vsix file is a self-contained extension package that can be installed in any VS Code-based IDE.
Prerequisites:
npm install -g @vscode/vsce
Package:
npm run build
vsce package --no-dependencies --out app-builder.vsix
Install in Antigravity IDE:
& "C:\Users\<YourUsername>\AppData\Local\Programs\Antigravity\bin\antigravity" --install-extension ".\app-builder.vsix" --force
Install in VS Code:
code --install-extension app-builder.vsix --force
After installing, restart the IDE to apply the new extension version.
This happens when the webviews try to connect to a Vite dev server that isn't running.
Fix: Run a production build and reinstall:
npm run build
vsce package --no-dependencies --out app-builder.vsix
# Then install the VSIX (see above) and restart the IDE
Even if you rebuild the .vsix with --force, Antigravity IDE and VS Code aggressively cache extension assets based on the version number. If you modify the Svelte UI but don't bump the version, you might still see the old UI.
Fix: Open package.json, increment the "version" (e.g., from 1.0.0 to 1.0.1), then rebuild and install the VSIX.
This occurs if elements are moved into a container with overflow: hidden but loose their global pointer events, or if dragging destroys and re-creates the DOM element mid-drag.
Fix: Components are rendered globally within their respective device-frame blocks but use absolute positioning. .device-frame and .canvas-node must both have pointer-events: auto so that the drag events are not stolen by the background canvas. The application builder now automatically auto-fits layout components (Navbar, Hero, Footer) to snap perfectly into the device frames.
The canvas opens automatically on activation. If it doesn't:
The Navigator is populated by messages sent from the canvas. This means:
If this doesn't work, try closing and reopening the canvas tab.
You need to register the new component in SidebarPanel.svelte under the groups array:
{
title: 'Basic',
items: [
{ type: 'MyNewComponent', icon: '🆕', label: 'My Component' },
// ...
]
}
Ensure you are dropping components onto the canvas viewport (the dark dotted area), not on the toolbar or properties panel.
| Feature | Priority |
|---|---|
| Drag-to-reorder layers in Navigator | 🔜 Next |
| Component props editor (change text, colors, etc.) | 🔜 Next |
| Export to Svelte code | 📋 Planned |
| Undo / Redo history | 📋 Planned |
| Import existing Svelte components from project | 📋 Planned |
| Responsive breakpoint preview toggle | 📋 Planned |
| Custom component registration UI | 💡 Idea |
| Collaboration / multiplayer canvas | 💡 Idea |
MIT — free to use, extend, and modify.
Built with ❤️ using Svelte 5, Vite, TypeScript, and the VS Code Extension API.