@rubytech/create-sitedesk-code 0.1.402 → 0.1.404

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.
Files changed (59) hide show
  1. package/package.json +1 -1
  2. package/payload/platform/plugins/web-designer/skills/web-design/references/placeholders.md +19 -2
  3. package/payload/platform/plugins/web-designer/skills/web-design/templates/index.html +12 -12
  4. package/payload/platform/scripts/check-no-esm-require.mjs +3 -0
  5. package/payload/premium-plugins/sitedesk/BUNDLE.md +6 -4
  6. package/payload/premium-plugins/sitedesk/PLUGIN.md +2 -2
  7. package/payload/premium-plugins/sitedesk/agents/sitedesk--media-producer.md +18 -7
  8. package/payload/premium-plugins/sitedesk/plugins/sitedesk-media/.claude-plugin/plugin.json +1 -1
  9. package/payload/premium-plugins/sitedesk/plugins/sitedesk-media/PLUGIN.md +30 -26
  10. package/payload/premium-plugins/sitedesk/plugins/sitedesk-media/README.md +26 -36
  11. package/payload/premium-plugins/sitedesk/plugins/sitedesk-media/commands/make-media.md +2 -2
  12. package/payload/premium-plugins/sitedesk/plugins/sitedesk-media/skills/microsite/SKILL.md +52 -75
  13. package/payload/premium-plugins/sitedesk/plugins/sitedesk-media/skills/socials/SKILL.md +52 -120
  14. package/payload/premium-plugins/sitedesk/plugins/sitedesk-media/skills/socials/references/sources.md +17 -52
  15. package/payload/server/public/assets/{AdminLoginScreens-rlk263u9.js → AdminLoginScreens-BzErD9Zo.js} +1 -1
  16. package/payload/server/public/assets/AdminShell-BihejKg_.js +1 -0
  17. package/payload/server/public/assets/{Checkbox-Chz6bfy-.js → Checkbox-Ds004CBE.js} +1 -1
  18. package/payload/server/public/assets/{Transcript-Bsx-bGgY.js → Transcript-CgaMQKgY.js} +1 -1
  19. package/payload/server/public/assets/{admin-BnZH758N.js → admin-BSuRtMws.js} +1 -1
  20. package/payload/server/public/assets/{browser-CIrfyZWe.js → browser-BO2eR_YY.js} +1 -1
  21. package/payload/server/public/assets/{calendar-D6Z8Kmrn.js → calendar-12QuR_oh.js} +1 -1
  22. package/payload/server/public/assets/chat-Qpyg5t65.js +1 -0
  23. package/payload/server/public/assets/chevron-left-DBUeR2CX.js +1 -0
  24. package/payload/server/public/assets/data-Ch5bne41.js +1 -0
  25. package/payload/server/public/assets/{graph-XZJZHzvv.js → graph-CDOJZepc.js} +1 -1
  26. package/payload/server/public/assets/{graph-labels-Cabqmf35.js → graph-labels-6HKBjyXX.js} +1 -1
  27. package/payload/server/public/assets/{maximize-2-DPe-Noig.js → maximize-2-DWmyXX8h.js} +1 -1
  28. package/payload/server/public/assets/{operator-BM_CDyCb.js → operator-D-s7jVnf.js} +1 -1
  29. package/payload/server/public/assets/{page-CMIbXzSg.js → page-BcxrdxYL.js} +1 -1
  30. package/payload/server/public/assets/{page-E7I5sEVt.js → page-rDhp8G9q.js} +1 -1
  31. package/payload/server/public/assets/{public-CrdWCSk2.js → public-zK67N3z2.js} +1 -1
  32. package/payload/server/public/assets/{rotate-ccw-Dwtj0NJ7.js → rotate-ccw-BzBJxqBN.js} +1 -1
  33. package/payload/server/public/assets/useSubAccountSwitcher-B-GuP1jj.css +1 -0
  34. package/payload/server/public/browser.html +4 -4
  35. package/payload/server/public/calendar.html +5 -5
  36. package/payload/server/public/chat.html +9 -9
  37. package/payload/server/public/data.html +8 -8
  38. package/payload/server/public/graph.html +9 -9
  39. package/payload/server/public/index.html +11 -11
  40. package/payload/server/public/operator.html +11 -11
  41. package/payload/server/public/public.html +9 -9
  42. package/payload/server/server.js +32 -32
  43. package/payload/premium-plugins/sitedesk/plugins/sitedesk-media/skills/brand-extract/SKILL.md +0 -86
  44. package/payload/premium-plugins/sitedesk/plugins/sitedesk-media/skills/make-media/SKILL.md +0 -75
  45. package/payload/premium-plugins/sitedesk/plugins/sitedesk-media/skills/make-media/references/intake-and-questions.md +0 -74
  46. package/payload/premium-plugins/sitedesk/plugins/sitedesk-media/skills/microsite/references/placeholders.md +0 -96
  47. package/payload/premium-plugins/sitedesk/plugins/sitedesk-media/skills/microsite/references/sections.md +0 -48
  48. package/payload/premium-plugins/sitedesk/plugins/sitedesk-media/skills/microsite/templates/index.html +0 -1004
  49. package/payload/premium-plugins/sitedesk/plugins/sitedesk-media/skills/microsite/templates/llms.txt +0 -32
  50. package/payload/premium-plugins/sitedesk/plugins/sitedesk-media/skills/socials/references/pii-strip.md +0 -64
  51. package/payload/premium-plugins/sitedesk/plugins/sitedesk-media/skills/socials/templates/og.html +0 -92
  52. package/payload/premium-plugins/sitedesk/plugins/sitedesk-media/skills/socials/templates/social-posts.md +0 -47
  53. package/payload/premium-plugins/sitedesk/plugins/sitedesk-media/skills/socials/templates/socials.html +0 -87
  54. package/payload/server/public/assets/AdminShell-C5vWTy2n.js +0 -1
  55. package/payload/server/public/assets/chat-h7SytZHx.js +0 -1
  56. package/payload/server/public/assets/chevron-left-DSTeS1_g.js +0 -1
  57. package/payload/server/public/assets/data-CL7CyX1C.js +0 -1
  58. package/payload/server/public/assets/useSubAccountSwitcher-BH-YjP0H.css +0 -1
  59. /package/payload/server/public/assets/{useSubAccountSwitcher-BVCMAnWK.js → useSubAccountSwitcher-Bg0RH3Gk.js} +0 -0
@@ -5,20 +5,20 @@
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
6
  <title>SiteDesk</title>
7
7
  <link rel="icon" href="/favicon.ico">
