The asset folder had four files in it. A logo in JPEG at 480 pixels wide with a white box baked around it, two blown-out phone photos of a driveway, and a scan of a business card. That was the entire visual library of a construction firm that builds luxury homes — and it's the normal state of trades clients. My position after this build: you should stop treating that as a design problem and start treating it as an evidence problem, because a construction website with AI-generated visuals can now manufacture the one asset no contractor ever has — continuous footage of a build in progress — if you avoid one specific mistake that sank my first attempt.
I built the whole site with AI generating every visual: layout in Figma, code via Claude Code, hero imagery from Higgsfield's image models, and the centerpiece timelapse from ByteDance's Seedance 2.5. Here's the workflow, and the two decisions in the middle that nobody writing about this stack mentions.

The evidence problem, not the design problem
A construction client's visitor is about to spend a very large amount of money with strangers. They are not evaluating your typography. They scroll looking for proof that these people have done this before — the site at week two with rebar exposed, the frame going up, the roof closing in. A contractor's real portfolio is process, and process is exactly what nobody photographs, because at 6 AM pouring a slab you are not thinking about content marketing.
So the job was never "make a nice construction website with AI." It was: manufacture credible process evidence, then design the page that puts it where the doubt lives. The hero has one job — make you believe these people work at this level. The build-timeline section has one job — show construction actually happening. That reframing made the video model the load-bearing element of the page, not a decoration.
Figma first, because Claude Code needs a source of truth
I was tempted to skip Figma. Claude Code generates a decent layout from a prompt — and I've watched those pages drift: you ask for one change, the model rebalances three other things, and by iteration six the design is gone because there was never a source of truth.
The direction I locked before drawing anything: dark charcoal with deep green (generated exteriors carry atmospheric haze that reads cinematic against dark and as noise against white), two typefaces total, and the build-timeline section directly after the hero — the doubt arrives early, so the evidence goes early.
The file structure is what Claude Code actually reads, so it stayed deliberately boring:
- Real variables, not hex values typed into fills:
color/surface/base,color/accent/moss,space/2throughspace/12 - Auto layout on every container — auto layout is what becomes flexbox; an absolutely positioned frame becomes an absolutely positioned div and a responsive bug
- Components for whatever repeats: service card, stat block, timeline step
- Frames named like code:
Section/Hero,Section/BuildTimeline, neverFrame 247
That naming discipline is the single highest-impact thing you can do before a handoff, for a reason I'll get to.
Generating the hero when the client has nothing
For architectural exteriors I used Nano Banana Pro through Higgsfield. My first prompts described the scene and got back renders — technically correct, emotionally dead. What fixed it was prompting the camera instead of the subject:
Cinematic architectural photograph, shot on 35mm, golden hour,
low sun raking across the frame from camera left.
Foreground: a yellow tracked excavator, arm lowered and at rest,
tracks caked in wet clay, parked on churned earth.
Midground: a completed contemporary luxury house — flat roof,
full-height glazing, vertical charcoal timber cladding.
Shallow depth of field. Dust particles caught in the light.
Muted desaturated palette. No people. No text. No logos.
Three details transfer to any trade. "Arm lowered and at rest" kills the action-shot cliche — a machine parked at the end of a shift reads as a real site someone walked away from. "Tracks caked in wet clay" is the credibility detail; clean equipment reads as a render. And naming the film stock does more for realism than any "photorealistic, 8k" keyword soup. The negatives matter equally: no people, because AI hands are still a coin flip; no text, because near-miss lettering is the first thing the eye catches. Keeping a whole set of generated assets consistent across a page is its own problem — I covered that in my sci-fi landing page build with Higgsfield.
Seedance 2.5 changes the brief, not just the spec sheet
ByteDance announced Seedance 2.5 at its Volcano Engine FORCE conference on June 23, 2026 and released it on July 31. The headline change is duration: 30 seconds in a single generation, double Seedance 2.0's 15, plus up to 50 conditioning references and audio generated in the same pass. On Higgsfield it generates at 480p or 720p with 4K as a separate upscale step — plan around 720p plus an upscale, not native 4K.
Here's why the 30-second number reframes the brief. At 8 seconds per clip — the length everyone worked with for two years — a construction timelapse is necessarily five separate generations cut together: excavation, foundation, framing, roofing, landscaping. That's how I planned it, and that's how I built it first.
It didn't work, and the failure mode is specific enough to be worth naming.
The segmented-clips mistake
I generated five 8-second clips, one per build phase, each seeded from the same reference stills. Watched in sequence, the house changed identity between every cut. The framing clip produced a two-story structure; the roofing clip put a single-story roof on it. Window count went six, four, seven. The cladding shifted from vertical charcoal timber to horizontal gray board. The landscaping clip invented a driveway on the opposite side of the plot.
Every clip was individually good. Together they told the story of five different houses on the same lot.
This is the thing about reference conditioning that gets undersold: references constrain style far more reliably than they constrain geometry. A reference still reproduces the mood, palette, and material feel — then guesses at the window count, because window count isn't what the conditioning signal encodes strongly. Across five independent generations those guesses don't agree, and architecture is the worst subject for it, because a house is defined by countable facts. You cannot prompt your way out either; I tried specifying "exactly six windows, single-story" across five jobs, and it improved the hit rate without making it reliable — five independent samples don't converge on a shared spec by luck.
So I threw the segments out and generated one continuous 20-second aerial arc, the build progressing under the moving camera. Same house the whole way through, because it was never re-sampled. Continuity is free inside a single generation and expensive across several — that inverts the "generate short clips and edit" rule that has held since AI video became usable. The prompt structure I'd carry to any project separates change from invariants:
Single continuous aerial shot, no cuts. Slow clockwise orbit.
Time-lapse progression:
0-4s bare plot, excavator cutting foundations
4-8s slab poured, formwork removed
8-13s timber frame rising, trusses set
13-17s roof closed, charcoal cladding, glazing installed
17-20s landscaping complete, interior lights on, dusk
Constant: single-story contemporary house, flat roof, six windows
on the front elevation, charcoal vertical timber cladding,
plot orientation and driveway position unchanged throughout.
The Constant: block gives the model an explicit invariant list instead of burying those facts inside the temporal description where they compete with the motion. I went 20 seconds rather than 30 for one reason: the scroll-scrub encode below inflates file size, the video sits above the fold, and a heavy hero-adjacent asset wrecks your LCP.
The Figma-to-Claude-Code handoff
For Claude Code the supported path is the official plugin — claude plugin install figma@claude-plugins-official, restart, authorize via /plugin. What the MCP server gives Claude Code is the part people get wrong: it reads design context — components, variables, layout data — not a picture. Your color/accent/moss variable arrives as a named token and becomes a CSS custom property with that name. Your auto-layout frame with a 24px gap becomes flexbox with gap: 24px. Your Section/BuildTimeline frame becomes a component named accordingly.
That's the payoff of the naming discipline: generated code quality is a direct function of how much semantic structure exists in the file. A messy Figma file produces messy code from a perfectly good MCP server, and then people conclude the server is bad. My first-pass prompt ended with the most useful instruction in the whole build — "Stop after the hero. Do not build other sections yet." Section by section, corrections compound; the next section inherits the fixed conventions. The full setup, including what to do when the server returns structure you didn't expect, is in my Claude Code and Figma MCP workflow.
Making the timelapse scroll-scrubbed
The interaction that makes the page: the visitor scrolls and the house builds at exactly the speed they scroll. On a page whose job is proving process, letting someone drive the process is a better argument than showing it.
The step everyone skips is the encode. A normal MP4 places keyframes every couple of seconds; seek to an arbitrary point and the decoder walks back to the nearest keyframe and rebuilds forward — fine for a play button, terrible when you seek sixty times a second. Force dense keyframes:
ffmpeg -i build-timelapse.mp4 -an \
-vf "scale=1280:-2,fps=30" \
-c:v libx264 -g 5 -keyint_min 5 -sc_threshold 0 \
-crf 23 -preset slow -movflags +faststart \
build-timelapse.scrub.mp4
On the JavaScript side, never write scroll position straight into currentTime — scroll events fire faster than a decoder can seek, and direct assignment stutters. Interpolate toward the target inside a requestAnimationFrame loop:
function tick() {
const delta = target - current;
if (Math.abs(delta) < 0.005) { running = false; return; }
current += delta * 0.15; // the feel dial
video.currentTime = current;
requestAnimationFrame(tick);
}
Wait for loadedmetadata before reading video.duration (it's NaN until then, and NaN seeks fail silently), keep the scroll listener { passive: true }, and serve a reduced-motion branch — a static section with a looping video — to anyone who asked their OS to stop moving things. On mid-range Android the scrub degrades noticeably; test on a real device and be ready to serve the reduced-motion path to mobile entirely. If the scrub is too rough, the frame-extraction flipbook (video exported to an image sequence painted to canvas) trades bandwidth for seek reliability — I built that version end to end in my Apple-style 3D scroll animation walkthrough.
What I'd tell you before you build one
The video model is the bottleneck, not the code. The HTML, CSS, and JavaScript is maybe ninety minutes with Claude Code doing the typing. Getting footage where the house doesn't mutate is the real project.
Continuity is now a generation-length decision. If the subject has countable geometry — buildings, products, vehicles — generate it in one pass. If it's atmospheric — weather, crowds, texture — segments are still fine, because nobody audits the cloud count.
Generated footage has an honesty floor. It sells atmosphere, not documentation. Every client gets the same conversation: this represents the kind of work you do, it is not a record of a specific job, and the moment real site footage exists we swap it in. Anyone selling generated footage as a case study is heading for an uncomfortable conversation.
Imperfection is an asset. I ended up color-grading the client's two terrible driveway photos and cropping them hard into the testimonials block. The imperfection reads as real and makes everything around it read as more real. That was an accident I'd now repeat deliberately. The pricing math for this kind of client work — build cost, media subscriptions, what to quote — is in my breakdown of local business sites built with Claude.
After 8+ years and 1,500+ projects, this is the first stack where a client with four unusable files in an asset folder ends up with a site that competes visually with firms that hired a photographer. Audit the asset folder before you quote anything — the photo situation, not the design brief, decides whether this pipeline saves you a week or costs you one. Builds like this one are a standing engagement on my services page.