@tryvitris/website-harness 1.0.1 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/agent/graph.yaml +16 -8
- package/agent/refs/browser.md +2 -0
- package/agent/refs/compose.md +2 -0
- package/agent/refs/design-quality.md +2 -0
- package/agent/refs/direction.md +2 -0
- package/agent/refs/implement.md +2 -0
- package/agent/refs/template-adaptation.md +2 -0
- package/agent/refs/template-library.md +2 -0
- package/agent/refs/typography.md +15 -0
- package/bin/api/agent/evaluate.js +7 -6
- package/bin/api/agent/grade.js +7 -6
- package/bin/api/cli/api.js +15 -14
- package/bin/api/cli.js +17 -16
- package/bin/api/engine.js +8 -7
- package/bin/api/hosting.js +9 -8
- package/bin/api/index.js +4 -3
- package/bin/api/render.js +2 -1
- package/bin/api/theme.js +2 -1
- package/bin/chunks/{chunk-JBSGJR7X.js → chunk-ATPI2YRF.js} +2 -2
- package/bin/chunks/{chunk-KIWEFRNG.js → chunk-BMD5GVUT.js} +6 -6
- package/bin/chunks/{chunk-AUO5I56E.js → chunk-C3F7XQD2.js} +194 -1
- package/bin/chunks/{chunk-UR4NWYVW.js → chunk-CPQQQ5YB.js} +3 -3
- package/bin/chunks/{chunk-LKN75JGA.js → chunk-GE6UUEG2.js} +13 -8
- package/bin/chunks/{chunk-445FZZEC.js → chunk-GM57SNLL.js} +9 -9
- package/bin/chunks/{chunk-RE4GOHSU.js → chunk-GO3XEQBA.js} +3 -3
- package/bin/chunks/{chunk-GQPUILFR.js → chunk-JPQCUN2J.js} +1301 -1252
- package/bin/chunks/{chunk-37F7XIMH.js → chunk-JTXFTNEA.js} +6 -1
- package/bin/chunks/{chunk-L44ZTNDM.js → chunk-NMTFSWPK.js} +6 -6
- package/bin/chunks/{chunk-VKU5TY5C.js → chunk-OQGUEQ6F.js} +1 -1
- package/bin/chunks/{chunk-M72KKZIB.js → chunk-Q6FLOYHS.js} +4 -3
- package/bin/chunks/{chunk-H3BS2EBR.js → chunk-QRIYA3GJ.js} +3 -3
- package/bin/chunks/chunk-S2XVNTQP.js +90 -0
- package/bin/chunks/{chunk-54QPYUM2.js → chunk-XJTAR7KM.js} +1 -1
- package/bin/chunks/{chunk-72Y4YMTV.js → chunk-YYK6367V.js} +2 -2
- package/bin/chunks/{chunk-65LRZIBP.js → chunk-YYYPSFFZ.js} +2 -2
- package/bin/chunks/{design-context-store-ETVS4N6W.js → design-context-store-BDYBQQCO.js} +7 -6
- package/bin/chunks/{packets-XFXKHSEY.js → packets-RXFWDCK2.js} +7 -6
- package/bin/chunks/{preparation-3OR7LVPQ.js → preparation-ETEEMB5H.js} +7 -6
- package/bin/cloudflare/backend.js +90 -11
- package/bin/types/src/agent/browser-typography.d.ts +33 -0
- package/bin/types/src/agent/theme-suite-identity.d.ts +1 -0
- package/bin/types/src/agent/typography-policy.d.ts +6 -0
- package/bin/types/src/compile/site.d.ts +1 -1
- package/bin/types/src/theme.d.ts +3 -1
- package/bin/types/src/types.d.ts +6 -1
- package/bin/types/src/typography.d.ts +27 -0
- package/bin/vitris-art.js +7 -6
- package/bin/vitris-build.js +5 -4
- package/bin/vitris-create-site.js +9 -8
- package/bin/vitris-cursor-hook.js +7 -6
- package/bin/vitris-eval.js +9 -8
- package/bin/vitris-go.js +9 -8
- package/bin/vitris-harvest.js +8 -7
- package/bin/vitris-knowledge.js +8 -7
- package/bin/vitris-launch-preflight.js +7 -6
- package/bin/vitris-motion-view.js +7 -6
- package/bin/vitris-references.js +5 -4
- package/bin/vitris-refresh.js +8 -7
- package/bin/vitris-stock.js +1 -1
- package/bin/vitris-templates.js +91 -1
- package/bin/vitris-themes.js +7 -6
- package/bin/vitris-upgrade.js +8 -7
- package/bin/vitris-verify-browser.js +33 -8
- package/bin/vitris-verify-performance.js +5 -4
- package/bin/vitris.js +17 -16
- package/design-system/MASTER.md +4 -0
- package/docs/CLI.md +4 -0
- package/package.json +2 -2
- package/templates/site/site.json +1 -0
- package/templates/site/theme/defaults.json +78 -17
package/bin/vitris-upgrade.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
upgradeSite
|
|
4
|
-
} from "./chunks/chunk-
|
|
4
|
+
} from "./chunks/chunk-ATPI2YRF.js";
|
|
5
5
|
import "./chunks/chunk-JCRGE6AL.js";
|
|
6
|
-
import "./chunks/chunk-
|
|
6
|
+
import "./chunks/chunk-JPQCUN2J.js";
|
|
7
7
|
import "./chunks/chunk-KVMZSQ3D.js";
|
|
8
8
|
import "./chunks/chunk-WOORR67N.js";
|
|
9
9
|
import "./chunks/chunk-PRLL7B63.js";
|
|
@@ -13,15 +13,16 @@ import "./chunks/chunk-M4LNHYYR.js";
|
|
|
13
13
|
import "./chunks/chunk-TY33XMHW.js";
|
|
14
14
|
import "./chunks/chunk-HL6JVA4A.js";
|
|
15
15
|
import "./chunks/chunk-M2ETYSVJ.js";
|
|
16
|
-
import "./chunks/chunk-
|
|
16
|
+
import "./chunks/chunk-C3F7XQD2.js";
|
|
17
17
|
import "./chunks/chunk-BIEDSEL2.js";
|
|
18
18
|
import "./chunks/chunk-IKNMBGGD.js";
|
|
19
19
|
import "./chunks/chunk-WEFDVXFX.js";
|
|
20
|
-
import "./chunks/chunk-
|
|
21
|
-
import "./chunks/chunk-
|
|
22
|
-
import "./chunks/chunk-
|
|
23
|
-
import "./chunks/chunk-
|
|
20
|
+
import "./chunks/chunk-QRIYA3GJ.js";
|
|
21
|
+
import "./chunks/chunk-NMTFSWPK.js";
|
|
22
|
+
import "./chunks/chunk-JTXFTNEA.js";
|
|
23
|
+
import "./chunks/chunk-GE6UUEG2.js";
|
|
24
24
|
import "./chunks/chunk-YYPYYOEV.js";
|
|
25
|
+
import "./chunks/chunk-S2XVNTQP.js";
|
|
25
26
|
import "./chunks/chunk-GZDLXYZV.js";
|
|
26
27
|
import "./chunks/chunk-G7MNMULR.js";
|
|
27
28
|
import "./chunks/chunk-T6PE4KN4.js";
|
|
@@ -10,8 +10,9 @@ import {
|
|
|
10
10
|
motionCompositionPolicy,
|
|
11
11
|
observeMotion,
|
|
12
12
|
templateMotionHash,
|
|
13
|
+
typographyPolicy,
|
|
13
14
|
validateTemplateMotionPlan
|
|
14
|
-
} from "./chunks/chunk-
|
|
15
|
+
} from "./chunks/chunk-JPQCUN2J.js";
|
|
15
16
|
import "./chunks/chunk-KVMZSQ3D.js";
|
|
16
17
|
import "./chunks/chunk-WOORR67N.js";
|
|
17
18
|
import "./chunks/chunk-PRLL7B63.js";
|
|
@@ -26,7 +27,12 @@ import {
|
|
|
26
27
|
hasAnalyticsRuntime,
|
|
27
28
|
productionQuality
|
|
28
29
|
} from "./chunks/chunk-M2ETYSVJ.js";
|
|
29
|
-
import
|
|
30
|
+
import {
|
|
31
|
+
TYPOGRAPHY_SCENARIO,
|
|
32
|
+
captureTypography,
|
|
33
|
+
captureTypographyStates,
|
|
34
|
+
typographyConsistencyFailures
|
|
35
|
+
} from "./chunks/chunk-C3F7XQD2.js";
|
|
30
36
|
import "./chunks/chunk-BIEDSEL2.js";
|
|
31
37
|
import {
|
|
32
38
|
measurePerformance,
|
|
@@ -37,11 +43,14 @@ import {
|
|
|
37
43
|
} from "./chunks/chunk-WEFDVXFX.js";
|
|
38
44
|
import {
|
|
39
45
|
buildVerified
|
|
40
|
-
} from "./chunks/chunk-
|
|
41
|
-
import
|
|
42
|
-
|
|
43
|
-
|
|
46
|
+
} from "./chunks/chunk-QRIYA3GJ.js";
|
|
47
|
+
import {
|
|
48
|
+
loadSitePages
|
|
49
|
+
} from "./chunks/chunk-NMTFSWPK.js";
|
|
50
|
+
import "./chunks/chunk-JTXFTNEA.js";
|
|
51
|
+
import "./chunks/chunk-GE6UUEG2.js";
|
|
44
52
|
import "./chunks/chunk-YYPYYOEV.js";
|
|
53
|
+
import "./chunks/chunk-S2XVNTQP.js";
|
|
45
54
|
import "./chunks/chunk-GZDLXYZV.js";
|
|
46
55
|
import "./chunks/chunk-G7MNMULR.js";
|
|
47
56
|
import {
|
|
@@ -340,6 +349,7 @@ var arg = (key) => {
|
|
|
340
349
|
};
|
|
341
350
|
var root = resolve(arg("--site") || ".");
|
|
342
351
|
var representative = process.argv.includes("--representative");
|
|
352
|
+
var typePolicy = typographyPolicy(root);
|
|
343
353
|
var concurrency = Number(arg("--concurrency") || process.env.VITRIS_BROWSER_CONCURRENCY || "1");
|
|
344
354
|
if (!Number.isInteger(concurrency) || concurrency < 1 || concurrency > 4) throw new Error("--concurrency must be an integer from 1 to 4");
|
|
345
355
|
var extraViewports = (arg("--extra-viewports") || "").split(",").filter(Boolean).map(Number);
|
|
@@ -373,10 +383,14 @@ var checks = [];
|
|
|
373
383
|
var routeChecks = [];
|
|
374
384
|
var compositionTargets = [];
|
|
375
385
|
var pagesToCheck = plan.pages.filter((p) => !representative || p.path === "/" || p.representative);
|
|
386
|
+
if (typePolicy.enabled && !representative) {
|
|
387
|
+
for (const page of await loadSitePages(root)) if (!pagesToCheck.some((p) => p.path === page.path)) pagesToCheck.push({ path: page.path, sections: [], purpose: "Authored route", representative: false });
|
|
388
|
+
}
|
|
376
389
|
if (!representative && existsSync(join2(dist, "cookie-compliance/index.html")) && !pagesToCheck.some((p) => p.path === "/cookie-compliance")) pagesToCheck.push({ path: "/cookie-compliance" });
|
|
377
390
|
var consentChecks = [];
|
|
378
391
|
var temporalMotion = [];
|
|
379
392
|
var routeJourneys = [];
|
|
393
|
+
var typography = [];
|
|
380
394
|
try {
|
|
381
395
|
try {
|
|
382
396
|
const chromium = await loadPlaywrightChromium();
|
|
@@ -424,6 +438,7 @@ try {
|
|
|
424
438
|
let firstVisit;
|
|
425
439
|
const cookieBanner = page.locator("#vitris-cookie-banner");
|
|
426
440
|
if (await cookieBanner.isVisible()) {
|
|
441
|
+
if (typePolicy.enabled) typography.push(await captureTypography(page, typePolicy.theme, p.path, width, "first-visit"));
|
|
427
442
|
if (p.path === "/") {
|
|
428
443
|
const path = `${directory}/first-visit-${width}${motion === "reduce" ? "" : "-normal"}.png`;
|
|
429
444
|
await page.screenshot({ path: join2(root, path) });
|
|
@@ -484,6 +499,7 @@ try {
|
|
|
484
499
|
await page.evaluate(`(async () => { await Promise.race([Promise.all([...document.images].filter(i=>i.getClientRects().length).map(i=>{i.loading='eager';return i.decode().catch(()=>{});})),new Promise(r=>setTimeout(r,5000))]); })()`);
|
|
485
500
|
const broken = await page.evaluate(`Array.from(document.images).filter(i=>i.getClientRects().length&&(!i.complete||!i.naturalWidth)).map(i=>i.getAttribute('src'))`);
|
|
486
501
|
failures.push(...broken.map((src) => `Broken tab image: ${src}`));
|
|
502
|
+
if (typePolicy.enabled) typography.push(await captureTypography(page, typePolicy.theme, p.path, width, `tab-${i}`));
|
|
487
503
|
}
|
|
488
504
|
if (await tabs.count()) await tabs.first().click();
|
|
489
505
|
for (const carousel of await page.locator('[data-island="carousel"]').all()) {
|
|
@@ -567,6 +583,7 @@ try {
|
|
|
567
583
|
const slug = p.path === "/" ? "home" : p.path.replace(/^\//, "").replace(/[^a-zA-Z0-9]+/g, "-").replace(/-+$/, "") || "home";
|
|
568
584
|
const screenshot = `${directory}/${slug}-${width}${motion === "reduce" ? "" : "-normal"}.png`;
|
|
569
585
|
await page.evaluate("window.VitrisMotion?.dispose(); window.VitrisCounters?.dispose()");
|
|
586
|
+
if (typePolicy.enabled) typography.push(...await captureTypographyStates(page, typePolicy.theme, p.path, width));
|
|
570
587
|
const unreadableMotion = await page.locator("[data-motion],[data-reveal],[data-motion-child],[data-reveal-child]").evaluateAll((es) => es.filter((e) => Number(getComputedStyle(e).opacity) < 0.99).map((e) => e.id || e.tagName));
|
|
571
588
|
if (unreadableMotion.length) failures.push(`Motion teardown left final static content hidden: ${unreadableMotion.join(", ")}`);
|
|
572
589
|
await page.evaluate("window.scrollTo(0,0)");
|
|
@@ -627,6 +644,10 @@ try {
|
|
|
627
644
|
}
|
|
628
645
|
const statusBefore = await page.locator('[role="status"]:visible').allTextContents();
|
|
629
646
|
const postsBefore = mockedLeadPosts;
|
|
647
|
+
if (typePolicy.enabled && !await form.evaluate((e) => e.checkValidity())) {
|
|
648
|
+
await form.locator("button[type=submit],input[type=submit],button:not([type])").first().click({ timeout: 3e3 });
|
|
649
|
+
typography.push(await captureTypography(page, typePolicy.theme, p.path, width, "form-invalid"));
|
|
650
|
+
}
|
|
630
651
|
let supported = true;
|
|
631
652
|
for (const field of await form.locator("input:not([type=hidden]):not([type=submit]),textarea,select").all()) {
|
|
632
653
|
const type = (await field.getAttribute("type") || "text").toLowerCase();
|
|
@@ -660,6 +681,7 @@ try {
|
|
|
660
681
|
const next = page.url();
|
|
661
682
|
const statusAfter = await page.locator('[role="status"]:visible').allTextContents();
|
|
662
683
|
const newStatus = statusAfter.some((text) => text.trim() && !statusBefore.includes(text));
|
|
684
|
+
if (typePolicy.enabled) typography.push(await captureTypography(page, typePolicy.theme, p.path, width, "form-result"));
|
|
663
685
|
if (mockedLeadPosts === postsBefore) failures.push("Lead form did not reach the mocked POST /api/leads adapter");
|
|
664
686
|
else if (!newStatus && !(new URL(next).searchParams.get("sent") && next !== before)) failures.push("Lead form has no new success state or destination");
|
|
665
687
|
} catch (error) {
|
|
@@ -680,8 +702,11 @@ try {
|
|
|
680
702
|
const compare = (a, b) => a.path.localeCompare(b.path) || a.width - b.width || String(a.motion || a.mode).localeCompare(String(b.motion || b.mode));
|
|
681
703
|
checks.sort(compare);
|
|
682
704
|
routeJourneys.sort(compare);
|
|
705
|
+
typography.sort((a, b) => compare(a, b) || a.state.localeCompare(b.state));
|
|
706
|
+
const typographyFailures = typePolicy.enabled ? [.../* @__PURE__ */ new Set([...typography.flatMap((c) => c.failures.map((f) => `${c.path} ${c.width}px ${c.state}: ${f}`)), ...typographyConsistencyFailures(typography)])] : [];
|
|
707
|
+
for (const failure of typographyFailures) console.log(`Typography: ${failure}`);
|
|
683
708
|
const templateMotion = existsSync(join2(root, TEMPLATE_MOTION_PATH)) ? await captureTemplateMotion(browser, root, `http://127.0.0.1:${address.port}/`, directory + "/template-motion", json(join2(root, TEMPLATE_MOTION_PATH))) : void 0;
|
|
684
|
-
save(join2(root, `agent/reviews/${name}.json`), { version: 4, sourceHash: sourceHash(root), distHash: fingerprint(root, ["dist"]), scope: name, concurrency, viewports, motionModes, staticMotionState: "complete-after-teardown", motionScenarioHash: MOTION_SCENARIO_HASH, temporalMotion, routeJourneys, checks, routeChecks, consentChecks, ...templateMotion ? { templateMotion } : {}, ...compositionMode ? { compositionTargets } : {} });
|
|
709
|
+
save(join2(root, `agent/reviews/${name}.json`), { version: 4, sourceHash: sourceHash(root), distHash: fingerprint(root, ["dist"]), scope: name, concurrency, viewports, motionModes, staticMotionState: "complete-after-teardown", motionScenarioHash: MOTION_SCENARIO_HASH, temporalMotion, routeJourneys, checks, routeChecks, consentChecks, ...typePolicy.enabled ? { typography: { scenario: TYPOGRAPHY_SCENARIO, captures: typography, failures: typographyFailures } } : {}, ...templateMotion ? { templateMotion } : {}, ...compositionMode ? { compositionTargets } : {} });
|
|
685
710
|
if (!representative && performancePolicy(root).enabled) {
|
|
686
711
|
const performance = await measurePerformance(root, `http://127.0.0.1:${address.port}`, { log: console.log });
|
|
687
712
|
if (performance.failures.length) {
|
|
@@ -690,7 +715,7 @@ try {
|
|
|
690
715
|
}
|
|
691
716
|
}
|
|
692
717
|
console.log(`${name}: ${checks.length} route/viewport checks`);
|
|
693
|
-
if (checks.some((c) => c.failures.length) || routeJourneys.some((j) => j.failures.length) || templateMotion?.captures.some((c) => c.failures.length)) process.exitCode = 1;
|
|
718
|
+
if (typographyFailures.length || checks.some((c) => c.failures.length) || routeJourneys.some((j) => j.failures.length) || templateMotion?.captures.some((c) => c.failures.length)) process.exitCode = 1;
|
|
694
719
|
} finally {
|
|
695
720
|
await browser?.close();
|
|
696
721
|
await new Promise((r) => server.close(() => r()));
|
|
@@ -7,11 +7,12 @@ import {
|
|
|
7
7
|
} from "./chunks/chunk-WEFDVXFX.js";
|
|
8
8
|
import {
|
|
9
9
|
buildVerified
|
|
10
|
-
} from "./chunks/chunk-
|
|
11
|
-
import "./chunks/chunk-
|
|
12
|
-
import "./chunks/chunk-
|
|
13
|
-
import "./chunks/chunk-
|
|
10
|
+
} from "./chunks/chunk-QRIYA3GJ.js";
|
|
11
|
+
import "./chunks/chunk-NMTFSWPK.js";
|
|
12
|
+
import "./chunks/chunk-JTXFTNEA.js";
|
|
13
|
+
import "./chunks/chunk-GE6UUEG2.js";
|
|
14
14
|
import "./chunks/chunk-YYPYYOEV.js";
|
|
15
|
+
import "./chunks/chunk-S2XVNTQP.js";
|
|
15
16
|
import "./chunks/chunk-GZDLXYZV.js";
|
|
16
17
|
import "./chunks/chunk-T6PE4KN4.js";
|
|
17
18
|
import "./chunks/chunk-7FS67SRF.js";
|
package/bin/vitris.js
CHANGED
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
runCli
|
|
4
|
-
} from "./chunks/chunk-
|
|
5
|
-
import "./chunks/chunk-
|
|
6
|
-
import "./chunks/chunk-
|
|
7
|
-
import "./chunks/chunk-
|
|
8
|
-
import "./chunks/chunk-
|
|
9
|
-
import "./chunks/chunk-
|
|
4
|
+
} from "./chunks/chunk-GM57SNLL.js";
|
|
5
|
+
import "./chunks/chunk-BMD5GVUT.js";
|
|
6
|
+
import "./chunks/chunk-YYK6367V.js";
|
|
7
|
+
import "./chunks/chunk-CPQQQ5YB.js";
|
|
8
|
+
import "./chunks/chunk-ATPI2YRF.js";
|
|
9
|
+
import "./chunks/chunk-Q6FLOYHS.js";
|
|
10
10
|
import "./chunks/chunk-2NW7KSPA.js";
|
|
11
|
-
import "./chunks/chunk-
|
|
12
|
-
import "./chunks/chunk-
|
|
13
|
-
import "./chunks/chunk-
|
|
11
|
+
import "./chunks/chunk-OQGUEQ6F.js";
|
|
12
|
+
import "./chunks/chunk-GO3XEQBA.js";
|
|
13
|
+
import "./chunks/chunk-YYYPSFFZ.js";
|
|
14
14
|
import "./chunks/chunk-34H54KEY.js";
|
|
15
15
|
import "./chunks/chunk-JCRGE6AL.js";
|
|
16
16
|
import "./chunks/chunk-XL2DRAYI.js";
|
|
17
|
-
import "./chunks/chunk-
|
|
17
|
+
import "./chunks/chunk-XJTAR7KM.js";
|
|
18
18
|
import "./chunks/chunk-XGTHGWPW.js";
|
|
19
|
-
import "./chunks/chunk-
|
|
19
|
+
import "./chunks/chunk-JPQCUN2J.js";
|
|
20
20
|
import "./chunks/chunk-KVMZSQ3D.js";
|
|
21
21
|
import "./chunks/chunk-WOORR67N.js";
|
|
22
22
|
import "./chunks/chunk-PRLL7B63.js";
|
|
@@ -26,15 +26,16 @@ import "./chunks/chunk-M4LNHYYR.js";
|
|
|
26
26
|
import "./chunks/chunk-TY33XMHW.js";
|
|
27
27
|
import "./chunks/chunk-HL6JVA4A.js";
|
|
28
28
|
import "./chunks/chunk-M2ETYSVJ.js";
|
|
29
|
-
import "./chunks/chunk-
|
|
29
|
+
import "./chunks/chunk-C3F7XQD2.js";
|
|
30
30
|
import "./chunks/chunk-BIEDSEL2.js";
|
|
31
31
|
import "./chunks/chunk-IKNMBGGD.js";
|
|
32
32
|
import "./chunks/chunk-WEFDVXFX.js";
|
|
33
|
-
import "./chunks/chunk-
|
|
34
|
-
import "./chunks/chunk-
|
|
35
|
-
import "./chunks/chunk-
|
|
36
|
-
import "./chunks/chunk-
|
|
33
|
+
import "./chunks/chunk-QRIYA3GJ.js";
|
|
34
|
+
import "./chunks/chunk-NMTFSWPK.js";
|
|
35
|
+
import "./chunks/chunk-JTXFTNEA.js";
|
|
36
|
+
import "./chunks/chunk-GE6UUEG2.js";
|
|
37
37
|
import "./chunks/chunk-YYPYYOEV.js";
|
|
38
|
+
import "./chunks/chunk-S2XVNTQP.js";
|
|
38
39
|
import "./chunks/chunk-GZDLXYZV.js";
|
|
39
40
|
import "./chunks/chunk-G7MNMULR.js";
|
|
40
41
|
import "./chunks/chunk-T6PE4KN4.js";
|
package/design-system/MASTER.md
CHANGED
|
@@ -74,3 +74,7 @@ New authored sites and reauthored routes compose the entire temporal journey wit
|
|
|
74
74
|
Used-component CSS only, islands only when needed. Give the actual LCP image priority when there is one; lazy-load images outside the initial view. Avoid `transition: all`.
|
|
75
75
|
|
|
76
76
|
New builds use original Vitris SVG icons through paired `<vitris-icon name="phone"></vitris-icon>` tags. Read `agent/refs/icons.md`; use `vitris-icons inspect NAME --json` for supported families and sizing. Choose by meaning, keep a coherent family and visible service labels, and verify actual desktop/mobile rendering. The compiler emits only the geometry used by each route, with no client catalog. Studio industry support is curated to eight symbols; never synthesize unavailable variants.
|
|
77
|
+
|
|
78
|
+
## Shared typography for new sites
|
|
79
|
+
|
|
80
|
+
New redesigns enable site.json typography version 1. Follow agent/refs/typography.md: shared size, weight, leading, tracking and font roles in theme/defaults.json; 18px body, 16px controls, 14px supporting text and a 12px rendered floor. Ordinary H3s share one responsive treatment across pages. Named, justified role variants preserve deliberate hierarchy. Browser acceptance checks every authored route and exposed interaction states. Historical sites retain their styles until an explicit reviewed adoption; kit upgrades never enable this automatically.
|
package/docs/CLI.md
CHANGED
|
@@ -75,6 +75,10 @@ vitris site create --dir ../acme --slug acme --from https://old-site.example --t
|
|
|
75
75
|
|
|
76
76
|
Open the new site in your coding agent and continue the prepare/work/complete loop with `npm run go` until local preview is ready. The same inputs work with `vitris-create-site` and `npm run create-site -- ...`. When the initial chat already names a template and supplies content, the agent should pass them at setup and continue the workflow without asking the user to select that template again.
|
|
77
77
|
|
|
78
|
+
New redesign sites enable `site.json.typography: {"version":1}` and ship concrete shared roles in `theme/defaults.json`. Defaults are 18px body, 16px controls/navigation, 14px supporting text and one responsive 24–32px H3 treatment. The 12px rendered minimum is a harness quality policy. See [the typography guide](../agent/refs/typography.md) for role tokens, named variants, font weights and reviewed adoption on an existing site. Existing sites and preserve-mode captures retain their current rendering; upgrading the harness does not opt them in.
|
|
79
|
+
|
|
80
|
+
For enabled sites, `npm run verify:browser -- --site .` records typography evidence in `agent/reviews/browser.json`, checks every authored route even if omitted from the storyboard, and blocks completion on undersized text or inconsistent roles. Checks cover resting text, supported disclosures/tabs and form validation/results. Refinement verification retains this policy and cannot skip browser checks. New template publication validates every original/branded route before changing the catalog. Custom widgets and text embedded in images still need visual review.
|
|
81
|
+
|
|
78
82
|
---
|
|
79
83
|
|
|
80
84
|
### `vitris run`
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tryvitris/website-harness",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.2",
|
|
4
4
|
"description": "Vitris agent harness for building and verifying customer websites, with a static compiler, media tools, and optional Cloudflare backend.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -150,7 +150,7 @@
|
|
|
150
150
|
"typecheck": "tsc --noEmit",
|
|
151
151
|
"test:admin": "node --experimental-strip-types --test src/admin-integration.test.ts",
|
|
152
152
|
"verify:admin": "node --experimental-strip-types scripts/verify-admin.ts",
|
|
153
|
-
"test": "node --experimental-strip-types --test --test-concurrency=2 src/admin-integration.test.ts src/icons.test.ts src/template-icon-migration.test.ts src/engine.test.ts src/upgrade.test.ts src/hosting.test.ts src/render.test.ts src/analytics.test.ts src/cookie-compliance.test.ts src/schema.test.ts src/patch.test.ts src/jobs.test.ts src/onboard.test.ts src/github-preview.test.ts src/agent.test.ts src/workflow.test.ts src/design-run.test.ts src/creative-profile.test.ts src/creative-efficiency.test.ts src/refine.test.ts src/refine-document-checks.test.ts src/critic-calibration.test.ts src/cli.test.ts src/jev.test.ts src/lifecycle.test.ts src/theme-lifecycle-policy.test.ts src/template-adaptation.test.ts src/adaptation-checkpoint.test.ts src/template-motion.test.ts src/template-motion-browser.test.ts src/experience-browser.test.ts src/jev-capabilities.test.ts src/jev-phase8.test.ts src/jev-prepilot.test.ts src/jev-phase0.test.ts src/jev-sept20.test.ts src/trace.test.ts src/cursor-hook.test.ts src/design-intelligence.test.ts src/design-context-integration.test.ts src/package-bin.test.ts src/knowledge-layers.test.ts src/launch-preflight.test.ts src/page-transfer.test.ts src/worker-publish.test.ts src/worker-preview.test.ts src/worker-security.test.ts src/harness-upgrades.test.ts src/stock-media.test.ts src/harness-distribution.test.ts src/storyboard-media.test.ts src/added-media.test.ts src/lead-forms.test.ts src/composition.test.ts src/reference-library.test.ts src/art-direction.test.ts src/scroll-motion.test.ts src/scroll-motion-browser.test.ts src/artistic-motion-browser.test.ts src/page-composition.test.ts src/reference-quality.test.ts src/production-quality.test.ts src/browser-focus.test.ts src/browser-work-queue.test.ts src/quality-subject.test.ts src/preview-cli.test.ts src/theme-selection.test.ts src/site-inputs.test.ts src/fieldwell.test.ts src/still-field.test.ts src/current-craft.test.ts src/copper-chair.test.ts src/clearline.test.ts src/template-cloud.test.ts src/contact-forms.test.ts src/contact-forms-operations.test.ts src/contact-forms-browser.test.ts src/preserve.test.ts src/release-safety.test.ts src/performance-media.test.ts src/lighthouse-browser.test.ts src/browser-timeout.test.ts src/browser-output-contract.test.ts src/template-motion-snapshot.test.ts",
|
|
153
|
+
"test": "node --experimental-strip-types --test --test-concurrency=2 src/admin-integration.test.ts src/icons.test.ts src/template-icon-migration.test.ts src/engine.test.ts src/upgrade.test.ts src/hosting.test.ts src/render.test.ts src/analytics.test.ts src/cookie-compliance.test.ts src/schema.test.ts src/patch.test.ts src/jobs.test.ts src/onboard.test.ts src/github-preview.test.ts src/agent.test.ts src/workflow.test.ts src/design-run.test.ts src/creative-profile.test.ts src/creative-efficiency.test.ts src/refine.test.ts src/refine-document-checks.test.ts src/critic-calibration.test.ts src/cli.test.ts src/jev.test.ts src/lifecycle.test.ts src/theme-lifecycle-policy.test.ts src/template-adaptation.test.ts src/adaptation-checkpoint.test.ts src/template-motion.test.ts src/template-motion-browser.test.ts src/experience-browser.test.ts src/jev-capabilities.test.ts src/jev-phase8.test.ts src/jev-prepilot.test.ts src/jev-phase0.test.ts src/jev-sept20.test.ts src/trace.test.ts src/cursor-hook.test.ts src/design-intelligence.test.ts src/design-context-integration.test.ts src/package-bin.test.ts src/knowledge-layers.test.ts src/launch-preflight.test.ts src/page-transfer.test.ts src/worker-publish.test.ts src/worker-preview.test.ts src/worker-security.test.ts src/harness-upgrades.test.ts src/stock-media.test.ts src/harness-distribution.test.ts src/storyboard-media.test.ts src/added-media.test.ts src/lead-forms.test.ts src/composition.test.ts src/reference-library.test.ts src/art-direction.test.ts src/scroll-motion.test.ts src/scroll-motion-browser.test.ts src/artistic-motion-browser.test.ts src/page-composition.test.ts src/reference-quality.test.ts src/production-quality.test.ts src/browser-focus.test.ts src/browser-work-queue.test.ts src/quality-subject.test.ts src/preview-cli.test.ts src/theme-selection.test.ts src/site-inputs.test.ts src/fieldwell.test.ts src/still-field.test.ts src/current-craft.test.ts src/copper-chair.test.ts src/clearline.test.ts src/template-cloud.test.ts src/contact-forms.test.ts src/contact-forms-operations.test.ts src/contact-forms-browser.test.ts src/preserve.test.ts src/release-safety.test.ts src/performance-media.test.ts src/lighthouse-browser.test.ts src/browser-timeout.test.ts src/browser-output-contract.test.ts src/template-motion-snapshot.test.ts src/typography.test.ts",
|
|
154
154
|
"eval:jev": "node --experimental-strip-types scripts/eval-jev.ts",
|
|
155
155
|
"benchmark": "node --experimental-strip-types scripts/benchmark.ts",
|
|
156
156
|
"refresh-agent": "node --experimental-strip-types scripts/refresh-agent.ts",
|
package/templates/site/site.json
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
"sourceFormatVersion": 1,
|
|
5
5
|
"capabilities": [],
|
|
6
6
|
"knowledgeRelease": "2026-09-22",
|
|
7
|
+
"typography": { "version": 1 },
|
|
7
8
|
"motion": { "strength": "off", "stagger": false },
|
|
8
9
|
"scrollMotion": { "version": 1, "policy": "enabled" },
|
|
9
10
|
"motionComposition": { "version": 2, "routes": "all-authored" }
|
|
@@ -1,17 +1,78 @@
|
|
|
1
|
-
{
|
|
2
|
-
"colorBg": "#F7F4EF",
|
|
3
|
-
"colorText": "#1A1714",
|
|
4
|
-
"colorMuted": "#5C574F",
|
|
5
|
-
"colorAccent": "#B44A2C",
|
|
6
|
-
"colorAccentText": "#FFFFFF",
|
|
7
|
-
"colorSurface": "#FFFFFF",
|
|
8
|
-
"colorSurface2": "#EFEAE3",
|
|
9
|
-
"colorBorder": "#E4DDD2",
|
|
10
|
-
"colorFocus": "#B44A2C",
|
|
11
|
-
"fontBody": "ui-sans-serif, system-ui, sans-serif",
|
|
12
|
-
"fontDisplay": "ui-serif, Georgia, serif",
|
|
13
|
-
"radius": "8px",
|
|
14
|
-
"radiusLg": "16px",
|
|
15
|
-
"radiusPill": "999px",
|
|
16
|
-
"maxWidth": "1120px"
|
|
17
|
-
|
|
1
|
+
{
|
|
2
|
+
"colorBg": "#F7F4EF",
|
|
3
|
+
"colorText": "#1A1714",
|
|
4
|
+
"colorMuted": "#5C574F",
|
|
5
|
+
"colorAccent": "#B44A2C",
|
|
6
|
+
"colorAccentText": "#FFFFFF",
|
|
7
|
+
"colorSurface": "#FFFFFF",
|
|
8
|
+
"colorSurface2": "#EFEAE3",
|
|
9
|
+
"colorBorder": "#E4DDD2",
|
|
10
|
+
"colorFocus": "#B44A2C",
|
|
11
|
+
"fontBody": "ui-sans-serif, system-ui, sans-serif",
|
|
12
|
+
"fontDisplay": "ui-serif, Georgia, serif",
|
|
13
|
+
"radius": "8px",
|
|
14
|
+
"radiusLg": "16px",
|
|
15
|
+
"radiusPill": "999px",
|
|
16
|
+
"maxWidth": "1120px",
|
|
17
|
+
"typography": {
|
|
18
|
+
"roles": {
|
|
19
|
+
"display": {
|
|
20
|
+
"size": "clamp(2.75rem, 1.8rem + 4vw, 5rem)",
|
|
21
|
+
"weight": 600,
|
|
22
|
+
"lineHeight": "1.08",
|
|
23
|
+
"tracking": "-0.03em",
|
|
24
|
+
"font": "display"
|
|
25
|
+
},
|
|
26
|
+
"section": {
|
|
27
|
+
"size": "clamp(2rem, 1.5rem + 2vw, 3.5rem)",
|
|
28
|
+
"weight": 600,
|
|
29
|
+
"lineHeight": "1.15",
|
|
30
|
+
"tracking": "-0.025em",
|
|
31
|
+
"font": "display"
|
|
32
|
+
},
|
|
33
|
+
"subheading": {
|
|
34
|
+
"size": "clamp(1.5rem, 1.3rem + 0.8vw, 2rem)",
|
|
35
|
+
"weight": 600,
|
|
36
|
+
"lineHeight": "1.25",
|
|
37
|
+
"tracking": "-0.015em",
|
|
38
|
+
"font": "display"
|
|
39
|
+
},
|
|
40
|
+
"card-title": {
|
|
41
|
+
"size": "1.5rem",
|
|
42
|
+
"weight": 600,
|
|
43
|
+
"lineHeight": "1.3",
|
|
44
|
+
"tracking": "-0.01em",
|
|
45
|
+
"font": "display"
|
|
46
|
+
},
|
|
47
|
+
"body": {
|
|
48
|
+
"size": "1.125rem",
|
|
49
|
+
"weight": 400,
|
|
50
|
+
"lineHeight": "1.6",
|
|
51
|
+
"tracking": "normal",
|
|
52
|
+
"font": "body"
|
|
53
|
+
},
|
|
54
|
+
"ui": {
|
|
55
|
+
"size": "1rem",
|
|
56
|
+
"weight": 600,
|
|
57
|
+
"lineHeight": "1.5",
|
|
58
|
+
"tracking": "normal",
|
|
59
|
+
"font": "body"
|
|
60
|
+
},
|
|
61
|
+
"caption": {
|
|
62
|
+
"size": "0.875rem",
|
|
63
|
+
"weight": 400,
|
|
64
|
+
"lineHeight": "1.5",
|
|
65
|
+
"tracking": "normal",
|
|
66
|
+
"font": "body"
|
|
67
|
+
},
|
|
68
|
+
"label": {
|
|
69
|
+
"size": "0.875rem",
|
|
70
|
+
"weight": 600,
|
|
71
|
+
"lineHeight": "1.5",
|
|
72
|
+
"tracking": "0.02em",
|
|
73
|
+
"font": "body"
|
|
74
|
+
}
|
|
75
|
+
},
|
|
76
|
+
"variants": {}
|
|
77
|
+
}
|
|
78
|
+
}
|