8
- <script type="module" crossorigin src="/assets/admin-BnZH758N.js"></script>
8
+ <script type="module" crossorigin src="/assets/admin-BSuRtMws.js"></script>
9
9
  <link rel="modulepreload" crossorigin href="/assets/chunk-CAM3fms7.js">
10
- <link rel="modulepreload" crossorigin href="/assets/useSubAccountSwitcher-BVCMAnWK.js">
11
- <link rel="modulepreload" crossorigin href="/assets/graph-labels-Cabqmf35.js">
12
- <link rel="modulepreload" crossorigin href="/assets/AdminShell-C5vWTy2n.js">
10
+ <link rel="modulepreload" crossorigin href="/assets/useSubAccountSwitcher-Bg0RH3Gk.js">
11
+ <link rel="modulepreload" crossorigin href="/assets/graph-labels-6HKBjyXX.js">
12
+ <link rel="modulepreload" crossorigin href="/assets/AdminShell-BihejKg_.js">
13
13
  <link rel="modulepreload" crossorigin href="/assets/admin-types-hioowVct.js">
14
- <link rel="modulepreload" crossorigin href="/assets/Checkbox-Chz6bfy-.js">
15
- <link rel="modulepreload" crossorigin href="/assets/AdminLoginScreens-rlk263u9.js">
14
+ <link rel="modulepreload" crossorigin href="/assets/Checkbox-Ds004CBE.js">
15
+ <link rel="modulepreload" crossorigin href="/assets/AdminLoginScreens-BzErD9Zo.js">
16
16
  <link rel="modulepreload" crossorigin href="/assets/preload-helper-CvXuAEud.js">
17
- <link rel="modulepreload" crossorigin href="/assets/maximize-2-DPe-Noig.js">
18
- <link rel="modulepreload" crossorigin href="/assets/Transcript-Bsx-bGgY.js">
19
- <link rel="modulepreload" crossorigin href="/assets/chevron-left-DSTeS1_g.js">
20
- <link rel="modulepreload" crossorigin href="/assets/page-E7I5sEVt.js">
21
- <link rel="stylesheet" crossorigin href="/assets/useSubAccountSwitcher-BH-YjP0H.css">
17
+ <link rel="modulepreload" crossorigin href="/assets/maximize-2-DWmyXX8h.js">
18
+ <link rel="modulepreload" crossorigin href="/assets/Transcript-CgaMQKgY.js">
19
+ <link rel="modulepreload" crossorigin href="/assets/chevron-left-DBUeR2CX.js">
20
+ <link rel="modulepreload" crossorigin href="/assets/page-rDhp8G9q.js">
21
+ <link rel="stylesheet" crossorigin href="/assets/useSubAccountSwitcher-B-GuP1jj.css">
22
22
  <link rel="stylesheet" crossorigin href="/assets/AdminLoginScreens-CWMpccrR.css">
23
23
  <link rel="stylesheet" href="/brand-defaults.css">
24
24
  </head>
@@ -5,20 +5,20 @@
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
6
  <title>Operator — Maxy</title>
7
7
  <link rel="icon" href="/favicon.ico">
8
- <script type="module" crossorigin src="/assets/operator-BM_CDyCb.js"></script>
8
+ <script type="module" crossorigin src="/assets/operator-D-s7jVnf.js"></script>
9
9
  <link rel="modulepreload" crossorigin href="/assets/chunk-CAM3fms7.js">
10
- <link rel="modulepreload" crossorigin href="/assets/useSubAccountSwitcher-BVCMAnWK.js">
11
- <link rel="modulepreload" crossorigin href="/assets/AdminShell-C5vWTy2n.js">
10
+ <link rel="modulepreload" crossorigin href="/assets/useSubAccountSwitcher-Bg0RH3Gk.js">
11
+ <link rel="modulepreload" crossorigin href="/assets/AdminShell-BihejKg_.js">
12
12
  <link rel="modulepreload" crossorigin href="/assets/admin-types-hioowVct.js">
13
- <link rel="modulepreload" crossorigin href="/assets/Checkbox-Chz6bfy-.js">
14
- <link rel="modulepreload" crossorigin href="/assets/AdminLoginScreens-rlk263u9.js">
13
+ <link rel="modulepreload" crossorigin href="/assets/Checkbox-Ds004CBE.js">
14
+ <link rel="modulepreload" crossorigin href="/assets/AdminLoginScreens-BzErD9Zo.js">
15
15
  <link rel="modulepreload" crossorigin href="/assets/preload-helper-CvXuAEud.js">
16
- <link rel="modulepreload" crossorigin href="/assets/maximize-2-DPe-Noig.js">
17
- <link rel="modulepreload" crossorigin href="/assets/Transcript-Bsx-bGgY.js">
18
- <link rel="modulepreload" crossorigin href="/assets/chevron-left-DSTeS1_g.js">
19
- <link rel="modulepreload" crossorigin href="/assets/rotate-ccw-Dwtj0NJ7.js">
20
- <link rel="modulepreload" crossorigin href="/assets/page-CMIbXzSg.js">
21
- <link rel="stylesheet" crossorigin href="/assets/useSubAccountSwitcher-BH-YjP0H.css">
16
+ <link rel="modulepreload" crossorigin href="/assets/maximize-2-DWmyXX8h.js">
17
+ <link rel="modulepreload" crossorigin href="/assets/Transcript-CgaMQKgY.js">
18
+ <link rel="modulepreload" crossorigin href="/assets/chevron-left-DBUeR2CX.js">
19
+ <link rel="modulepreload" crossorigin href="/assets/rotate-ccw-BzBJxqBN.js">
20
+ <link rel="modulepreload" crossorigin href="/assets/page-BcxrdxYL.js">
21
+ <link rel="stylesheet" crossorigin href="/assets/useSubAccountSwitcher-B-GuP1jj.css">
22
22
  <link rel="stylesheet" crossorigin href="/assets/AdminLoginScreens-CWMpccrR.css">
23
23
  <link rel="stylesheet" href="/brand-defaults.css">
24
24
  </head>
@@ -5,18 +5,18 @@
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
6
  <title>SiteDesk</title>
7
7
  <link rel="icon" href="/favicon.ico">
8
- <script type="module" crossorigin src="/assets/public-CrdWCSk2.js"></script>
8
+ <script type="module" crossorigin src="/assets/public-zK67N3z2.js"></script>
9
9
  <link rel="modulepreload" crossorigin href="/assets/chunk-CAM3fms7.js">
