Skip to content

Cowork Cost Calculator Playbook

Why this playbook exists

The /cowork-cost-calculator/ tool was rebuilt v1→v6 over one long session (18 Jun 2026, session ce18cacd) — from a broken non-Zen scaffold into a polished "meter" instrument, then extended with a credit-check widget + a /cost screenshot. Two things are easy to get wrong and expensive to rediscover: (1) the cost-model calibration (my first numbers were ~6× too low until I pinned them to Microsoft's public estimator) and (2) the Zen-template contract (a missing body class silently kills light/dark). This captures both so the next session that touches Cowork costing starts from the right place.

Read this first before touching static/js/cowork-cost-calculator.js · static/css/cowork-cost-calculator.css · layouts/cowork-cost-calculator/list.html · the Cowork pricing-spoke/hub credit copy · or any "what does Cowork cost" number on the site.


TL;DR

/cowork-cost-calculator/  (Hugo section: content/cowork-cost-calculator/_index.md + layouts/cowork-cost-calculator/list.html)
  3 tabs: Calculator · Compare & control · FAQ
  Calculator panel order:  framing line → meter card (controls left | readout right)
                           → credit-check widget (credits×runs=$) → habit strip → disclaimer
  Engine static/js/cowork-cost-calculator.js:
    compute()        main estimate  (USAGE bands × users × CREDIT_COST + seats × SEAT)
    computeCredit()  credit-check   (credits × runs × CREDIT_COST)  ← DOM-independent of compute()
    animateMeter()   count-up (tracks module-level meterCurrent + meterRAF, cancels prior frame)
  5 currencies: USD GBP EUR AUD NZD (rate table in CURRENCIES)

Default reading (50 users / Balanced): seat + meter ≈ $10,500/mo (range $7,500–$15,000). Per-user ≈ $120–410/mo across light→heavy.


🔴 The cost model — and the calibration story (most important section)

The numbers are the product. Get them wrong and the tool is worse than useless — it misleads a paying audience.

Constants (in cowork-cost-calculator.js): - CREDIT_COST = 0.01 — $0.01 per Copilot Credit (PayGo, public) - SEAT = 30$30 Microsoft 365 Copilot enterprise seat (see "$30 vs $19.99" below) - HEAVY_TASK_CREDITS = 2500 — one heavy run, used by the habit strip + credit-check default

USAGE bands — credits/user/month [low, mid, high]:

Level low mid high
Light 6,000 9,000 13,000
Balanced 15,000 21,000 30,000
Heavy 32,000 40,000 52,000

How these were calibrated (the ~6× lesson)

  • v4 and earlier were ~6× too low. I'd guessed ~20/100/400 credits per prompt. When I studied Jukka Niiranen's public cost-of-cowork.html and Microsoft's own estimator, the real per-prompt figures were ~125/500/2500 — and real users run many prompts/tasks a month.
  • The fix: stop guessing per-prompt, calibrate per-user-per-month against a public anchor. I pinned the bands so the per-user output lands in the ~$120–410/user/month envelope that Microsoft's public Customer Cowork Estimator produces (aka.ms/CustomerCoworkEstimatoradoption.microsoft.com).
  • Rule for future edits: if you change a band, re-check the per-user output still sits in that public envelope. Never widen the model on a hunch — anchor it to a public Microsoft source and say so.

$30 vs $19.99 (recurring subconscious false-flag)

The subconscious inbox keeps flagging "$19.99 M365 Premium." That's the consumer SKU. This tool targets enterprise admins → the $30 M365 Copilot seat is correct. Jukka (the licensing authority) uses $30; Sush explicitly confirmed "$30 OK" more than once. Keep $30. Ignore the $19.99 flag.


The design — "the meter", not a form

Sush's two hard notes drove the design: "less knobs, every text earns its place" and "it doesn't even look like a tool" (vs Jukka's instrument). Result:

  • One unified card: controls (users number + Light/Balanced/Heavy pills) on the left, a count-up meter readout on the right. Inputs folded INTO the card (no separate input layer).
  • Seat-vs-meter split bar — visually shows how much of the bill is the predictable seat vs the variable credit burn.
  • Verdict line ("Nx your seat") + habit strip (one run → weekly → daily → team escalation) to make the "cost is in the repeats" point.
  • Widened by dropping the right companion rail (606→972px): body.page-cowork-cost-calculator .zt-reading--tool-detail > .zt-companion { display:none } + grid 250px minmax(0,1fr) at @media(min-width:1024px). Base .zt-reading collapses to 1fr ≤1024px — clean handoff, no gap.

The credit-check widget (Sush's idea)

For people who already know a task's exact cost: credits × runs = $ (currency-aware, reads the same currency selector). computeCredit() touches a disjoint DOM set (#cc-credits, #cc-runs, #cc-cost, #cc-sub) from the main estimate — they never interfere. Default 2500×20 = $500.

The /cost integration (verified Cowork feature)

/cost is a real Cowork slash-command: type it in a task window after a task and Cowork replies e.g. "379.6 credits used for this task so far." (confirmed by Sush's own screenshot, 18 Jun 2026). This is the perfect input for the credit-check widget — run a task → /cost → exact credits → ×frequency → real monthly $. The tool's credit-check tip links to the pricing spoke "see it in action"; the spoke + hub carry the screenshot (static/images/blog/cowork/cost-command-credits.webp, 1300×282).


Zen-template contract — the gotchas that bite

  1. Body needs the zen-migrated class (added via the chain in layouts/_default/baseof.html). Miss it and the page is force-dark with a dead light/dark toggle. This was the original v1 bug.
  2. White-on-accent buttons/pills MUST use var(--accent-strong) (#4F46E5) — passes WCAG in BOTH modes. var(--accent) is #818CF8 in dark and fails contrast on the active pill (2.98:1). This was a pre-deploy review fix.
  3. No undefined tokens. v1 used --indigo-600 / --slate-50 / --amber-50 / --green-600 (don't exist) → broken colours. Use canonical Zen tokens only.
  4. No gradients/glows — solid --bg-elevated / --accent-subtle; one indigo accent.
  5. The .cowcalc-cc-tip callout uses --accent-subtle bg + var(--accent) left border — both-mode safe (verified dark: text 11:1, link 6.3:1, code 17:1).

QA traps (don't chase ghosts)

  • naturalWidth === 0 on blog images is a lazy-load artifact, not a bug. loading="lazy" images don't fetch bytes until near-viewport. To truly check decode: set img.loading='eager', scrollIntoView(), await onload, then read naturalWidth. (Live webp decodes 1300×282.)
  • Count-up mid-animation false fail. Reading #out-meter right after a pill/currency change catches the count-up at ~480ms. Wait ≥700ms before asserting, or it's a timing artifact.
  • Playwright dark-mode: the site toggles via document.documentElement.setAttribute('data-theme','dark') (see static/js/switcher.js). If you set it then click the toggle, you flip it back to light. Set the attribute and DON'T click.
  • Playwright + ESM: the QA script must live inside the repo tree (copy a temp _qa-*.mjs to repo root, run, delete) — import { chromium } won't resolve from the session-state folder.

  • Hub microsoft-copilot-cowork-complete-guide.md: > 💸 calculator callout in Licensing + /cost callout & screenshot in "What Cowork actually looks like".
  • Pricing spoke microsoft-copilot-cowork-pricing-cost-management.md: calculator link in "Who runs Cowork" + the "Know your exact per-task cost — the /cost command" section (screenshot + "make the case for your own seat" angle + credit-check link). In-page anchor id: know-your-exact-per-task-cost--the-cost-command.
  • Tool ecosystem grid + FAQ link back to the Cowork blogs; credit-check tip → pricing spoke.

Registration + deploy

  • OG image: add the slug to data/tool_colours.toml FIRST (it's the OG generator's canonical gate, NOT toolkit_nav), then node scripts/og-generator-tool/make.mjs. Icon colour comes from data/toolkit_nav.toml color (#6366F1). Output static/images/og/cowork-cost-calculator.jpg.
  • Registry: data/toolkit_nav.toml (feeds header subtitle + /free-tools + ecosystem card).
  • cache_version: bump hugo.toml on any CSS/JS change.
  • SEO gate (check-seo-lengths.ps1 -Strict): title ≤60 (currently 59), description ≤155 (148), OG ≤50KB.
  • Build: pwsh -NoProfile -File scripts\hugo-safe.ps1 (auto-runs check-blog-html.mjs when content/blog changed).
  • Deploy: Cloudflare Pages rebuilds Hugo from source on push to main. main is a separate worktree (C:\ssClawy\_atgc-main) — do NOT git checkout main. Publish from wip: git fetchgit merge origin/main (resolve layouts/blog/list.html cluster registry if it conflicts — keep all clusters) → git push origin HEAD:main. Re-fetch right before push (bots commit often). Verify live with HTTP markers + a Playwright decode check.

File map

File Role
content/cowork-cost-calculator/_index.md Frontmatter (title 59c / desc 148c) + FAQ array + images: ["images/og/cowork-cost-calculator.jpg"]
layouts/cowork-cost-calculator/list.html 3-tab layout; Calculator panel markup (meter card, credit-check widget, habit strip)
static/css/cowork-cost-calculator.css .cowcalc-* styles (meter card grid, split bar, pills, credit-check, .cowcalc-cc-tip)
static/js/cowork-cost-calculator.js compute / computeCredit / animateMeter, USAGE bands, CURRENCIES, tabs
data/tool_colours.toml OG generator canonical slug gate
data/toolkit_nav.toml tool registry
static/images/blog/cowork/cost-command-credits.webp the /cost screenshot (1300×282)

Built 18 Jun 2026, session ce18cacd. Live commit 8cf9f978.