The client's asset folder contained four files.
A small JPEG logo with a white background baked into it. Two overexposed phone photos of a driveway. A scan of a business card.
That was effectively the entire visual library for a company selling high-value construction work.
So when I say I built a construction website with zero photos, I mean zero usable project photography—the kind of finished-home photography, progress footage, architectural details, and site documentation you would normally expect to design around.
My stack was:
Figma for the visual direction, Claude Code for implementation, Nano Banana Pro through Higgsfield for architectural concepts, and ByteDance Seedance 2.5 for the construction sequence.
But the most important lesson from the build was not which AI model produced the best frame.
It was this:
AI can solve the visual-explanation problem. It cannot replace real evidence.
A generated house can establish mood.
A generated construction sequence can explain a process.
Neither should be presented as a project the contractor actually built.
That distinction changed how I structured the whole site.

The Real Problem Was Not "We Have No Good Photos"
Construction websites have an unusual trust problem.
A visitor may be considering a project worth tens or hundreds of thousands of dollars. Before they care about your typeface, animation, or card radius, they want to know:
Can these people actually do the work?
Traditionally, the answer comes from real project evidence:
finished projects;
progress photography;
client testimonials;
licenses and certifications where applicable;
named projects;
specific capabilities;
real site details.
AI does not manufacture any of that evidence.
What it can manufacture is the visual layer around the evidence.
That sounds like a small distinction. It is not.
My first framing for this project was:
We need to generate convincing construction evidence.
I would no longer phrase it that way.
The better brief is:
We need to explain the quality and process of the company's work visually while keeping actual proof clearly separated from illustrative AI media.
That leads to a much more trustworthy page.
Real client material—even imperfect phone photos—belongs in the proof sections.
Generated material belongs in places where the visitor understands it as visual storytelling, concept imagery, or process illustration.
For U.S. marketing, that distinction also aligns with the FTC's basic rule that advertising claims must be truthful, non-deceptive, and supported where objective claims are made. A visual can create an implied claim just as copy can.
Figma Was My Source of Truth Before Claude Code Started Building
I was tempted to skip Figma.
Claude Code can generate an attractive frontend from a description, and for low-stakes pages that may be enough.
The problem appears after revision three or four.
You change the hero.
Spacing shifts elsewhere.
You adjust the service cards.
Typography changes slightly.
You fix the typography and discover the mobile composition has moved.
The page is being designed and implemented simultaneously, so there is no stable visual target to compare against.
For this build, I separated those stages.
The design direction was locked first: dark charcoal surfaces, restrained deep green accents, two typefaces, large architectural imagery, and the construction-process section immediately after the hero.
That last decision mattered more than the color palette.
The visitor's first question is trust.
So the page answers it early.
Structure Your Figma File for an Agent, Not Just for Yourself
The Figma file did not need to be elaborate.
It needed to be legible.
I used meaningful variables, reusable components, Auto Layout where appropriate, and frame names that described their purpose rather than their creation order.
For example:
Section/Hero
Section/BuildTimeline
Section/Services
Component/ServiceCard
Component/ProjectStat
The reason is straightforward.
Figma's current MCP integration gives AI agents structured design context: components, variables, typography, layout information, and other design data. Claude's official Figma plugin can also use Code Connect to map design components to their real codebase equivalents.
Today, the integration goes further than it did when I first built this workflow. Figma's remote MCP server can now also let supported agents write native content back to the Figma canvas, including frames, components, variables, and Auto Layout.
So the workflow is becoming bidirectional.
Figma can inform the code.
Claude Code can also help update the design.
But I would correct one claim from my original notes: a Figma variable does not magically guarantee a CSS custom property with the identical name, and every Auto Layout frame does not deterministically become the exact Flexbox implementation you imagined.
Structured Figma data gives Claude much better information.
Your implementation prompt, codebase, component system, and Code Connect mappings still determine the final translation.
The Current Claude Code + Figma Setup
Figma's recommended Claude Code setup is still the official plugin:
claude plugin install figma@claude-plugins-official
Then restart Claude Code and authenticate through /plugin.
The plugin exposes workflows such as design-context extraction, implementation from Figma frames, design-system rules, and component mapping.
That means the handoff can be much stronger than:
Here is a screenshot. Reproduce it.
Claude can work from the underlying structure instead.
And structure is what makes iterative implementation more stable.
One instruction I still use constantly is:
Stop after the hero. Do not implement the next section yet.
AI-generated frontends improve dramatically when they are corrected section by section rather than generated as one enormous first pass.
The fixed conventions from section one then become context for section two.
Generating an Architectural Hero With No Photography
For the hero concept I used Nano Banana Pro through Higgsfield.
Higgsfield currently positions Nano Banana Pro as its precision-oriented Google image model for complex scenes, perspective, lighting, quantities, and other structured visual instructions.
My first prompts were subject-heavy:
Luxury modern house on a construction site.
The outputs were competent.
They were also generic.
What improved the result in this particular build was describing the camera, light, material condition, and environmental imperfections instead of piling on adjectives such as "photorealistic" and "8K."
The useful prompt looked closer to this:
Cinematic architectural photograph, 35mm perspective.
Golden-hour sunlight entering from camera left.
Foreground:
yellow tracked excavator at rest,
arm lowered,
tracks covered in wet clay,
parked on disturbed earth.
Midground:
single-story contemporary luxury house,
flat roof,
full-height glazing,
vertical charcoal timber cladding.
Natural construction-site dust in the light.
Muted, slightly desaturated grade.
No text or logos.
No people.
The details that mattered were ordinary.
Mud on the tracks.
Equipment at rest rather than dramatically posed.
Controlled light direction.
Real material descriptions.
Those cues helped the scene feel observed rather than advertised.
I also removed people from this particular set because they were unnecessary. The purpose of the hero was the architecture and worksite atmosphere, not proving that the model could generate convincing workers.
Generated Architecture Needs an Explicit Label
This is the part I would make stricter today.
If an AI-generated house appears close to:
Recent Projects
or:
Homes We've Built
the visitor can reasonably infer that the contractor built that house.
A tiny disclosure elsewhere on the page may not fix the overall impression.
If the image is synthetic, I would position it as something like:
Illustrative visualization
or use it in a clearly conceptual context.
The actual portfolio should remain actual.
The FTC looks at both explicit and implied advertising claims when considering whether marketing is misleading.
Even outside the U.S., the principle is useful:
Do not make synthetic media do a job that requires factual evidence.
Seedance 2.5 Is Where the Build Became Interesting
The centerpiece was the construction sequence.
ByteDance officially launched Seedance 2.5 on July 31, 2026. The model extended a single generation from 15 seconds to up to 30 seconds, added multi-round extensions, synchronized audio-video generation, and expanded reference conditioning.
A single request can use up to:
30 image references;
10 video references;
10 audio references.
That gives the model as many as 50 multimodal references in one generation.
The duration change mattered more to my project than the feature list suggests.
Construction is a continuity problem.
The same building has to remain the same building while time changes around it.
And my first approach got that completely wrong.
My First Attempt: Five Clips, Five Different Houses
I originally broke the build into separate clips:
excavation;
foundation;
framing;
roof;
finished exterior.
Each clip looked good alone.
Together, they failed.
The house changed height.
The front elevation changed.
Window counts drifted.
Cladding orientation shifted.
The driveway moved.
The architectural identity disappeared between cuts.
In my test, reference images were good at holding broad style, palette, and atmosphere.
They were less reliable at preserving every countable architectural constraint across independent generations.
That distinction matters enormously for buildings.
If an AI changes the shape of one cloud between shots, nobody cares.
If it changes six windows to four, you are looking at a different house.
One Longer Generation Reduced the Continuity Problem
I abandoned the five clips and generated one longer continuous sequence.
The camera followed one site while the construction progressed inside the same generation.
The prompt separated two things:
what changes
from
what must remain constant.
Single continuous aerial shot.
No cuts.
Slow clockwise orbit.
Progression:
0–4s
Bare plot. Excavator prepares foundations.
4–8s
Foundation and slab complete.
8–13s
Timber frame rises. Roof structure appears.
13–17s
Roof closes. Glazing and charcoal cladding are installed.
17–20s
Landscaping completes. Interior lights turn on at dusk.
INVARIANTS:
Single-story contemporary house.
Flat roof.
Six front-facing windows.
Vertical charcoal timber cladding.
Same driveway position.
Same plot orientation.
Same building footprint throughout.
I would not say continuity becomes "free" inside one generation.
Seedance 2.5 can still make mistakes.
ByteDance itself says there is still room for improvement in complex physical interactions and scene stability.
But keeping the sequence inside one generation removed a major source of drift in this particular project:
the building no longer had to be independently reinvented five times.
That was the breakthrough.
Seedance 2.5 Resolution Has Changed Since My First Draft
My original notes said Seedance 2.5 on Higgsfield topped out at 720p and required a separate 4K upscale.
That is no longer a safe statement.
Higgsfield's current help documentation lists Seedance 2.5 at up to 1080p on eligible Pro and Plus plans, while Seedance 2.0 remains the version explicitly listed with generation up to 4K. Higgsfield still recommends starting at 720p while iterating because higher-resolution generations cost more.
So the workflow I would use now is:
prototype cheaply at 720p;
lock the motion and geometry;
run the final Seedance 2.5 pass at the highest appropriate supported resolution;
then upscale only if the placement genuinely needs more pixels.
Do not spend premium credits discovering that the driveway moved.
The Prompt Structure Matters More Than "Cinematic"
Seedance's current guidance recommends a structured prompt built around subject/action, setting/lighting, camera movement, and visual mood.
For architecture, I add one more block:
invariants.
The model needs to know not only what should happen, but what should not change while it happens.
For example:
Camera:
slow aerial orbit, fixed direction
Action:
construction progresses from excavation to completed exterior
Appearance:
overcast-to-golden-hour transition
Invariants:
same footprint
same number of floors
same roof geometry
same driveway
same facade materials
same window arrangement
This is useful beyond houses.
The same structure works for:
products;
vehicles;
packaging;
machinery;
interiors.
Whenever identity depends on countable geometry, write the invariants explicitly.
Turning the Construction Sequence Into a Scroll Interaction
I did not want the finished video simply playing above a section.
The interaction I wanted was:
scroll down → house gets built.
The visitor controls the progress.
That maps the interface to the story the page is telling.
The technical problem is video seeking.
A normal delivery encode may have relatively long groups of pictures between keyframes. Repeated random seeking can therefore become expensive because the decoder may need to reconstruct frames from an earlier keyframe.
For my scrubbed version, I created a denser GOP:
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
-g 5 means frequent keyframes.
That makes seeking easier.
It also increases file size.
So this is a deliberate exchange:
better scrubbing ↔ heavier video.
There is no universal GOP value that is right for every project.
Benchmark the actual asset.
Do Not Bind Every Scroll Event Directly to Video Time
My first implementation effectively treated scroll position like this:
video.currentTime = scrollProgress * video.duration;
Technically simple.
Visually rough.
Scroll events can arrive faster than the browser can comfortably seek and decode.
Instead, I let scrolling update a target and let an animation loop ease the video toward it:
let target = 0;
let current = 0;
let running = false;
function tick() {
const delta = target - current;
if (Math.abs(delta) < 0.005) {
current = target;
video.currentTime = current;
running = false;
return;
}
current += delta * 0.15;
video.currentTime = current;
requestAnimationFrame(tick);
}
function seekTo(time) {
target = time;
if (!running) {
running = true;
requestAnimationFrame(tick);
}
}
The 0.15 is not sacred.
It is the feel dial.
Too low and the build trails behind the user's scroll.
Too high and you are almost back to hard seeking.
Three Production Checks Matter More Than the Animation
First, wait for video metadata before doing duration math.
Before loadedmetadata, video.duration may not contain the usable value your scrub code expects.
Second, honor prefers-reduced-motion.
If someone has asked the operating system to reduce motion, a scroll-controlled cinematic sequence should not be the only way to consume the section.
Serve a stable alternative.
Third, test an actual mid-range phone.
Desktop Chrome on a development Mac is not your performance baseline.
On a slower mobile decoder, aggressive video seeking can turn a premium interaction into a broken one.
If the experience does not hold up, fall back to a simpler autoplay clip, static poster, or frame-based sequence rather than forcing desktop behavior onto the device.
Protect LCP Before You Fall in Love With the Video
The biggest frontend risk in this concept is not the JavaScript.
It is media weight.
A giant video near the top of the page can punish Largest Contentful Paint, bandwidth usage, and mobile responsiveness.
I would not eagerly download the full scrub asset simply because it exists near the hero.
A more defensive implementation uses:
a lightweight poster;
preload="metadata" or intentionally delayed loading;
an appropriately sized responsive asset;
lazy activation when the sequence approaches the viewport;
and a simpler mobile fallback when necessary.
The visual idea is not valuable enough to justify making the whole site feel slow.
The Figma-to-Code Workflow Has Improved Since I Built This
There is another freshness update worth including.
When I originally built this, the main Figma → Claude Code flow was:
Figma
↓
MCP reads design
↓
Claude Code implements it
The current Figma MCP can also support:
Claude Code
↓
MCP
↓
Create/update real Figma objects
including frames, components, variables, and Auto Layout when the relevant seat and permissions are available.
That makes Figma more useful as a genuine source of truth.
The developer does not necessarily have to choose between:
update code
and
go manually update the design.
The agent can participate in both sides of the loop.
I still would not let that become an excuse to skip human visual review.
Bidirectional automation makes inconsistency easier to fix.
It does not make every automatic decision correct.
What I Would Change If I Rebuilt the Site Today
The biggest change would be how I describe the role of AI imagery.
I would separate the site into three visual classes.
| Visual class | What I would use | What it is allowed to imply |
|---|---|---|
| Real proof | Actual client photos, testimonials, documented facts | "This happened." |
| AI illustration | Generated architecture and process sequences | "This is what the service/process can look like." |
| UI/design | Icons, diagrams, backgrounds, decorative visuals | No factual project claim |
That one distinction solves a surprising number of problems.
It also makes the bad driveway photos more valuable.
They are imperfect.
But they are real.
That is precisely why I would keep them.
Real Imperfection Can Increase Trust
The two phone photos that looked useless at the beginning ended up having a role.
I graded them.
Cropped them tightly.
Placed them around real customer-oriented proof rather than trying to make them hero photography.
They did not suddenly become award-winning images.
They became authentic evidence.
That creates a useful contrast.
The synthetic hero carries atmosphere.
The generated construction sequence carries explanation.
The real photos carry reality.
Those jobs should not be confused.
What I Learned About AI Video Continuity
The most reusable technical lesson from the whole project is this:
choose your generation strategy based on what is allowed to drift.
For atmosphere-heavy material, separate clips can be perfectly fine.
Clouds can move.
Dust can change.
Crowd composition can shift.
For geometry-heavy subjects, independent generations create a harder problem.
A house.
A car.
A product.
A machine.
A package with a fixed label.
Those objects are defined by features a viewer can count and compare.
When continuity matters, favor:
one longer generation;
explicit invariants;
stable reference assets;
or a controlled first-frame/last-frame continuation workflow.
Seedance 2.5 was important to this build because its 30-second generation window gave me enough room to stop slicing the core visual idea into independent clips. ByteDance explicitly positions the release around longer storytelling and improved continuity across complex sequences.
What I Would Not Automate
There are still decisions I want a person making.
I would manually verify that:
the generated house does not resemble a real project being falsely attributed to the contractor;
the materials shown are consistent with services the company actually offers;
the copy does not claim results unsupported by the business;
AI media is labeled or positioned clearly enough not to impersonate portfolio evidence;
real testimonials remain genuine;
mobile performance is acceptable;
accessibility does not depend on the animation;
and generated visuals are replaced with real project media as the client's library improves.
AI makes the production problem dramatically easier.
It does not remove the publication decision.
The Better Workflow for a Construction Website With No Usable Photography
My current workflow is simpler than the one I started with.
Start with truth.
What has this contractor actually done?
What services can you substantiate?
What real evidence exists, even if it is ugly?
Then design the information architecture in Figma.
Use AI imagery to fill presentation gaps, not factual gaps.
Generate one consistent architectural direction.
Use longer AI-video generations where continuity matters.
Build section by section through Claude Code.
Treat Figma variables, components, and layout as structured context rather than a screenshot.
Optimize the video specifically for its interaction.
Then verify the real site on mobile, with reduced motion, and under realistic network conditions.
That workflow is slower than typing:
Build me a premium construction website.
It is much faster than repairing the consequences of that prompt afterward.
FAQ
Frequently Asked Questions
Everything you need to know about this topic
Technically, yes.
But I would not use generated images as substitutes for genuine portfolio evidence. Use them as illustrative or conceptual visuals and keep real project claims tied to real evidence.
I used Nano Banana Pro through Higgsfield for architectural concept imagery. Higgsfield currently positions Nano Banana Pro as a precision-oriented image model for complex scenes, composition, perspective, lighting, and structured prompts.
I used ByteDance Seedance 2.5.
ByteDance officially launched Seedance 2.5 on July 31, 2026. It supports up to 30-second generations, synchronized audio, multi-round extension, and as many as 50 multimodal references in one generation.
Higgsfield's current help documentation lists Seedance 2.5 generation at up to 1080p for eligible plans. Seedance 2.0 is the variant explicitly listed with generation up to 4K. Higgsfield also provides separate upscale workflows.
In my tests, independent clips caused the building geometry to drift between generations. A single longer sequence reduced the number of times the house had to be independently reconstructed.
It did not guarantee perfect consistency, but it produced a substantially more coherent result for this project.
Figma's official MCP integration gives Claude Code structured access to design context including components, variables, layout information, and other file data. The current plugin can also use Code Connect mappings and supports workflows that can create or update native Figma content.
Not as a guaranteed one-to-one transformation.
Auto Layout gives the coding agent useful structural information that often maps naturally to CSS Flexbox or related layout systems, but the final implementation depends on the codebase, prompt, framework, and existing components.
If a visual could reasonably be mistaken for work the contractor actually completed, I would make the distinction explicit.
At minimum, do not place synthetic imagery in a context that creates an unsupported portfolio or performance claim. Applicable advertising and consumer-protection rules vary by jurisdiction.
The Bottom Line
The surprising part of this project was not that AI could generate an attractive construction website.
That part is becoming ordinary.
The difficult part was deciding what the AI-generated material was allowed to mean.
The first version of my thinking was:
The client has no evidence, so generate better evidence.
That is the wrong lesson.
The better one is:
Preserve real evidence. Use AI to make the story around it understandable and visually competitive.
Figma gave Claude Code a stable design target.
Nano Banana Pro filled the architectural visualization gap.
Seedance 2.5 gave me enough continuous generation time to build a construction sequence without reinventing the house at every cut.
Claude Code turned the design into an implementation.
FFmpeg and a small amount of JavaScript turned the video into an interaction.
But the two terrible driveway photos still had a job no generative model could take from them:
they were real.
That is the balance I would build around again.
If you're designing an AI-assisted website workflow where the client has weak assets, start by asking which missing things can safely be illustrated—and which missing things can only be solved by collecting better evidence.
That question will improve the site more than another model switch.
Build Better AI Design-to-Code Workflows
I build AI-assisted web, software, and agentic development workflows that connect design, generation, implementation, and production verification.
If you want to see more of that work, visit mejba.me.