10
- <link rel="modulepreload" crossorigin href="/assets/useSubAccountSwitcher-BVCMAnWK.js">
11
- <link rel="modulepreload" crossorigin href="/assets/AdminShell-C5vWTy2n.js">
10
+ <link rel="modulepreload" crossorigin href="/assets/useSubAccountSwitcher-Bg0RH3Gk.js">
11
+ <link rel="modulepreload" crossorigin href="/assets/AdminShell-BihejKg_.js">
12
12
  <link rel="modulepreload" crossorigin href="/assets/admin-types-hioowVct.js">
13
13
  <link rel="modulepreload" crossorigin href="/assets/preload-helper-CvXuAEud.js">
14
- <link rel="modulepreload" crossorigin href="/assets/maximize-2-DPe-Noig.js">
15
- <link rel="modulepreload" crossorigin href="/assets/Transcript-Bsx-bGgY.js">
16
- <link rel="modulepreload" crossorigin href="/assets/chevron-left-DSTeS1_g.js">
17
- <link rel="modulepreload" crossorigin href="/assets/rotate-ccw-Dwtj0NJ7.js">
18
- <link rel="modulepreload" crossorigin href="/assets/page-CMIbXzSg.js">
19
- <link rel="stylesheet" crossorigin href="/assets/useSubAccountSwitcher-BH-YjP0H.css">
14
+ <link rel="modulepreload" crossorigin href="/assets/maximize-2-DWmyXX8h.js">
15
+ <link rel="modulepreload" crossorigin href="/assets/Transcript-CgaMQKgY.js">
16
+ <link rel="modulepreload" crossorigin href="/assets/chevron-left-DBUeR2CX.js">
17
+ <link rel="modulepreload" crossorigin href="/assets/rotate-ccw-BzBJxqBN.js">
18
+ <link rel="modulepreload" crossorigin href="/assets/page-BcxrdxYL.js">
19
+ <link rel="stylesheet" crossorigin href="/assets/useSubAccountSwitcher-B-GuP1jj.css">
20
20
  <link rel="stylesheet" href="/brand-defaults.css">
21
21
  </head>
22
22
  <body class="public-surface">
@@ -1417,7 +1417,7 @@ function webchatChannelDescriptor(key) {
1417
1417
  }
1418
1418
 
1419
1419
  // app/lib/claude-auth.ts
1420
- import { readFileSync, writeFileSync } from "fs";
1420
+ import { readFileSync, writeFileSync, renameSync, unlinkSync } from "fs";
1421
1421
  import { sep } from "path";
1422
1422
  import { lock } from "proper-lockfile";
