Skip to content

Repository files navigation

ReFrame

ReFrame

Your AI already built the website. ReFrame is where you visually finish it.
Click anything, make it look right — no prompt, no tokens, no regeneration, no fighting the code. The source stays yours.


What this is

ReFrame is a manual editing layer for websites that already exist as React/Next.js code — including sites generated by AI tools (v0, Lovable, bolt.new, Cursor). Those tools are good at generating a first draft and bad at the mechanical follow-up ("move this 12px," "align these cards," "make the mobile nav 8px shorter") — the kind of edit that's fastest done by hand, on a canvas, not by prompting an LLM again.

ReFrame is explicitly not an AI product. There's no chat, no LLM calls, no token metering anywhere in the editing path. It's a parser + a deterministic mutation engine + a canvas — closer to a code-aware Wix/Webflow than to a coding assistant.

Current scope (v0): Next.js (App Router) + React (Server & Client Components) + Tailwind CSS. Not a universal website editor yet.

Why this over the existing manual editor (Onlook)?

Existing direct-manipulation editors for React (Onlook is the closest one) operate on the rendered DOM/className string, not on the source's actual structure. That works for a static className="p-4" — but breaks down exactly where real component libraries live:

  • a className driven by a prop (variant === "transparent" ? "..." : "...") gets silently dropped or flattened to whichever branch happened to be visible when the edit was made
  • editing a shared component doesn't clearly distinguish "change this one instance" from "change the shared definition," so overrides get clobbered

ReFrame's engine is built around the opposite bet: parse real component structure — props, conditionals, shared-component usages, clsx/cn() calls — and refuse to guess when it doesn't recognize the shape, rather than silently corrupting it. See Architecture below for the specifics of what's currently supported.

Architecture

A pnpm workspace with two packages:

packages/core/    Headless engine — parse, resolve, mutate, write. No UI, no server.
apps/dev/         Dev-time visual editor: HTTP proxy + host shell + browser-side click resolver.

packages/core

  • parse.ts — source files → a ComponentGraph (recast-wrapped Babel parser, so mutations reprint only the changed subtree instead of the whole file).
  • class-ir.ts — a typed intermediate representation for className expressions. Every shape either matches a supported pattern or comes back as { kind: "unsupported", reason } — there is no silent fallback.
    • Supported: a plain string; prop === "value" ? A : B (direct comparison ternaries); clsx(...) / cn(...) calls whose args are each a string literal or test && "...".
    • Explicitly refused (each with a distinct reason): calls to any other helper function; template literals; ternaries on a derived variable (const isX = variant === "x"; isX ? A : B — traced dataflow is deliberately out of scope for now); nested/chained ternaries; anything else unrecognized.
  • resolve.ts — routes a DOM click (or a route + component name) to the right source target: the shared definition, or one specific call-site usage. Fails loudly ("can't disambiguate") rather than guessing when a component has multiple usages in one file that can't be told apart.
  • mutate/ — deterministic, targeted mutations: class.ts (set a ternary branch, without ever collapsing it to a flat string), prop.ts (per-instance prop overrides), move.ts (reorder JSX children as a whitespace-preserving chunk), tailwind.ts (token-exact utility class replacement — p-4p-6 never touches sm:p-4).
  • tailwind-scale.ts / properties.ts — maps a visual property edit (e.g. height in px) onto the Tailwind spacing scale when it lands on an exact step, falling back to an arbitrary-value class (h-[72px]) rather than silently rounding.
  • write.ts — recast-based reprinting: only the mutated subtree changes, so diffs stay small and human-reviewable.

apps/dev

  • proxy.ts — a reverse proxy in front of your already-running next dev. Injects one <script> tag into HTML responses (never touches RSC flight payloads), rewrites Host/Origin so Next's dev-origin checks stay happy, and passes the HMR WebSocket straight through. Your project's source is never modified — no config change, no injected script in your own layout.tsx — the injection happens at the HTTP layer, in front of the server.
  • static/preload.js — runs in the target page; walks up from a clicked DOM node via React's fiber tree (_debugInfo, since React 19 removed _debugSource) to resolve the click to the owning component, including through Server Component nesting.
  • host.ts / static/host.html — the editor shell: iframe of your app + a component list
    • a properties panel (height, padding, instance-vs-shared scope picker), talking to the proxy and to packages/core's mutation functions.

Getting started

Requires Node.js and pnpm.

pnpm install
pnpm test    # run packages/core's test suite

To try the live editor against a target Next.js app:

# 1. In your target project, start Next's own dev server as usual
cd path/to/your-nextjs-app && npm run dev   # e.g. listening on :3000

# 2. In this repo, point ReFrame's dev tool at it
cd apps/dev
pnpm start ../../path/to/your-nextjs-app 3000
# open http://localhost:4200

apps/dev assumes next dev is already running on the target port — it doesn't spawn it for you in this slice. There's a small bundled fixture app for trying this out immediately without a real project: fixtures/onlook-validation-app.

Status

Early and actively evolving — engine and dev-tool pieces above are implemented and tested; the polished canvas UI (drag/resize wired into the visual editor, a git-diff review step) is not built yet. Expect the supported-pattern boundary in class-ir.ts to expand over time rather than all at once — patterns outside it fail with an explicit reason rather than being silently mishandled.

License

Not yet decided.

About

Visual editor to edit React/Next.js websites directly in their source code with no AI.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages