Skip to content

Repository files navigation

Capasight

Critical talent feasibility for Nordic enterprises.

A one-page site for the Capasight design-partner program.

Capasight is a pre-commitment talent feasibility gate. Before a technical transformation, site or capability plan is approved, it tests whether the critical roles can be supplied and attracted in the chosen market, compares hire/build/partner/relocate/redesign, records the evidence, and sets the baseline for measuring whether the chosen intervention worked.

The wedge: 10–25 business-critical AI, data, software, embedded or engineering roles, across 1–3 Nordic locations, with an executive decision due inside 90 days.

The site exists to turn that buyer into a paid design-partner conversation — without implying a product, dataset, customer or partnership that does not yet exist.

Live: https://tonyq7.github.io/capasight/

The booking CTA is currently a placeholder. Production builds normally reject placeholder URLs; the ban is temporarily suspended via ALLOW_PLACEHOLDER_BOOKING_URL. See Before public launch.

Stack

Astro, strict TypeScript, native JavaScript and bespoke CSS. No backend, forms, cookies, analytics, CMS, React or Tailwind. Fonts are self-hosted; the site makes no third-party requests until a visitor deliberately follows the booking or source link.

Quick start

Requires Node 24.

npm ci
cp .env.example .env      # then set a real PUBLIC_BOOKING_URL
npm run dev               # http://localhost:4321/capasight/
Script What it does
npm run dev Dev server at the production base path.
npm run build Verifies the evidence ledger, then builds to dist/.
npm run preview Serves the built output.
npm run check astro check — typecheck, including .astro files.
npm run lint ESLint plus the evidence gate.
npm test Playwright: smoke, keyboard, links, axe, responsive.

Configuration

PUBLIC_BOOKING_URL (required)

Every "Discuss one workforce decision" button points here. It must be a valid, absolute HTTPS scheduling URL that the founder controls, and it must not be a placeholder.

Production builds fail without it, and fail on a placeholder. That is deliberate — a launch site whose only conversion path is a dead link should not deploy. Set it locally in .env, and in CI as a repository variable (not a secret; it ships in the HTML and is public by construction):

Settings → Secrets and variables → Actions → Variables → PUBLIC_BOOKING_URL

The fit call should ask for company and role, the decision at stake, the critical roles and locations, the decision deadline, and current workforce-planning tooling — and should explicitly ask for no employee or candidate personal data.

ALLOW_PLACEHOLDER_BOOKING_URL (interim)

Set to 1 while a real scheduling page is being arranged. It suspends the placeholder ban only.

The escape hatch is deliberately loud rather than convenient: while it is set, the no production CTA is a placeholder test reports as skipped with its reason in every CI run instead of quietly passing.

To enforce, set a real PUBLIC_BOOKING_URL and delete ALLOW_PLACEHOLDER_BOOKING_URL from the repository variables, both workflows, and playwright.config.ts.

How this is put together

Everything public lives in typed config

  • src/config/copy.ts — every string the site renders, as typed records: hero, model, triggers, method, positioning, pilot, FAQ, footer.
  • src/config/claims.tsClaim records (the source ledger).
  • src/config/scenarios.tsScenario records behind the feasibility gate.
  • src/config/site.ts — identity and the booking URL. The only config module that touches import.meta.env.

That split is load-bearing: the other three are free of Astro imports, so scripts/verify-claims.mjs imports them directly under Node's type stripping and checks the real records instead of regexing source text.

The evidence gate

scripts/verify-claims.mjs runs before every build and fails it on any of:

  1. Incomplete claims — a missing field, a non-HTTPS source, a malformed or future date, a definition too short to name the population.
  2. Unsourced market claims — a percentage, money figure or multiplier in the copy with no Claim record behind it.
  3. Invented scenario counts — any digit, or a spelled-out count of roles, in an illustrative scenario. An "illustrative" label does not stop "18 roles" reading as measurement. Durations ("three quarters") are allowed; counts are not. A record may opt out only by declaring dataClass: 'user-provided-sample', meaning the figures are the customer's own.
  4. Claims that exceed reality — customers, partnerships, data rights, proof or ROI that do not exist. Checked against the copy records, so a rename cannot smuggle one past.

The rules exist because Capasight's argument is that a number without its population is not evidence. A site that shipped a bare percentage — or a fictional role count — would be arguing against itself.

The survey plate

src/lib/contours.ts models a talent market as a scalar field — overlapping employers and clusters sum into terrain — and traces iso-lines through it with marching squares. SurveyPlate.astro draws the result as a contour map with the plan's route across it, plus a cross-section comparing that route against the level the plan requires.

It all runs at build time and emits static SVG: the plates are complete with JavaScript disabled, and ship no runtime cost.

The terrain shapes are illustrative. They encode nothing measured. They exist to make the shape of a constraint legible, the way a sketch map makes a route legible without being a survey.

Progressive enhancement

Nothing load-bearing needs JavaScript. Without it the scenario tabs do not collapse, so all three plates render stacked and readable; reveal animations are skipped and content is simply present; the FAQ uses native <details>. Reduced motion is a hard stop, not a softening.

Regenerating the social card

public/og.png is committed. Its source is the unlisted /og-card route, screenshotted by a real browser because the design depends on self-hosted variable fonts and an optical-size axis, which SVG rasterisers render approximately or not at all.

npm run dev                  # in one terminal
node scripts/make-og.mjs     # in another

Deployment

Push to main. .github/workflows/deploy.yml builds and publishes to GitHub Pages via the official Pages workflow, with separate build and deploy jobs, the github-pages environment, and only contents: read, pages: write and id-token: write.

Pages must be set to GitHub Actions as its source (Settings → Pages).

.github/workflows/ci.yml runs lint, typecheck, build and the full Playwright suite on every pull request.

What this site must never say

Recorded here because it is a positioning constraint, not a preference. Most are enforced by the evidence gate; all of them are the rule regardless:

  • No customer, logo, testimonial or case study — there are none.
  • No claimed accuracy, savings, ROI, performance result or market size.
  • No proprietary dataset or integration that does not exist.
  • No attribution to Talent Venture Group, Talent Venture Studios or Universum Global, and no implication of their endorsement or of privileged data access, without written approval. Until data rights are signed, the site may say only that Capasight can use employer and talent research the customer licenses or commissions.
  • No pilot price before three real proposals have tested willingness to pay. No free pilot either.
  • Scenarios are labelled illustrative decision logic wherever they appear, and carry no counts.

Before public launch

Human decisions that no script can make:

  • Clear Capasight through PRV, Bolagsverket, EUIPO/TMview, domains, search and relevant app/company databases. If a material HR/SaaS conflict appears, stop rather than improvising another brand. (EUIPO guidance)
  • Configure the 30-minute design-partner fit call, set the real PUBLIC_BOOKING_URL, and delete ALLOW_PLACEHOLDER_BOOKING_URL from the repository variables, both workflows and playwright.config.ts.
  • Approve any future TVG / TVS / Universum attribution in writing, and resolve Universum data rights separately from marketing attribution.
  • Add the incorporated entity name to site.legalEntity once it exists; it surfaces on the privacy page automatically.
  • Re-verify the Arbetsförmedlingen claim and bump lastVerifiedAt.
  • After name clearance, connect a company-controlled custom domain. Not required for the Pages launch.

History

This repository was TonyQ7/ML-Project. Its previous contents are preserved at the tag archive/ml-project-before-capasight.

Licence

MIT. Manrope and Newsreader are used under the SIL Open Font License; their licences are in public/fonts/.

About

Critical talent feasibility for Nordic enterprises.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages