Run dotnet run --project src/Forma.Builder from the repository root. Close the
old Builder before rebuilding its executable. The native Windows host contains
the web workspace: menus, toolbox, canvas, inspector and docked code editor.
Start with a project
Builder opens on a full-window start screen. Choose New project, Open project, a recent project, or a Login form, Settings dialog, or Dashboard template. Templates provide a starting layout; sign-in, storage, and dashboard data still need your application logic. Save a new design to keep it.
Recent entries show their last saved time. Removing an entry only removes it from the recent list; it does not delete the project file. Missing files are marked. Choose Go to the designer or press Escape to close the start screen. Use File → Start page to return later. Startup actions become available after the host finishes loading, without briefly exposing the designer first.
Build and test a small form
-
Click Toolbox in the left sidebar, then drag a Panel onto the form, then drop a TextBox, Label and Button inside it. The children belong to the panel and move with it. Double-clicking a toolbox entry also inserts a control.
-
Name them
nameInput,greetingLabelandgreetButtonin Properties. Names are unique identifiers; the read-only ID stays stable across renames. -
Move and resize them using selection handles or Layout values. Change zoom and confirm movement still uses form coordinates. Hold Alt to bypass snapping guides; Escape cancels an active drag.
-
Select the Button and click Custom Properties… below the property search. In the Script tab, replace the starter source with:
forma.on("click", () => { const name = String(forma.get("nameInput", "value") ?? "").trim(); forma.set("greetingLabel", "text", name ? `Hello, ${name}!` : "Enter a name."); }); -
Save the editor, then click Preview. Type a name and click the button. Preview runs a separate design copy in a resizable window with maximize support. Close it to end that runtime session. Saving script edits requires a fresh Preview to test the changed source.
-
Save the project with Ctrl+S. Open the
.formafile with Ctrl+O to confirm the design and script reopen. Ctrl+Z/Ctrl+Y undo and redo design edits; focused text editors keep their own text undo behavior.
Edit faster
| Action | How |
|---|---|
| Find a command, control, or form | Ctrl+K opens the command palette |
| Show the keyboard shortcut sheet | F1 or Help → Keyboard shortcuts |
| Select several controls | Ctrl/Shift+click, or drag a rectangle on the form |
| Select all controls | Ctrl+A while the design surface has focus |
| Copy / cut / paste / duplicate | Ctrl+C / Ctrl+X / Ctrl+V / Ctrl+D |
| Move the selection | Arrow keys; Shift uses 10-pixel steps |
| Resize the main selected control | Alt+Shift+arrow; Ctrl uses 10-pixel steps |
| Zoom the canvas | Ctrl+wheel, Ctrl+=, or Ctrl+-; Ctrl+0 restores 100% |
| Open a control's default event handler | Double-click a placed control |
Alignment/distribution actions operate on the eligible selected controls. Selecting a panel and its child does not move or copy the child twice. Pasted controls receive fresh IDs/names. Locked controls and managed layouts still restrict editing. Focused inputs and the code editor keep their own shortcuts.
The toolbar's Fit zoom accounts for the form frame and available canvas space. The selection breadcrumb lets you select a parent container directly. Form-size presets resize the form rather than changing canvas zoom. View options include a snapping grid and tab-order overlay; hold Alt during dragging to bypass snapping. The workspace offers keyboard navigation and labelled controls.
Browse the project
The left sidebar switches between Explorer and Toolbox. Solution Explorer
shows all forms, nested components, source files, the global script and image
assets in use. Click a component to select it in Design, or expand it and click
script.js, event.js, component.css or custom-properties.json to edit that source.
See Solution Explorer for search and keyboard navigation.
Add another form
Choose File → New form or Ctrl+N. The new form belongs to the current project; use the form selector above the canvas to return to the first form. Save retains all forms in the same file. Use File → New project or Ctrl+Shift+N to start a separate project. Preview runs the currently selected form.
From Preview, forma.showForm("settingsForm", { modal: true }) opens another
form from the same project and returns a promise for its close result. See
project files and multi-form Preview.
Layout and properties
Panel and GroupBox allow free positioning. Flow/stack/table layouts own child positions; X/Y edits do not override their arrangement. Use layout slots for split panes, tabs and table cells. TabControl has an Add tab action and horizontal or vertical tabs. Dock/Anchor apply to free-position children; Dock controls position and can control dimensions. This is intentional layout behavior.
Click empty form space to edit the form title, dimensions and appearance. Use property search to find component-specific settings. Enabled/Visible affect Preview; Design keeps components selectable. Locked prevents design edits. The workspace theme toggle changes the editor, not your form's appearance.
For live values outside events, use forma.bind and read .value when needed.
For shared values, open Project → Main script and use
forma.provide/forma.use or forma.shared. See the
script guide, runtime property reference
and global script examples.
Preview runs inside Builder. A saved design is not an exported executable; executable export and generated C# event handlers remain roadmap work.
Architecture and contributing
BuilderViewModel owns design state; services validate editing, persistence,
properties and Preview operations. Views host native windows and dispatch
browser messages. The browser handles immediate pointer feedback, while C#
validates committed edits. Preview owns its own model and reactive script scope.
See the MVVM architecture and folder structure.
Before adding a control, check the roadmap and toolbox implementation. A complete addition needs a model, renderer, factory/toolbox registration, contextual inspector properties, persistence, supported script operations and meaningful verification.
Automated checks
dotnet build Forma.slnx
dotnet test Forma.slnx
node --test tests/WebRuntime/*.test.cjs
Desktop testing complements these checks for pointer interactions, rendering and native window integration.