Building the agentic future of
agency management.
Production websites and custom software, engineered for clients on a platform we build ourselves.
Terminal, the Stacklumen site builder, in its light frame: one bar with the site and page, four breakpoint layers, zoom, Preview and Publish; the Insert panel of section presets; a client page on the canvas; and the inspector with its state tray and property groups. A short demo plays: the cursor opens Typography, drags the heading from 46 to 58 pixels, retypes its last words on the canvas, then walks the page through Tablet and Phone and back. Between those steps the window changes to StackIDE, the Stacklumen desktop app, with the same site open: the page opens from its folder, Claude Code tightens the heading from a terminal, the heading is rewritten and saved, and the Designer tab shows it live; another time the site is published from the sidebar and Pulse counts up the week. StackIDE comes with links to download it and to read about it.
Save any section as a component to reuse it across pages.
Designs you save from a page appear here, ready to drop in.
Select a card on the canvas to bind it to a collection.
Make repeating (12 items)Buildings that hold their light.
Homes, schools and libraries, drawn around the daylight.
See the workTwelve years, three kinds of building.
The parent is a block box, so there is nothing to set here.
The page root has no parent layout.
box-shadow: 0 8px 24px rgba(0,0,0,.12);
Declarations the groups above do not edit. One per line, applied when you click away.
{g.rows?.map((r) => ( <div class="slt-prop" data-set={r.set ? '' : undefined} data-kind={r.k}> {r.k === 'fold' ? ( <span class="slt-prop__fold"><ChevronRight />{r.l}</span> ) : ( <span class="slt-prop__l">{r.l}</span> )} {r.k === 'select' && ( <span class="slt-field slt-field--select"><span data-o={r.o}>{r.v}</span><ChevronDown />{r.tok && <Braces className="slt-tok" />}</span> )} {(r.k === 'input' || r.k === 'unit') && ( <span class="slt-field"><span data-o={r.o}>{r.v}</span>{r.unit && <u>{r.unit}</u>}{r.tok && <Braces className="slt-tok" />}</span> )} {r.k === 'swatch' && ( <span class="slt-prop__pair slt-prop__pair--swatch"> <i class="slt-sw" data-mock-swatch={r.o ? '' : undefined}></i> <span class="slt-field"><span data-o={r.o}>{r.v}</span>{r.tok && <Braces className="slt-tok" />}</span> </span> )} {r.k === 'seg' && ( <span class="slt-seg slt-seg--fill slt-seg--row"> {r.opts!.map(({t, on, icon: Ico, cls: oc}) => ( <span data-on={on ? '' : undefined} class={oc}>{Ico ? <Ico /> : oc?.includes('is-line') ? <i></i> : t}</span> ))} </span> )} {r.k === 'actions' && ( <span class="slt-prop__pair"> {r.opts!.map((o) => <span class="slt-btn">{o.t}</span>)} </span> )} {r.k === 'pair' && ( <span class="slt-prop__pair"> <span class="slt-field"><u class="slt-field__key">{r.pair![0]}</u><span data-o={r.pair![2]}>0</span></span> <span class="slt-field"><u class="slt-field__key">{r.pair![1]}</u><span data-o={r.pair![3]}>0</span></span> </span> )} {r.k === 'scale' && ( <span class="slt-field slt-field--scale"><u>⇔</u><span data-o={r.o}>0×0</span></span> )} {r.k === 'aligns' && ( <span class="slt-prop__pair slt-prop__aligns"> <span><AlignStartVertical /><AlignCenterVertical /><AlignEndVertical /></span> <span><AlignStartHorizontal /><AlignCenterHorizontal /><AlignEndHorizontal /></span> </span> )} {r.k === 'range' && ( <span class="slt-prop__pair"> <span class="slt-range"><i></i></span> <span class="slt-field"><span>{r.v}</span></span> </span> )} </div> ))}Interactions run in Preview and on the published site. On the canvas a click stays a click: it selects.
Add interactionBuildings that hold their light.
Homes, schools and libraries, drawn around the daylight.
See the workTwelve years, three kinds of building.
What you set is what ships. To the pixel.
The canvas, the preview and the published page read the same values. Size the heading, set the padding, pick an accent, then bind the cards to a collection.
Care that fits around your day.
Same-week appointments, clear prices, and a team that explains every step.
Book a visitCheckups
Cleaning, X-rays and a plan in one visit.
See details →
Whitening
In the chair or at home, priced up front.
See details →
Implants
Planned, placed and followed up here.
See details →
Inspector
h1.hero-title
listServices · 3 items
- title Text
- summary Text
- link Link
Set once on the template. Every item renders it.
Staging free · {PRICE.terminalSitesFrom}
Every site in a folder. Every agent in the terminal.
StackIDE is the Stacklumen desktop app for Mac and Windows. Each site syncs to a folder both ways. Claude Code, Codex and the other agents run in a real terminal, and in a synced site’s folder they’re already connected to the workspace. Publish is one click away in the status bar.
- Folder sync → Every site is a folder on your computer, synced both ways, with conflicts kept rather than lost.
- Terminal and agents → Claude Code, Codex, Gemini CLI and more run in a real terminal, and in a synced site’s folder they’re already connected to the workspace.
- Cloud, by application → Clone, run and preview apps on your computer; deploys open once the workspace is approved.
- One-click Publish → From the status bar, every step shown as it runs, and the address once it is live.
- Keyboard-first → ⌘K for anything, ⌘1 to ⌘9 for each section, ⌘S to save straight to the site.
One workspace behind every client. From the board to the bill.
What is late, what is unbilled, and which client it belongs to.
Overview
Last 30 days
Client work by stage, with the timer on the card.
Client work
Everything in flight, by stage
Backlog 2
Move the blog to the CMS
Lumen Dental AR
Cookie banner copy
Meridian Group JM
In progress 2
Homepage hero revision
Overdue AR
Rate calculator
1:24 running KT
In review 1
Service schema and OG tags
Northwind Logistics JM
Client approval 1
Brand palette sign-off
Meridian Group AR
Every client, and what each one has running.
Clients
Who the work is for
One plan for the agency across every app, and a plan for each site on its own domain.
Plan
One subscription for the agency
One suite, one account. Each app hands its work to the next.
Layers
body Body
section Navbar
a .cs-nav__home
nav .cs-nav__links
section Hero
div .cs-hero__copy
h1 .cs-hero__title
p .cs-hero__lede
div .cs-hero__actions
section Feature grid
h2 .cs-features__title
div .cs-features__row
div .cs-card
div .cs-card
Home · Desktop 1200px · base styles
Buildings that hold their light.
Inspectorh1
h1 cs-hero__title + class
Default Hover Focus Active
Style Interact Settings
Layout
In parent layout
Spacing
Size
Typography
Background
Overview
Sites
CRM
Projects
Clients
Billing
Plan
Overview
Last 30 days
18 Open
3 Overdue
34.5h Billable, 30 days
11.2h Not yet invoiced
Delivery Open work, and what is late
Homepage hero revision Lumen Dental 3d late
Service schema and OG tags Northwind Logistics 1d late
Intake form copy Meridian Group Due today
Spring menu photography Flames Fri
Sites
Files
pages about.html index.html journal.html work.html .mcp.json styles.css terminal.jsonpages/index.html Saves to the site as you save
~/Stacklumen/Northgate%claude
> Tighten the hero heading and add a call to action
Read(pages/index.html)
Read 23 lines
Update(pages/index.html)
Updated pages/index.html with 2 additions and 1 removal
stacklumen - get_publish_checks (MCP)
Home: nothing to fix before publishing
The heading now reads “Buildings that hold light.” and a
“Start a project” link sits beside “See the work”.
>Tighten the hero heading and add a call to action
? for shortcuts
Shapes
Text
Assets
Effects
Layers
Agents
+1 502 555 0142
Your agent over MCP · signed in
Move the logo 4 mm left and make it violet.
edit_design · move_by · set_fill Moved to 6 mm from the trim and set to #8B5CF6 — saved as one revision.
Document
SizeBusiness card · 3.5 × 2 in
Width (mm)88.9 Height (mm)50.8
Bleed (mm)3.18 StockSuper
Brand colours
Shipped. {clientCount} client sites, one case study each.
Engineered for you. Scoped and priced in writing first.
Lumen Dental
- Style
- ModernMinimalBold
- Color
- Blue Green Purple
- Project
- WebsiteWeb AppDashboard
- Timeline
- ASAP (1-2 weeks)1-3 monthsFlexible
- CMS
- No Yes
- Login
- No Yes
What's next?
Brief sentToday
First replyWithin one business day
Written proposalIn 3 business days
Web builds from Custom software from {fmt(startFloor.value)}
Continue Finish Saving... Thank you!YourVision
Step 1 of 6
Let's get to know you
Every answer is saved as you continue.
What's your style?
Tell us about your needs
Technical needs
- Custom software From $15,000 Applications, client portals and internal tools, from written scope to launch. Brief an app build →
- Web builds From $3,000 Marketing sites built in Terminal, with a CMS your team can run. Brief a new site →
Proposal in 3 business days
Everything the engagement touches. Read it before you send a brief.
- {CLIENT_WORK.map((c) => (
<li class="hm-roster-row">
<span class="hm-roster-shot">
<img src={c.img} alt="" width="1200" height="900" loading="lazy" decoding="async" />
</span>
<span class="hm-roster-name">{c.name}</span>
<span class="hm-roster-meta">{[c.sector, c.place].filter(Boolean).join(' · ')}</span>
<span class="hm-roster-go">Case study</span>
</li>
))}
- {CLIENT_WORK.map((c) => (
<li class="hm-roster-row">
<span class="hm-roster-shot">
<img src={c.img} alt="" width="1200" height="900" loading="lazy" decoding="async" />
</span>
<span class="hm-roster-name">{c.name}</span>
<span class="hm-roster-meta">{[c.sector, c.place].filter(Boolean).join(' · ')}</span>
<span class="hm-roster-go">Case study</span>
</li>
))}
Stacklumen
HubClients
Northwind — six-week build.
Week 4 of 6 · demo Friday
Discovery & scope
Shipped
Design system
Shipped Baselumen
Build & integration
In build Terminal
Review & launch
Up next Baselumen
Stages, not dates. The same board the client sees in their portal — every bar moves when the work does, and nothing is entered twice.
Friday demo, 4:00pm — recorded and shared with the client, with the week's mockups queued for approval.
Stacklumen
ProposalNot in scope.
Every proposal names what it does not cover, in writing, before anyone signs — so the answer arrives now rather than in week five.
SOC 2
Not certified. Every proposal says so in writing rather than leaving it to be assumed.
HIPAA / BAA
Not currently available. We can scope an engagement to avoid PHI; talk to us if you need a BAA.
Penetration testing
Self-tested internally; there is no third-party penetration test report yet.
DTC advertising
Calibrated for law firms, medical practices and warehousing — not direct-to-consumer.
No project is initiated, and no work is performed, without a signed proposal that supersedes anything shown here.
Northwind Logistics · proposal v2 · Sep 4, 2026
Stacklumen
TermsSections
01 Acceptance
02 Use
03 IP & content
04 Data & privacy
05 Billing
06 Warranty & liability
07 Term
08 Legal
09 Contact
Who owns what.
03.01 — Customer content
You retain all rights to the data, files, comments, and other content you submit to the products (“Customer Content”).
03.02 — Stacklumen IP & work product
For deliverables produced under a statement of work, ownership transfers to the client upon full payment as specified in that agreement, subject to Stacklumen’s retained right to use generic, non-confidential learnings and the pre-existing tools, libraries and patterns described above.
03.03 — Feedback license
Suggestions you send us may be used to improve the products, without obligation and without any claim on the result.
These terms supplement, but do not replace, a signed statement of work or other written agreement. Where a signed agreement conflicts with them, the signed agreement controls for that matter.
Last updated May 1, 2026 · v2.0
StackIDEThe desktop app for Mac and Windows
StackIDE, the Stacklumen desktop app for Mac and Windows, with the same site open. Between the designer’s steps, short demos play: the home page opens from the site’s folder while Claude Code and Codex work in Lumi, StackIDE’s window for agents, each under its own name; Lumi steps from one session to the next, Claude Code’s edit to the heading lands in the open file, and the heading is rewritten, saved and shown live in the Designer tab; then the site is published from its row in the sidebar, and Pulse counts up the week’s publishes, form submissions and agent edits.
{H1[version]}
Homes, schools and libraries, drawn around the daylight.
See the work Start a projectTwelve years, three kinds of building.
{folder}%claude
> Tighten the hero heading and add a call to action
Read(pages/index.html)
Read 23 lines
Update(pages/index.html)
Updated pages/index.html with 2 additions and 1 removal
stacklumen - get_publish_checks (MCP)
Home: nothing to fix before publishing
The heading now reads “Buildings that hold light.” and a
“Start a project” link sits beside “See the work”.
Working… (esc to interrupt)
? for shortcuts
{folder}%codex
›Add alt text to every image on the Work page
Called {hy(text).map((p) => (p === '-' ? <i class="sxi-hy">-</i> : p.trim() ? p : '\u00a0'.repeat(p.length)))}
Work: 3 images without alt text
Edited pages/work.html (+{imgLines.length} -{imgLines.length})
{imgLines.map((l, i) => ( <> <p class="sxi-tl sxi-cx__diff sxi-cx__diff--del" data-step="agents2:6"><span class="sxi-cx__no">{l.no}</span><i class="sxi-cx__sign"><i class="sxi-hy">-</i></i><span><Tight text={before(WORK_IMAGES[i])} /></span></p> <p class="sxi-tl sxi-cx__diff sxi-cx__diff--add" data-step="agents2:6"><span class="sxi-cx__no">{l.no}</span><i class="sxi-cx__sign">+</i><span><Tight text={after(WORK_IMAGES[i])} /></span></p> </> ))}Called {hy(text).map((p) => (p === '-' ? <i class="sxi-hy">-</i> : p.trim() ? p : '\u00a0'.repeat(p.length)))}
Work: nothing to fix before publishing
Added alt text to the 3 images on pages/work.html.
Working (esc to interrupt)
Start an agent
Your own coding agents, signed in with your own accounts, in a real terminal with the whole window to work in.
Pulse
All 3 sites up · checked 2m ago
SitesChecked 2m ago
Activity
Cloud
Apps built from GitHub and served by Stacklumen. Run one on this Mac, change it, ship it for review, merge it live.
Northgate portal Live Deploying
alder-finch/northgate-portal · main · astro · Northgate/portal
On this Mac~/Stacklumen/northgate-portal
Ready for review1 open into main
Deploys Live: 9e1c4a7 · 3d ago Live: 4b7e2f0 · 1m ago
{hy(text).map((p) => (p === '-' ? <i class="sxi-hy">-</i> : p.trim() ? p : '\u00a0'.repeat(p.length)))}
{hy(text).map((p) => (p === '-' ? <i class="sxi-hy">-</i> : p.trim() ? p : '\u00a0'.repeat(p.length)))}
{hy(text).map((p) => (p === '-' ? <i class="sxi-hy">-</i> : p.trim() ? p : '\u00a0'.repeat(p.length)))}
{hy(text).map((p) => (p === '-' ? <i class="sxi-hy">-</i> : p.trim() ? p : '\u00a0'.repeat(p.length)))}
{hy(text).map((p) => (p === '-' ? <i class="sxi-hy">-</i> : p.trim() ? p : '\u00a0'.repeat(p.length)))}
{hy(text).map((p) => (p === '-' ? <i class="sxi-hy">-</i> : p.trim() ? p : '\u00a0'.repeat(p.length)))}
{hy(text).map((p) => (p === '-' ? <i class="sxi-hy">-</i> : p.trim() ? p : '\u00a0'.repeat(p.length)))}
{hy(text).map((p) => (p === '-' ? <i class="sxi-hy">-</i> : p.trim() ? p : '\u00a0'.repeat(p.length)))}
Installing
npm install, the first time and whenever the lockfile changes.
Starting Astro
The page opens as soon as the dev server answers.
Your projects
Three projects in progress with Northgate.
Construction
Next: Roof inspection · updated 2h ago
Design development
Next: Planning approval · updated 1d ago
Handover
Next: Snagging walk-through · updated 3d ago
{hy(text).map((p) => (p === '-' ? <i class="sxi-hy">-</i> : p.trim() ? p : '\u00a0'.repeat(p.length)))}
{hy(text).map((p) => (p === '-' ? <i class="sxi-hy">-</i> : p.trim() ? p : '\u00a0'.repeat(p.length)))}
{hy(text).map((p) => (p === '-' ? <i class="sxi-hy">-</i> : p.trim() ? p : '\u00a0'.repeat(p.length)))}
{hy(text).map((p) => (p === '-' ? <i class="sxi-hy">-</i> : p.trim() ? p : '\u00a0'.repeat(p.length)))}
{hy(text).map((p) => (p === '-' ? <i class="sxi-hy">-</i> : p.trim() ? p : '\u00a0'.repeat(p.length)))}
{hy(text).map((p) => (p === '-' ? <i class="sxi-hy">-</i> : p.trim() ? p : '\u00a0'.repeat(p.length)))}
astro {hy(text).map((p) => (p === '-' ? <i class="sxi-hy">-</i> : p.trim() ? p : '\u00a0'.repeat(p.length)))}
{hy(text).map((p) => (p === '-' ? <i class="sxi-hy">-</i> : p.trim() ? p : '\u00a0'.repeat(p.length)))}
{hy(text).map((p) => (p === '-' ? <i class="sxi-hy">-</i> : p.trim() ? p : '\u00a0'.repeat(p.length)))}
{hy(text).map((p) => (p === '-' ? <i class="sxi-hy">-</i> : p.trim() ? p : '\u00a0'.repeat(p.length)))}
{hy(text).map((p) => (p === '-' ? <i class="sxi-hy">-</i> : p.trim() ? p : '\u00a0'.repeat(p.length)))}
{folder}%cat .mcp.json
{MCP_JSON.map((l) => <p class="sxi-tl sxi-tl--out" data-step="code:2" style={`--ind:${l.ind}`}>{breaks(l.text).map((part, i) => (i ? <><wbr />{part}</> : part))}</p>)}{folder}%
Folder syncs and publishes report here.
{lines.map((l, i) => ( <p class="sxi-log__line" data-tone="accent" data-step={`publish:${i + 1}`}> <span class="sxi-log__time">{l.at}</span> <span>{l.text.split('/').map((part, j, all) => (j < all.length - 1 ? <>{part}/<wbr /></> : part))}</span> </p> ))}{srText}
{H1[version]}
Homes, schools and libraries, drawn around the daylight.
See the work Start a projectTwelve years, three kinds of building.
{folder}%claude
> Tighten the hero heading and add a call to action
Read(pages/index.html)
Read 23 lines
Update(pages/index.html)
Updated pages/index.html with 2 additions and 1 removal
stacklumen - get_publish_checks (MCP)
Home: nothing to fix before publishing
The heading now reads “Buildings that hold light.” and a
“Start a project” link sits beside “See the work”.
Working… (esc to interrupt)
? for shortcuts
{folder}%codex
›Add alt text to every image on the Work page
Called {hy(text).map((p) => (p === '-' ? <i class="sxi-hy">-</i> : p.trim() ? p : '\u00a0'.repeat(p.length)))}
Work: 3 images without alt text
Edited pages/work.html (+{imgLines.length} -{imgLines.length})
{imgLines.map((l, i) => ( <> <p class="sxi-tl sxi-cx__diff sxi-cx__diff--del" data-step="agents2:6"><span class="sxi-cx__no">{l.no}</span><i class="sxi-cx__sign"><i class="sxi-hy">-</i></i><span><Tight text={before(WORK_IMAGES[i])} /></span></p> <p class="sxi-tl sxi-cx__diff sxi-cx__diff--add" data-step="agents2:6"><span class="sxi-cx__no">{l.no}</span><i class="sxi-cx__sign">+</i><span><Tight text={after(WORK_IMAGES[i])} /></span></p> </> ))}Called {hy(text).map((p) => (p === '-' ? <i class="sxi-hy">-</i> : p.trim() ? p : '\u00a0'.repeat(p.length)))}
Work: nothing to fix before publishing
Added alt text to the 3 images on pages/work.html.
Working (esc to interrupt)
Start an agent
Your own coding agents, signed in with your own accounts, in a real terminal with the whole window to work in.
Pulse
All 3 sites up · checked 2m ago
SitesChecked 2m ago
Activity
Cloud
Apps built from GitHub and served by Stacklumen. Run one on this Mac, change it, ship it for review, merge it live.
Northgate portal Live Deploying
alder-finch/northgate-portal · main · astro · Northgate/portal
On this Mac~/Stacklumen/northgate-portal
Ready for review1 open into main
Deploys Live: 9e1c4a7 · 3d ago Live: 4b7e2f0 · 1m ago
{hy(text).map((p) => (p === '-' ? <i class="sxi-hy">-</i> : p.trim() ? p : '\u00a0'.repeat(p.length)))}
{hy(text).map((p) => (p === '-' ? <i class="sxi-hy">-</i> : p.trim() ? p : '\u00a0'.repeat(p.length)))}
{hy(text).map((p) => (p === '-' ? <i class="sxi-hy">-</i> : p.trim() ? p : '\u00a0'.repeat(p.length)))}
{hy(text).map((p) => (p === '-' ? <i class="sxi-hy">-</i> : p.trim() ? p : '\u00a0'.repeat(p.length)))}
{hy(text).map((p) => (p === '-' ? <i class="sxi-hy">-</i> : p.trim() ? p : '\u00a0'.repeat(p.length)))}
{hy(text).map((p) => (p === '-' ? <i class="sxi-hy">-</i> : p.trim() ? p : '\u00a0'.repeat(p.length)))}
{hy(text).map((p) => (p === '-' ? <i class="sxi-hy">-</i> : p.trim() ? p : '\u00a0'.repeat(p.length)))}
{hy(text).map((p) => (p === '-' ? <i class="sxi-hy">-</i> : p.trim() ? p : '\u00a0'.repeat(p.length)))}
Installing
npm install, the first time and whenever the lockfile changes.
Starting Astro
The page opens as soon as the dev server answers.
Your projects
Three projects in progress with Northgate.
Construction
Next: Roof inspection · updated 2h ago
Design development
Next: Planning approval · updated 1d ago
Handover
Next: Snagging walk-through · updated 3d ago
{hy(text).map((p) => (p === '-' ? <i class="sxi-hy">-</i> : p.trim() ? p : '\u00a0'.repeat(p.length)))}
{hy(text).map((p) => (p === '-' ? <i class="sxi-hy">-</i> : p.trim() ? p : '\u00a0'.repeat(p.length)))}
{hy(text).map((p) => (p === '-' ? <i class="sxi-hy">-</i> : p.trim() ? p : '\u00a0'.repeat(p.length)))}
{hy(text).map((p) => (p === '-' ? <i class="sxi-hy">-</i> : p.trim() ? p : '\u00a0'.repeat(p.length)))}
{hy(text).map((p) => (p === '-' ? <i class="sxi-hy">-</i> : p.trim() ? p : '\u00a0'.repeat(p.length)))}
{hy(text).map((p) => (p === '-' ? <i class="sxi-hy">-</i> : p.trim() ? p : '\u00a0'.repeat(p.length)))}
astro {hy(text).map((p) => (p === '-' ? <i class="sxi-hy">-</i> : p.trim() ? p : '\u00a0'.repeat(p.length)))}
{hy(text).map((p) => (p === '-' ? <i class="sxi-hy">-</i> : p.trim() ? p : '\u00a0'.repeat(p.length)))}
{hy(text).map((p) => (p === '-' ? <i class="sxi-hy">-</i> : p.trim() ? p : '\u00a0'.repeat(p.length)))}
{hy(text).map((p) => (p === '-' ? <i class="sxi-hy">-</i> : p.trim() ? p : '\u00a0'.repeat(p.length)))}
{hy(text).map((p) => (p === '-' ? <i class="sxi-hy">-</i> : p.trim() ? p : '\u00a0'.repeat(p.length)))}
{folder}%cat .mcp.json
{MCP_JSON.map((l) => <p class="sxi-tl sxi-tl--out" data-step="code:2" style={`--ind:${l.ind}`}>{breaks(l.text).map((part, i) => (i ? <><wbr />{part}</> : part))}</p>)}{folder}%
Folder syncs and publishes report here.
{lines.map((l, i) => ( <p class="sxi-log__line" data-tone="accent" data-step={`publish:${i + 1}`}> <span class="sxi-log__time">{l.at}</span> <span>{l.text.split('/').map((part, j, all) => (j < all.length - 1 ? <>{part}/<wbr /></> : part))}</span> </p> ))}