Construct
Import an existing app
Bring existing pages across, one file, one route or one plan at a time.
import brings existing code into a Construct project: it scaffolds the layers you ask for and leaves a TODO(import) note in each pointing at the old source file. Porting the logic is a separate step, by you or, optionally, a model.
One file#
construct import PriceCheck --feature pricing --layers domain,hook --from ./old/PriceCheck.tsx
A whole page, guided#
construct import --route /v2/home
The route wizard traces the real import graph from that route's page, proposes a plan for the whole feature, and asks "Approve this plan and build it now?" before writing anything. By default it makes exactly one analysis call, to a hosted model, to produce the plan. Afterwards it runs validate and tells you what is left to fill in. The same wizard is available as the Import Wizard in the Cockpit UI.
Plan without a model: --planner mechanical#
construct import --route /v2/home --planner mechanical
Reads each traced file's syntax tree — JSX, its own state/effects, fetch/storage I/O, reducer/machine shape, plain exported functions — and computes the same { feature, units } plan no LLM call, instantly, offline, repeatably. Every layer the plan proposes prints a one-line reason (hook: keeps its own state/effects in the component (useState)), and files it leaves out (types-only, a barrel) are listed with why. The plan still goes through the same approval step and the same deterministic repair (normalizePlanLayers) as the AI-produced plan — only how the plan is computed changes. AI stays the default until it's been compared against the mechanical plan on more real routes; pick "Plan with: Mechanical" in the Cockpit wizard for the same choice.
From an approved plan#
construct import --plan ./plan.json
A plan is { feature, units: [{ name, layers, from }, ...] }; the command runs the same scaffold once per unit.
Add --llm to have a model write the ported logic#
Adding --llm <provider> (claude or ollama) makes one call per generated file. See Using an AI model, optionally.
Adopting Construct inside an existing project#
Construct doesn't need to own your whole repository. construct init accepts a directory, so you can scope it to one subdirectory of a larger, unrelated project — no changes required anywhere else in that project:
# from the root of an existing, non-Construct app:
construct init tools/construct
cd tools/construct && npm install && construct sync
Every other command accepts --dir <path> to target that subdirectory without cd-ing into it first (handy for CI, scripts, or running from the parent app's root):
construct generate domain PriceCheck --feature pricing --dir tools/construct
construct validate --dir tools/construct
--dir resolves the same way cd-ing in would — walking upward from that path to find the nearest architecture.yml — and every command still only ever reads or writes inside that project; nothing outside it is touched.