Build Framer
KINDAreplaces $10/mosaves $120/yrback to the verdict
A visual editor over a layout tree rather than a canvas of positioned boxes, reusable components with overridable content, breakpoints that adjust rules rather than duplicating designs, and a static export of real HTML and CSS that loads fast and works without JavaScript for its content.
Before step 1
Everything below is assumed from the first step. Tick each one when you actually have it, not when you plan to.
- installfree
Why Runs the editor build and the asset pipeline.
Get it nodejs.org, or nvm install 22. open ↗
Verify
node --version prints v22 or higher - have readyfree
Why Layout containers are only tested by a real design, which will contain the one arrangement that makes you want an absolute position. Solving that with a container type is the point.
Get it Take a site you designed or admire and rebuild it. The section that resists is where the container model needs work.
Verify
A real multi-section page is rebuilt without any positioned element - have readyfree
Why Page weight and responsive images are invisible with placeholder graphics and immediately obvious with real photographs.
Get it Use images you have the rights to, at the sizes they came from the camera.
Verify
A page with photographs reports its weight - have readyoften free hosting; roughly 10 to 15 US dollars a year for a domain
Why Product phase only. The output is plain files and needs somewhere to live with a certificate.
Get it Any static hosting with automatic certificates, plus a domain from any registrar.
Verify
The site serves over HTTPS - decidefree with your own endpoint
Why A static site cannot receive a submission by itself, and the easy answer sends your visitors' data to a service you have not evaluated.
Get it Decide before publishing a form: your own endpoint, or a service whose terms and retention you have read. Record the decision.
Verify
The destination and its retention are documented
Data model
Create these before the first phase that stores anything. Changing a table later is the expensive kind of change.
- sites(id, name, updated_at), pages(id, site_id, path, title, meta_json) - nodes(id, page_id, parent_id, ordinal, kind, props_json, style_rules_json) · kind is stack, grid, text, image, link or component_instance - components(id, site_id, name, root_node_id), instances(node_id, component_id, overrides_json) - breakpoints(id, site_id, name, min_width, ordinal) - style_rules · per node per breakpoint, adjusting the rule rather than redefining the node - assets(id, site_id, path, kind, width, height, bytes) - No node has x and y. A node has a parent, an order and layout rules, which is what makes one design work at every width.
Environment variables
These go in a .env file the app reads at startup. The pack's .env.example is this table as a file · copy it, never commit the filled-in version.
| Variable | Needed | Example | Where the value comes from |
|---|---|---|---|
VITE_SITE_PATH | required | ./sites/mysite.json | The site definition. Version controlled, so a design change is a reviewable diff. |
VITE_ASSETS_DIR | required | ./assets | Source images before size generation. |
VITE_IMAGE_WIDTHS | required | 480,960,1440,1920 | Sizes generated per image for responsive markup. |
VITE_PAGE_WEIGHT_WARN_KB | required | 600 | Page weight at which the editor warns. Visible while building rather than after publishing. |
EXPORT_DIR | required | ./dist | Where static output is written. |
FORM_ENDPOINT | optional | https://forms.example.com/submit | Where submissions post. Yours, or a service whose retention you have read. |
The build, in order
A layout tree with no coordinates
You can build a page visually and nothing stores a position.
Stack and grid with real rules. Direction, gap, padding, alignment.
Files
src/model.tsterminalnpm create vite@latest . -- --template vanilla-ts
Drop targets are containers and positions in an order, not points on a canvas.
Files
src/drag.tsThe same code path. Two renderers diverge and the difference always appears after publishing.
Files
src/render.ts
done when · tick each as it passeswatch out- Allowing an escape hatch of absolute positioning for one tricky element means every subsequent tricky element uses it too, and within a month the site is a canvas again. If a layout genuinely needs it, that is a missing container type rather than a reason to store coordinates.
Components with overrides
Changing a component changes every instance, except where an instance deliberately differs.
An instance is a component reference plus the properties it changed. Nothing else.
Files
src/components.tsEvery render, so propagation is automatic rather than a sync step.
Files
src/resolve.tsName what is missing. A silent hole is worse than a visible error.
Files
src/resolve.ts
done when · tick each as it passeswatch out- Storing an instance as a copy with a link back makes a component change ambiguous, because you cannot tell which differences were deliberate and which are stale. Store only overrides and resolve at render, which is what makes propagation automatic.
Breakpoints that adjust rather than duplicate
A narrow screen gets a different layout without a second design to maintain.
Per node per breakpoint, inheriting upward. One tree, several rule sets.
Files
src/breakpoints.tsSwitchable in the editor, using the same renderer.
Files
src/preview.tsEdit text once and check every width. If you have to edit twice, the tree got duplicated.
done when · tick each as it passeswatch out- Duplicating the node tree per breakpoint means every content change has to be made three times and they drift within a week, which is the exact problem responsive design was invented to solve. One tree, rules overridden per breakpoint, inherited upward.
Images that do not ruin the page weight
A page with photographs still loads quickly on a phone.
Several widths, plus a modern format alongside a fallback.
Files
src/assets.tsSo the browser picks. Serving one size to everyone is the default failure.
Files
src/render.tsPer page, in the editor. Visible while building rather than discovered after launch.
Files
src/ui/Weight.tsx
done when · tick each as it passeswatch out- Serving one large image to every device is the single biggest cause of slow pages built this way, and it is invisible on a fast connection. Generate sizes, emit the markup that lets the browser choose, and report the total weight so the problem is visible while you build rather than after.
Static export that works without scripts
The published site shows its content with JavaScript disabled.
Map node kinds to real elements. Generic containers everywhere is the tell of a bad builder.
Files
src/export.tsNot injected. Verify by disabling scripting and reloading.
Two exports identical, so a diff shows real changes.
Files
src/export.test.ts
done when · tick each as it passeswatch out- A visual builder that emits a page of generic containers filled by JavaScript produces a site that is slower, less accessible and invisible to anything that does not run scripts. Emit semantic markup with the content present, and treat interactivity as an enhancement rather than the delivery mechanism.
Publishing, forms and the things a site needsproduct builder
The site is live, its forms work, and it can be republished from a version you can diff.
Any static host with automatic certificates. The output is plain files.
Files
scripts/deploy.shSomewhere you control, with a decision about retention recorded.
Files
src/forms.tsdocs/forms.mdJSON with stable ordering, so a design change is reviewable as a diff.
Files
src/serialise.ts
done when · tick each as it passeswatch out- A form on a static site needs somewhere to post, and wiring it to a third party endpoint sends your visitors' submissions to a service you have not thought about. Decide where submissions go and what happens to them before publishing the form rather than after the first one arrives.
That is the whole plan for Framer. What it deliberately does not cover is below · check the gaps before you call it a replacement.
- The visual design polish of the commercial editor.
- Animation and interaction design.
- The template marketplace.
- Managed hosting with a delivery network.
- visual design polish
- animations
- templates
- CMS
- hosting
- preview/publish flow
- forms
- A content collection so a blog does not mean duplicating a page per post
- Design tokens for colour and spacing, applied by reference across the site
- A visual diff between two versions of a page, since the definition is already diffable
Need the files? The project pack on the verdict page hands your agent the whole brief · more website builders.