AI WebsiteAI WebsiteBuilderBuilder

2024Solo DeveloperArchived

A drag-and-drop website builder where an LLM writes the state management code.

A four-week prototype from early 2024 that combines drag-and-drop website building with AI-powered code generation. You lay out components visually, and an LLM handles the wiring—generating the frontend state management code that connects everything together.

The app has two modes: edit and preview. In edit mode, every component becomes draggable. You can reorder, resize, nest, and select elements to configure them. Switch to preview mode and the same component tree renders as a fully functional website—click handlers fire, forms submit, state flows through. The transition between modes is seamless, with all application state preserved.

JSON as the Entire Application

The core design decision is representing an entire React application as a JSON config tree. Every component, every event handler, every piece of state management—it’s all JSON. A recursive DynamicElement walks each node: it checks the config shape and routes to the right renderer. Nodes with actions and initialState become DynamicProviders—React Context providers with reducers built at runtime. Nodes with a type become DynamicComponents—real DOM elements with attributes and event handlers resolved from the config. Each renderer outputs its children as more DynamicElements, recursing until the tree is fully rendered. This single representation is what makes everything else possible. Dual rendering works because the tree doesn’t change between modes—only the event binding layer does. The AI can wire up state because it’s just transforming JSON. And the code editor works because the “source” is just a projection of the config.

When you select a component in edit mode, a code editor opens in the sidebar. But the “code” you see isn’t stored anywhere—it’s generated on the fly from the component’s internal config. Edit a Tailwind class or change the text, and the changes parse back into config mutations that update the live preview instantly.

Virtual Code Editor

The inline code editor shows what looks like a React component’s source, but there’s no source file. The builder stores each component as a config object—tag name, Tailwind classes, children, text content, event handlers. When you open the editor, a function walks the config and generates JSX on the fly. When you type a change, a reverse parser diffs it back into config mutations. The “code” is always a live projection of the actual component state, not a separate artifact that can drift out of sync.

The most ambitious feature is Magic Wiring. You don’t tell the AI what to do—you just build the design, and it intuits how things should connect. In the demo below, you can see this with a simple counter: the user drags out a number display, an up button, and a down button. Without any instructions, the AI looks at the component tree, infers that the buttons should increment and decrement the number, generates a React Context provider with the right reducer logic, and wires everything together. The generated code runs via eval in the browser, which is intentionally unsafe but enables things that would be impossible otherwise.

Behind the Scenes: Magic Wiring

The prompt gives Claude strict TypeScript interfaces—ComponentConfig, ProviderConfig, FunctionConfig—and few-shot examples. The model receives the component tree as JSON and returns a modified tree with providers inserted. A context registry lets components reference providers by string ID at runtime (normally you need a direct JavaScript reference to a Context object), but React’s scoping rules still apply—a component can only read a provider’s state if it’s a descendant in the tree. This is why the placement algorithm matters: the provider must be inserted above all its consumers. Everything the model outputs except the function body is structurally verifiable: the system recursively checks that every node conforms to the schema, that contextIds reference real providers, and that action names match. If validation fails, the error gets appended back into the conversation and the model is re-queried.

FunctionConfig: Constraining Eval

Most approaches would have the model write actual code—React components, hooks, state management. That requires the model to know syntax, handle imports, and produce bug-free JavaScript. FunctionConfig takes the opposite approach: the model only declares what state it needs and what to do with it. The runtime handles everything else—resolving references, injecting values, managing the Context tree, wiring event handlers. Because the structured fields (contextId, selector, action names) are all verifiable before anything runs, the only part that actually gets eval’d is a tiny expression like return args[0].toString(). This removes most of the context the model would need and eliminates entire categories of errors.

// DISPLAY: The model outputs this for the label's text:
label.textcontent = {
  contextId: "1",                    // "I need state from provider 1"
  selector: ["count"],               // "Specifically the 'count' field"
  body: "return args[0].toString();" // "Turn it into a string"
}

// INCREMENT: And this for the + button's click handler:
button.onClick = {
  contextId: "1",                    // "Dispatch to provider 1"
  actionName: "increment",           // "The increment action"
  actionPayload: null                // "No payload needed"
}

// Before eval, the runtime verifies the structured fields:
assert("1" in providers)             // ✓ provider exists
assert("count" in provider.state)    // ✓ field exists
assert("increment" in provider.actions) // ✓ action exists

// Then resolves and executes:
value = providers["1"].state["count"]    // → 42
fn = new Function("args", body)          // (args) => { return args[0].toString(); }
result = fn([value])                     // → "42"

// The model said what it needs. The runtime does the rest.
Demo
Stack
ReactTypeScriptTailwind CSSshadcnReduxClaude API
Features
  • Drag-and-drop component layout
  • LLM-generated state management code
  • Inline code editing with live preview
  • AI-powered design refinement (Magic Paint)
  • Seamless edit/preview mode switching