1423
1423
  if (!CLAUDE_CREDENTIALS_FILE.startsWith(MAXY_DIR + sep)) {
@@ -1473,7 +1473,17 @@ function writeOAuthCredentials(tokens) {
1473
1473
  ...tokens.refreshToken != null ? { refreshToken: tokens.refreshToken } : {},
1474
1474
  expiresAt: newExpiresAt
1475
1475
  };
1476
- writeFileSync(CLAUDE_CREDENTIALS_FILE, JSON.stringify(fileData, null, 2), "utf-8");
1476
+ const tmpPath = `${CLAUDE_CREDENTIALS_FILE}.${process.pid}.tmp`;
1477
+ try {
1478
+ writeFileSync(tmpPath, JSON.stringify(fileData, null, 2), "utf-8");
1479
+ renameSync(tmpPath, CLAUDE_CREDENTIALS_FILE);
1480
+ } catch (writeErr) {
1481
+ try {
1482
+ unlinkSync(tmpPath);
1483
+ } catch {
1484
+ }
1485
+ throw writeErr;
1486
+ }
1477
1487
  return newExpiresAt;
1478
1488
  } catch (err) {
1479
1489
  console.error(`[claude-auth] credential write failed: ${err instanceof Error ? err.message : String(err)}`);
@@ -9259,10 +9269,10 @@ var public_reader_default = app5;
9259
9269
  // server/routes/webchat.ts
9260
9270
  import { basename as basename7, dirname as dirname6 } from "path";
9261
9271
  import { join as join18 } from "path";
9262
- import { existsSync as existsSync10, readdirSync as readdirSync11, readFileSync as readFileSync19, renameSync as renameSync3, statSync as statSync7, writeFileSync as writeFileSync7 } from "fs";
9272
+ import { existsSync as existsSync10, readdirSync as readdirSync11, readFileSync as readFileSync19, renameSync as renameSync4, statSync as statSync7, writeFileSync as writeFileSync7 } from "fs";
9263
9273
 
9264
9274
  // server/canonical-webchat-override.ts
9265
- import { readFileSync as readFileSync17, writeFileSync as writeFileSync5, renameSync } from "fs";
9275
+ import { readFileSync as readFileSync17, writeFileSync as writeFileSync5, renameSync as renameSync2 } from "fs";
9266
9276
  import { join as join16 } from "path";
9267
9277
  var FILE = "canonical-webchat-session.json";
9268
9278
  var UUID = /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/;
@@ -9300,7 +9310,7 @@ function writeCanonicalOverrideId(accountDir, userId, sessionId) {
9300
9310
  const path2 = canonicalOverridePath(accountDir);
9301
9311
  const tmp = `${path2}.${process.pid}.tmp`;
9302
9312
  writeFileSync5(tmp, JSON.stringify({ byAdmin }, null, 2), "utf8");
9303
- renameSync(tmp, path2);
9313
+ renameSync2(tmp, path2);
9304
9314
  }
9305
9315
 
9306
9316
  // ../lib/models/src/index.ts
@@ -9346,7 +9356,7 @@ function isNewSessionEffortLevel(value) {
9346
9356
  }
9347
9357
 
9348
9358
  // ../services/claude-session-manager/src/sidecar-store.ts
9349
- import { existsSync as existsSync9, mkdirSync as mkdirSync3, readdirSync as readdirSync10, readFileSync as readFileSync18, renameSync as renameSync2, unlinkSync, writeFileSync as writeFileSync6 } from "fs";
9359
+ import { existsSync as existsSync9, mkdirSync as mkdirSync3, readdirSync as readdirSync10, readFileSync as readFileSync18, renameSync as renameSync3, unlinkSync as unlinkSync2, writeFileSync as writeFileSync6 } from "fs";
9350
9360
  import { join as join17 } from "path";
9351
9361
  function escapeRegExp(s) {
9352
9362
  return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
@@ -9363,11 +9373,11 @@ function createSidecarStore(config) {
9363
9373
  const tmp = `${path2}.tmp.${process.pid}`;
9364
9374
  try {
9365
9375
  writeFileSync6(tmp, JSON.stringify(record), "utf8");
9366
- renameSync2(tmp, path2);
9376
+ renameSync3(tmp, path2);
9367
9377
  return { ok: true };
9368
9378
  } catch (error) {
9369
9379
  try {
9370
- if (existsSync9(tmp)) unlinkSync(tmp);
9380
+ if (existsSync9(tmp)) unlinkSync2(tmp);
9371
9381
  } catch {
9372
9382
  }
9373
9383
  return { ok: false, error };
@@ -9424,7 +9434,7 @@ function createSidecarStore(config) {
9424
9434
  const path2 = pathFor(sessionsDir, id);
9425
9435
  try {
9426
9436
  if (existsSync9(path2)) {
9427
- unlinkSync(path2);
9437
+ unlinkSync2(path2);
9428
9438
  return { ok: true, removed: true };
9429
9439
  }
9430
9440
  return { ok: true, removed: false };
@@ -9974,7 +9984,7 @@ ${note}` : note;
9974
9984
  else parsed.adminPermissionMode = value;
9975
9985
  const tmp = `${accountJsonPath}.${process.pid}.tmp`;
9976
9986
  writeFileSync7(tmp, JSON.stringify(parsed, null, 2), "utf8");
9977
- renameSync3(tmp, accountJsonPath);
9987
+ renameSync4(tmp, accountJsonPath);
9978
9988
  } catch (err) {
9979
9989
  const detail = err instanceof Error ? err.message : String(err);
9980
9990
  console.error(`[webchat:settings] op=${op} outcome=refused value=${value} reason=write-failed detail=${detail}`);
@@ -10373,7 +10383,7 @@ var telegram_default = app7;
10373
10383
 
10374
10384
  // server/routes/quickbooks.ts
10375
10385
  import { join as join21 } from "path";
10376
- import { existsSync as existsSync13, readFileSync as readFileSync22, writeFileSync as writeFileSync8, mkdirSync as mkdirSync4, rmSync, renameSync as renameSync4 } from "fs";
10386
+ import { existsSync as existsSync13, readFileSync as readFileSync22, writeFileSync as writeFileSync8, mkdirSync as mkdirSync4, rmSync, renameSync as renameSync5 } from "fs";
10377
10387
  var TAG24 = "[quickbooks]";
10378
10388
  var INTUIT_TOKEN_URL = "https://oauth.platform.intuit.com/oauth2/v1/tokens/bearer";
10379
10389
  var STATE_RE = /^[A-Za-z0-9_-]+$/;
@@ -10392,7 +10402,7 @@ async function completeConsent(args) {
10392
10402
  }
10393
10403
  const claimFile = `${pendingPath(accountDir, state)}.claimed`;
10394
10404
  try {
10395
- renameSync4(pendingPath(accountDir, state), claimFile);
10405
+ renameSync5(pendingPath(accountDir, state), claimFile);
10396
10406
  } catch {
10397
10407
  console.error(`${TAG24} op=callback state=${state} stateValid=false realmId=${realmId ?? ""}`);
10398
10408
  return { ok: false, status: 400, message: "Invalid or unknown authorization state.", stateValid: false };
@@ -10481,20 +10491,10 @@ var quickbooks_default = app8;
10481
10491
 
10482
10492
  // server/routes/onboarding.ts
10483
10493
  import { spawn, spawnSync as spawnSync2, execFileSync as execFileSync3 } from "child_process";
10484
- import { openSync as openSync3, closeSync as closeSync3, writeFileSync as writeFileSync10, writeSync, existsSync as existsSync15, readFileSync as readFileSync24, unlinkSync as unlinkSync2, renameSync as renameSync6 } from "fs";
10494
+ import { openSync as openSync3, closeSync as closeSync3, writeFileSync as writeFileSync10, writeSync, existsSync as existsSync15, readFileSync as readFileSync24, unlinkSync as unlinkSync3, renameSync as renameSync7 } from "fs";
10485
10495
  import { createHash as createHash3, randomUUID as randomUUID7 } from "crypto";
10486
10496
 
10487
10497
  // app/lib/claude-spawn-env.ts
10488
- var HOST_AUTH_REFRESH_TIMEOUT_MS = "30000";
10489
- function hostCredsEnv(platform, credsFile) {
10490
- if (platform === "darwin" && credsFile) {
10491
- return {
10492
- CLAUDE_CODE_HOST_CREDS_FILE: credsFile,
10493
- CLAUDE_CODE_HOST_AUTH_REFRESH_TIMEOUT_MS: HOST_AUTH_REFRESH_TIMEOUT_MS
10494
- };
10495
- }
10496
- return {};
10497
- }
10498
10498
  function claudeBin() {
10499
10499
  return process.env.CLAUDE_BIN ?? "claude";
10500
10500
  }
@@ -10586,7 +10586,7 @@ function readHostCredsBlob(service) {
10586
10586
  }
10587
10587
 
10588
10588
  // ../lib/admins-write/src/index.ts
10589
- import { existsSync as existsSync14, readFileSync as readFileSync23, writeFileSync as writeFileSync9, renameSync as renameSync5, mkdirSync as mkdirSync5, readdirSync as readdirSync13, statSync as statSync8, appendFileSync as appendFileSync2 } from "fs";
10589
+ import { existsSync as existsSync14, readFileSync as readFileSync23, writeFileSync as writeFileSync9, renameSync as renameSync6, mkdirSync as mkdirSync5, readdirSync as readdirSync13, statSync as statSync8, appendFileSync as appendFileSync2 } from "fs";
10590
10590
  import { dirname as dirname7, join as join22 } from "path";
10591
10591
  function id8(value) {
10592
10592
  return value.slice(0, 8);
@@ -10621,7 +10621,7 @@ function writeFileAtomic(filePath, contents, mode) {
10621
10621
  mkdirSync5(dirname7(filePath), { recursive: true });
10622
10622
  const tempPath = `${filePath}.tmp-${process.pid}-${Date.now()}`;
10623
10623
  writeFileSync9(tempPath, contents, mode !== void 0 ? { mode } : void 0);
10624
- renameSync5(tempPath, filePath);
10624
+ renameSync6(tempPath, filePath);
10625
10625
  }
10626
10626
  function writeAdminEntry(input) {
10627
10627
  const result = { usersJsonResult: "noop", accountJsonResult: "noop" };
@@ -10818,7 +10818,7 @@ app9.post("/claude-auth", async (c) => {
10818
10818
  let logoutError = null;
10819
10819
  try {
10820
10820
  execFileSync3(claudeBin(), ["auth", "logout"], {
10821
- env: { ...process.env, ...hostCredsEnv(process.platform, CLAUDE_CREDENTIALS_FILE) },
10821
+ env: { ...process.env },
10822
10822
  encoding: "utf-8",
10823
10823
  timeout: 8e3
10824
10824
  });
@@ -10866,7 +10866,7 @@ app9.post("/claude-auth", async (c) => {
10866
10866
  vncLog("claude-auth", { action: "start", transport: "native", platform: "darwin" });
10867
10867
  darwinCredsBefore = listHostCredsMdats();
10868
10868
  const claudeProc2 = spawn(claudeBin(), ["auth", "login"], {
10869
- env: { ...process.env, ...hostCredsEnv(process.platform, CLAUDE_CREDENTIALS_FILE) },
10869
+ env: { ...process.env },
10870
10870
  stdio: ["pipe", "pipe", "pipe"]
10871
10871
  });
10872
10872
  claudeProc2.unref();
@@ -10885,7 +10885,7 @@ app9.post("/claude-auth", async (c) => {
10885
10885
  writeFile: (blob) => {
10886
10886
  const tmp = `${CLAUDE_CREDENTIALS_FILE}.${process.pid}.tmp`;
10887
10887
  writeFileSync10(tmp, blob, { mode: 384 });
10888
- renameSync6(tmp, CLAUDE_CREDENTIALS_FILE);
10888
+ renameSync7(tmp, CLAUDE_CREDENTIALS_FILE);
10889
10889
  },
10890
10890
  log: (line) => console.log(line)
10891
10891
  });
@@ -11049,7 +11049,7 @@ app9.delete("/set-pin", requireAdminSession, async (c) => {
11049
11049
  }
11050
11050
  const remaining = users.filter((u) => u.userId !== sessionUserId);
11051
11051
  if (remaining.length === 0) {
11052
- unlinkSync2(USERS_FILE);
11052
+ unlinkSync3(USERS_FILE);
11053
11053
  console.log(`[set-pin] cleared users.json (last entry removed): userId=${sessionUserId.slice(0, 8)}\u2026`);
11054
11054
  } else {
11055
11055
  writeFileSync10(USERS_FILE, JSON.stringify(remaining), { mode: 384 });
@@ -11151,7 +11151,7 @@ ${body.newPin}
11151
11151
  var onboarding_default = app9;
11152
11152
 
11153
11153
  // server/routes/client-error.ts
11154
- import { appendFileSync as appendFileSync3, existsSync as existsSync16, renameSync as renameSync7, statSync as statSync9 } from "fs";
11154
+ import { appendFileSync as appendFileSync3, existsSync as existsSync16, renameSync as renameSync8, statSync as statSync9 } from "fs";
11155
11155
  import { join as join23 } from "path";
11156
11156
  var CLIENT_ERRORS_LOG = join23(LOG_DIR, "client-errors.log");
11157
11157
  var MAX_LOG_SIZE = 10 * 1024 * 1024;
@@ -11204,7 +11204,7 @@ function rotateIfNeeded() {
11204
11204
  if (!existsSync16(CLIENT_ERRORS_LOG)) return;
11205
11205
  const stats = statSync9(CLIENT_ERRORS_LOG);
11206
11206
  if (stats.size < MAX_LOG_SIZE) return;
11207
- renameSync7(CLIENT_ERRORS_LOG, CLIENT_ERRORS_LOG + ".1");
11207
+ renameSync8(CLIENT_ERRORS_LOG, CLIENT_ERRORS_LOG + ".1");
11208
11208
  } catch (err) {
11209
11209
  console.error(`[client-error] log rotation failed: ${err instanceof Error ? err.message : String(err)}`);
11210
11210
  }
@@ -11684,7 +11684,7 @@ var logs_default = app13;
11684
11684
  import { execFileSync as execFileSync4 } from "child_process";
11685
11685
  var app14 = new Hono();
11686
11686
  app14.get("/", (c) => {
11687
- const claudeEnv = { ...process.env, ...hostCredsEnv(process.platform, CLAUDE_CREDENTIALS_FILE) };
11687
+ const claudeEnv = { ...process.env };
11688
11688
  let version = "unknown";
11689
11689
  try {
11690
11690
  const raw = execFileSync4(claudeBin(), ["--version"], { env: claudeEnv, encoding: "utf-8", timeout: 5e3 });
@@ -1,86 +0,0 @@
1
- ---
2
- name: brand-extract
3
- description: Turn a business's existing website into a brand pack for the micro-site — a tokenized palette (ink/paper/rule/accent plus a deepened accent for legible text), the logo and icon saved as image files, and a brand.md recording the company facts the site exposes (name, contact, services, about copy, socials) together with an explicit list of what is still unknown. Use as the first step of make-media, or on its own when someone wants design tokens + logo + company facts pulled from a URL. Trigger phrases include "extract the brand from <url>", "get tokens and logo from <site>", "pull the company details from their website".
4
- allowed-tools:
5
- - Bash
6
- - Read
7
- - Write
8
- - WebFetch
9
- - Grep
10
- ---
11
-
12
- # brand-extract
13
-
14
- Reads an existing website and produces what the `microsite` and `socials`
15
- templates need to be branded: a **palette**, the **logo** and **icon** as files,
16
- and a **brand.md** of company facts with an honest "still unknown" list.
17
-
18
- ## Outputs
19
-
20
- ```
21
- <output>/site/images/logo.png # the wordmark/lockup, on a white or transparent ground
22
- <output>/site/images/icon.png # the square mark / monogram (favicon source)
23
- <output>/site/favicon.png # 64px icon
24
- <output>/brand.md # tokens + facts found + gaps
25
- ```
26
-
27
- ## Palette — the token contract
28
-
29
- The templates resolve every colour through ten CSS custom properties. Fill their
30
- values from the site; do not introduce new token names.
31
-
32
- | Token | Role | How to choose |
33
- |---|---|---|
34
- | `INK_900` | primary text, headings, dark surfaces | the site's darkest near-black text colour |
35
- | `INK_700` | secondary text | a step lighter than INK_900 |
36
- | `INK_400` | muted / captions | a mid grey |
37
- | `PAPER_100` | white surface | the lightest surface (usually `#FFFFFF`) |
38
- | `PAPER_200` | page-bg tint / bands | a faint off-white for alternating bands |
39
- | `RULE_100` | borders / dividers | a pale neutral hairline |
40
- | `ACCENT` | the brand accent (separators, hairlines, CTA hover) | the logo's accent colour, used verbatim |
41
- | `ACCENT_TEXT` | accent used as small text (eyebrows, links) | the accent **deepened** until it is legible at ~10px on white (aim for ≥ 3:1 contrast). This is the one token you compute rather than copy — a light brand accent is unreadable as tracked-caps text, so darken it while keeping the same hue. |
42
- | `ACCENT_SOFT` | soft tint behind accent text | a pale wash of the accent |
43
- | `BRAND_GREY` | logo/wordmark grey | the logo's neutral grey |
44
-
45
- If the operator supplied design tokens directly, use them verbatim and skip
46
- derivation. The three-font editorial system (Cormorant Garamond display, Lora
47
- body, Inter UI) is the template default and stays unless the operator asks to
48
- change it — brand identity lives in the logo, the accent, and the copy.
49
-
50
- ## Logo — make it usable on dark and light
51
-
52
- Save the site's primary logo as `images/logo.png`. Note its background: a logo on
53
- a **white ground** sits cleanly on a light nav but cannot be dropped onto a dark
54
- photo. The `socials` tiles place the logo on a white chip precisely so a
55
- white-ground logo still reads over any hero. Record in brand.md whether a
56
- transparent or light-art variant exists. Save the square mark as `images/icon.png`
57
- and a 64px `favicon.png`.
58
-
59
- Right-size the logo (a multi-megabyte original is overkill for a 42–84px display);
60
- keep it crisp but reasonable.
61
-
62
- ## Facts — record, and mark the gaps
63
-
64
- Write `brand.md` with everything the site exposes: trading name, legal name,
65
- tagline, sector, established year, phone, email, address, region, services,
66
- "about" copy, social links. For every field the site does **not** expose, write
67
- it under a `## Still unknown` heading. That list is exactly what `make-media`
68
- turns into questions for the operator.
69
-
70
- Do not promote a marketing line to a hard fact. "Over 35 years" is a claim about
71
- experience, not a company age; "since 1987" is a trading date, not necessarily an
72
- incorporation date. Keep claims as claims.
73
-
74
- ## The 2000px image rule
75
-
76
- Never `Read` an image whose longest edge exceeds 2000px — it can break the
77
- session. Measure first (`sips -g pixelWidth -g pixelHeight`), and if larger,
78
- downscale a preview into `/tmp`, read that, and delete it.
79
-
80
- ## Completion criteria
81
-
82
- - `images/logo.png`, `images/icon.png`, `favicon.png` exist and are right-sized.
83
- - `brand.md` lists the ten palette tokens with values, the company facts found,
84
- and an explicit "Still unknown" list.
85
- - No colour was invented beyond deriving `ACCENT_TEXT` from `ACCENT`; no marketing
86
- claim was recorded as a registration fact.
@@ -1,75 +0,0 @@
1
- ---
2
- name: make-media
3
- description: Single-entry orchestrator that turns an operator's raw inputs — a folder or zip of photos, an existing website URL, social-media links, and any free-text notes about the business — into a finished marketing micro-site plus a set of share-ready social tiles. Use whenever the deliverable is "a website and social images for this business" from mixed source material. Routes to brand-extract → microsite → socials, and asks the operator targeted questions to fill every field the sources do not supply. Trigger phrases include "make a site for this business", "build a microsite from these photos and their website", "turn this into a landing page and social tiles", "sitedesk media for <business>".
4
- allowed-tools:
5
- - Bash
6
- - Read
7
- - Write
8
- - Edit
9
- - Glob
10
- - Grep
11
- - WebFetch
12
- - Skill
13
- - AskUserQuestion
14
- ---
15
-
16
- # make-media
17
-
18
- Orchestrates the `brand-extract → microsite → socials` pipeline. The deliverable is a self-contained `site/` directory (a scrollable single-page micro-site, an `llms.txt`, and a `socials/` folder of Open Graph + social tiles with a gallery and captions) plus a zipped copy, built from whatever the operator provides and whatever the orchestrator has to ask for.
19
-
20
- This skill is a playbook, not a programmatic dispatcher. It tells you the routing and the gap-filling contract; you execute each step under the underlying skills' own contracts.
21
-
22
- ## What the operator gives, and what you do with it
23
-
24
- | Operator supplies | Used for | If missing |
25
- |---|---|---|
26
- | **Images** (folder or zip of photos) | hero rotator, photo grids, founder portrait, testimonial, social tiles | required — the site is image-led. If none, stop and ask. |
27
- | **Website URL** | brand tokens (palette, accent), logo, company name, contact, services, "about" copy | run `brand-extract`; anything it cannot read becomes a question |
28
- | **Social links** (Facebook / Instagram / TikTok / LinkedIn) | footer + drawer links, social handles, extra copy/ideas in the operator's own voice | login-walled platforms usually cannot be scraped — say so plainly and ask the operator to paste any posts they want used |
29
- | **Free-text notes / pasted posts / quotes** | founder section, testimonials, "from the site" updates, service descriptions, taglines | use verbatim where the operator marks a quote; never reword a real client testimonial into marketing prose |
30
- | **Design tokens** (if supplied directly) | the palette `:root` — use them verbatim, do not re-pick | if absent, `brand-extract` derives them from the site |
31
-
32
- ## The core rule: ask, never invent
33
-
34
- Every `{{ PLACEHOLDER }}` in the templates is a fact about a real business. The brand and the operator's notes fill most of them. **For every placeholder still unfilled after `brand-extract`, ask the operator — do not synthesise a plausible value.** A fabricated phone number, a guessed founding year, an invented testimonial, or a made-up company number is a defect, not a convenience. The reference list of questions is in [`references/intake-and-questions.md`](references/intake-and-questions.md); ask only for what is genuinely missing, grouped so the operator answers in as few turns as possible.
35
-
36
- Two facts are load-bearing and frequently wrong if guessed: the **founding/established year** (a business that "trades since 1987" may have incorporated much later — keep the two distinct), and any **company-registration detail** (number, registered office) which must come from the register or the operator, never from the website's marketing line.
37
-
38
- ## Process — high level
39
-
40
- 1. **Resolve the workspace.** Default output root is the images directory's parent, or the operator's stated path. The deliverable lands in `<output>/site/`.
41
- 2. **Run `brand-extract`** against the website URL: produces the brand tokens (palette + accent), the logo (placed as `site/images/logo.png`) and icon, the company facts it can read, and a `brand.md` recording what was found and what is still unknown. If the operator supplied design tokens directly, use those verbatim instead of re-deriving.
42
- 3. **Curate the images.** Verify each photo's *content* by eye (never trust filenames), measuring first and previewing any image whose longest edge exceeds 2000px (downscale to `/tmp`, read, delete) so a large photo never breaks the session. Pick the strongest, most varied shots for the hero rotator and the strongest finished result for the testimonial; map the rest to the photo grids. A person's portrait is for the founder section and a portrait-only social tile, never a landscape crop.
43
- 4. **Fill the gaps.** Compare the placeholder inventory ([`microsite/references/placeholders.md`](../microsite/references/placeholders.md)) against what brand-extract found and the operator's notes. Ask the operator for everything still missing, in grouped questions. Wait for answers. Do not proceed with blanks.
44
- 5. **Run `microsite`** to build `site/index.html` + `site/llms.txt` from the templates, substituting every placeholder. No `{{ }}` may survive into the output.
45
- 6. **Run `socials` in `microsite` mode** to render the Open Graph + social tiles into `site/socials/`, plus `site/socials.html` (gallery) and `site/social-posts.md` (captions), and to wire the site's `og:image` to the landscape tile.
46
- 7. **Verify and report.** Confirm no placeholder survived, every referenced asset resolves over a local HTTP server, the site renders at desktop and mobile, and the social tiles are at exact dimensions. Report the path to `site/` and the zip, and list any value you had to ask for.
47
-
48
- ## Outcome contract
49
-
50
- ```
51
- <output>/site/
52
- index.html # the scrollable micro-site
53
- llms.txt # answer-engine summary
54
- favicon.png
55
- images/ # curated, optimised webp + logo.png + icon.png
56
- socials/ # og-{landscape,square,portrait}-{main,interior,build}.png + og-portrait-founder.png
57
- socials.html # tile gallery with download links + OG snippet
58
- social-posts.md # captions per tile and platform
59
- og.html # tile render page (kept for re-runs)
60
- <output>/<brand-slug>-microsite.zip
61
- ```
62
-
63
- ## Completion criteria
64
-
65
- - `grep "{{" site/index.html site/llms.txt site/socials.html` returns nothing — every placeholder substituted.
66
- - No invented facts: every value traces to the website, the operator's notes, or an answer the operator gave. Anything still genuinely unknown is shown as a clear gap, not a guess.
67
- - The site renders at desktop and a 390px mobile viewport with no horizontal overflow and no broken images; the hero rotates; the back-to-top works.
68
- - Social tiles exist at exact sizes (1200×628 / 1200×1200 / 1080×1350); any person tile is portrait only.
69
- - The operator-facing report names the site path, the zip path, and every field that had to be asked for.
70
-
71
- ## When NOT to use this skill
72
-
73
- - The operator only wants the micro-site, or only the social tiles → call `microsite` or `socials` directly.
74
- - The operator only wants brand tokens and a logo from a URL → call `brand-extract` directly.
75
- - There are no usable photos of the business → the site is image-led; stop and ask for photos before anything else.
@@ -1,74 +0,0 @@
1
- # Intake & gap-filling questions
2
-
3
- Ask only for what the website and the operator's notes did not already supply.
4
- Group the questions so the operator answers in as few turns as possible, and
5
- present sensible candidates from the source material where you have them ("Your
6
- site says you've traded since 1994 — is that the year to show?").
7
-
8
- Never invent a value to avoid asking. A guessed phone number or founding year is
9
- a defect. If the operator does not know a field (e.g. company number), leave that
10
- slot out of the output rather than filling it with a placeholder or a guess.
11
-
12
- ## 1. Identity
13
-
14
- - Trading name and full legal name (e.g. "Acme Joinery" / "Acme Joinery Ltd").
15
- - Short monogram / initials, if any (used as a small brand mark).
16
- - Tagline / strapline, in their own words.
17
- - Sector label for the nav and tiles (e.g. "Builders", "Joiners", "Florist").
18
- - Established year. **Keep "trading since" separate from "company incorporated".**
19
- - Company registration number + jurisdiction, and registered office — only if the
20
- operator wants legal detail in the footer. Take these from the register or the
21
- operator, never from a marketing line.
22
-
23
- ## 2. Contact & place
24
-
25
- - Phone (display + dialable), mobile if separate.
26
- - Email.
27
- - Website domain and full URL (for canonical + Open Graph).
28
- - Address: street, post town, county, postcode (only the parts they want shown).
29
- - Service area / region phrase (e.g. "the South East" or "Greater Manchester").
30
- - Social profiles: Facebook, Instagram, TikTok, LinkedIn (URLs + handles).
31
-
32
- ## 3. The story (copy, in their voice)
33
-
34
- - One or two paragraphs on who they are and how long they've been going.
35
- - What they're proudest of / the standard they hold to.
36
- - A headline sentence that sums the business up.
37
- - The three or four "by the numbers" facts (established, experience, ownership,
38
- coverage, specialism, approach, promise).
39
-
40
- ## 4. What they do (services)
41
-
42
- - Up to six services, each a short name and a one-line description.
43
- - A one-line lede for the services section.
44
-
45
- ## 5. The founder / person on site
46
-
47
- - Name and role of the person who fronts the business.
48
- - A short intro in their voice (what they do, how hands-on they are).
49
- - A quote from them, ideally about a specific job or their approach.
50
- - 1–3 recent "from the site" updates in their own words (the social-post voice
51
- is good here — keep it, just drop the emoji per the plain register).
52
- - A portrait photo of them (used in the founder section and a portrait social
53
- tile — a person is never cropped to landscape).
54
-
55
- ## 6. Proof (testimonial)
56
-
57
- - A real client quote, used verbatim. Note the one phrase to highlight.
58
- - Who it's from and the context ("on their new kitchen").
59
- - Which finished-job photo best illustrates it.
60
- - Any thank-you artefact (a card, a gift photo) that adds a personal touch.
61
-
62
- ## 7. FAQ (answer-engine targets)
63
-
64
- - 3–5 plain questions a customer actually asks, each with a one or two sentence
65
- answer. Default set: what they do, how long they've been going, where they're
66
- based / areas covered, plus two specific to the trade.
67
-
68
- ## 8. Images (you curate, but confirm)
69
-
70
- - Confirm which photo is the strongest "arrive here" shot (hero / main tile).
71
- - Confirm the best finished-result shot (testimonial + interior tile).
72
- - Confirm a strong in-progress / scale shot (build tile, full-bleed).
73
- - Flag if the photo set is mostly work-in-progress so expectations are set, and
74
- ask for any finished-result photos that would strengthen the hero.
@@ -1,96 +0,0 @@
1
- # Placeholder reference
2
-
3
- Every `{{ TOKEN }}` in the templates and what fills it. After substitution,
4
- `grep "{{"` across the output must return nothing. Never invent a value — if a
5
- token has no source, go back to the operator and ask.
6
-
7
- ## Brand tokens (palette) — from `brand-extract`
8
-
9
- `INK_900` `INK_700` `INK_400` (text: primary / secondary / muted) ·
10
- `PAPER_100` `PAPER_200` (white surface / page-bg tint) · `RULE_100` (dividers) ·
11
- `ACCENT` (brand accent) · `ACCENT_TEXT` (accent **deepened** for legible small
12
- text) · `ACCENT_SOFT` (pale accent wash) · `BRAND_GREY` (logo grey).
13
-
14
- ## Identity
15
-
16
- `COMPANY_NAME` (trading name) · `COMPANY_LEGAL_NAME` · `COMPANY_SHORT` (monogram /
17
- initials) · `TAGLINE` · `SECTOR_LABEL` (e.g. "Builders") · `ESTABLISHED_YEAR` ·
18
- `YEARS_TRADING` (e.g. "over 35 years") · `OWNERSHIP` (e.g. "Family-run") ·
19
- `COMPANY_NUMBER` · `COMPANY_JURISDICTION` · `COPYRIGHT_YEAR`.
20
-
21
- ## Contact & place
22
-
23
- `PHONE_DISPLAY` `PHONE_TEL` `PHONE_INTL` · `MOBILE_DISPLAY` `MOBILE_TEL` ·
24
- `EMAIL` · `WEBSITE_URL` `WEBSITE_DOMAIN` · `STREET_ADDRESS` `POST_TOWN` `LOCALITY`
25
- `COUNTY` `POSTCODE` · `REGION` (service-area phrase) `REGION_2` (secondary area) ·
26
- `FACEBOOK_URL` `INSTAGRAM_URL` `TIKTOK_URL` (+ `*_HANDLE` in social-posts).
27
-
28
- ## Hero info-card
29
-
30
- `HERO_STRAPLINE` · `HERO_META` (the "New builds · Extensions …" line) ·
31
- `HERO_SPEC_1..4` (four credential cells). Hero image alts are exemplar — rewrite
32
- to the real photos.
33
-
34
- ## Story / Build / Craft body blocks
35
-
36
- `STORY_HEADLINE` `STORY_PARA_1` `STORY_PARA_2` ·
37
- `BUILD_HEADLINE` `BUILD_PARA_1..3` (each may open with a `<strong>lead-in.</strong>`) ·
38
- `CRAFT_HEADLINE` `CRAFT_PARA_1..3`.
39
-
40
- ## Founder / team-lead section
41
-
42
- `FOUNDER_SECTION_LABEL` (eyebrow) · `FOUNDER_NAME` `FOUNDER_FIRST_NAME` ·
43
- `FOUNDER_HEADLINE` `FOUNDER_INTRO` `FOUNDER_QUOTE` `FOUNDER_ETHOS` ·
44
- `FEATURE_PROJECT_ALT` `FEATURE_PROJECT_CAPTION` · `GIFT_ALT` `GIFT_CAPTION` ·
45
- `UPDATES_LABEL` · `UPDATE_1..3_LOC` `UPDATE_1..3_TEXT` ("from the site" cards).
46
-
47
- ## Testimonial
48
-
49
- `TESTIMONIAL_QUOTE` (verbatim; wrap the highlight clause in
50
- `<span class="hl">…</span>`) · `TESTIMONIAL_ATTRIB` · `TESTIMONIAL_CONTEXT`.
51
-
52
- ## Services
53
-
54
- `SERVICES_HEADLINE` `SERVICES_LEDE` · `SERVICE_1..6_NAME` `SERVICE_1..6_DESC` ·
55
- `OFFER_CATALOG_NAME` (JSON-LD).
56
-
57
- ## Why-us / key facts
58
-
59
- `WHY_HEADLINE` · `FACT_1..6_KEY` `FACT_1..6_VALUE` · `FACTS_FOOTNOTE`. (The first
60
- fact row, "Established", uses `ESTABLISHED_YEAR`; Coverage uses `REGION`; Based
61
- uses `LOCALITY`/`COUNTY`.)
62
-
63
- ## FAQ (visible + JSON-LD use the same tokens)
64
-
65
- `FAQ_1..5_Q` `FAQ_1..5_A`.
66
-
67
- ## CTA / footer / meta / schema
68
-
69
- `CTA_HEADLINE` · `FOOTER_LABEL` `FOOTER_LEGAL` · `META_DESCRIPTION`
70
- `META_DESCRIPTION_SHORT` · `SCHEMA_TYPE` (e.g. `GeneralContractor`,
71
- `LocalBusiness`, `HomeAndConstructionBusiness`) `SCHEMA_DESCRIPTION`.
72
-
73
- ## llms.txt
74
-
75
- `LLMS_SUMMARY` (the one-paragraph elevator summary) · `RECENT_PROJECTS`.
76
-
77
- ## Social tiles (`socials` skill — og.html / socials.html / social-posts.md)
78
-
79
- The `socials` skill renders the tiles. In `microsite` mode it resolves the four
80
- brand themes (`main`, `interior`, `build`, `founder`) as the candidate set; the
81
- per-hero head/sub no longer live as separate markup tokens — the skill builds them
82
- into `og.html`'s `CANDIDATES_JSON` object from the brand copy. The remaining scalar
83
- tokens the templates still carry:
84
-
85
- - **og.html:** `TILE_EYEBROW` · `TILE_SPEC_1..4` · `CANDIDATES_JSON` (the
86
- `{ key: { img, pos, head, sub } }` set, one entry per theme) · `COMPANY_*` ·
87
- `WEBSITE_DOMAIN` · `PHONE_DISPLAY` · the palette tokens.
88
- - **socials.html (gallery):** repeats one group block per tile key —
89
- `TILE_KEY` · `TILE_HEAD` · `TILE_CAPTION`; the OG snippet (microsite only) uses
90
- `WEBSITE_URL`.
91
- - **social-posts.md (captions):** one block per tile key, with
92
- `TILE_KEY_INSTAGRAM` `TILE_KEY_LINKEDIN` `TILE_KEY_TIKTOK` `TILE_KEY_FACEBOOK`
93
- `TILE_KEY_X` (where `TILE_KEY` is the theme key).
94
-
95
- See [`../../socials/references/sources.md`](../../socials/references/sources.md) for
96
- the full adapter contract.