@cavuno/board 3.2.0 → 4.0.0

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 (77) hide show
  1. package/CHANGELOG.md +406 -0
  2. package/README.md +6 -2
  3. package/dist/{_spec-nkWAraS0.d.mts → _spec-GVe6WAfT.d.mts} +68 -59
  4. package/dist/{_spec-nkWAraS0.d.ts → _spec-GVe6WAfT.d.ts} +68 -59
  5. package/dist/bin.mjs +7 -2
  6. package/dist/{blog-iV9XEIGf.d.ts → blog-BsmKizpd.d.ts} +1 -1
  7. package/dist/{blog-DGBHmExV.d.mts → blog-Cf64mI8A.d.mts} +1 -1
  8. package/dist/{board-BJbXd_9_.d.mts → board-DUhgiacm.d.ts} +7 -6
  9. package/dist/{board-JhdUWIoq.d.ts → board-GGWJ4coe.d.mts} +7 -6
  10. package/dist/breadcrumbs-DFKr0HzU.d.mts +372 -0
  11. package/dist/breadcrumbs-DiccJhk4.d.ts +372 -0
  12. package/dist/chunk-BGKNXG4H.mjs +146 -0
  13. package/dist/{chunk-NXY3OWGF.mjs → chunk-T2KC6XGV.mjs} +1 -1
  14. package/dist/{chunk-STE77MAT.mjs → chunk-YEAQ3JEI.mjs} +143 -134
  15. package/dist/doctor.js +1 -1
  16. package/dist/doctor.mjs +1 -1
  17. package/dist/filters.d.mts +25 -20
  18. package/dist/filters.d.ts +25 -20
  19. package/dist/filters.js +3 -692
  20. package/dist/filters.mjs +3 -29
  21. package/dist/format.d.mts +57 -231
  22. package/dist/format.d.ts +57 -231
  23. package/dist/format.js +327 -968
  24. package/dist/format.mjs +207 -264
  25. package/dist/go.js +11 -1
  26. package/dist/go.mjs +1 -1
  27. package/dist/index.d.mts +23 -76
  28. package/dist/index.d.ts +23 -76
  29. package/dist/index.js +11 -36
  30. package/dist/index.mjs +11 -36
  31. package/dist/{jobs-BiEvL9d7.d.ts → jobs-BuLpV8iy.d.mts} +4 -4
  32. package/dist/{jobs-lVvKCBCU.d.mts → jobs-QrbXOYB9.d.ts} +4 -4
  33. package/dist/paths.d.mts +89 -1
  34. package/dist/paths.d.ts +89 -1
  35. package/dist/paths.js +62 -14
  36. package/dist/paths.mjs +11 -3
  37. package/dist/route-contract.js +23 -13
  38. package/dist/route-contract.mjs +2 -2
  39. package/dist/{search-CyRvVMUp.d.ts → search-Cr4noJJZ.d.mts} +14 -3
  40. package/dist/{search-CCyFWPi3.d.mts → search-DdsniXQv.d.ts} +14 -3
  41. package/dist/seo.d.mts +30 -29
  42. package/dist/seo.d.ts +30 -29
  43. package/dist/seo.js +197 -718
  44. package/dist/seo.mjs +26 -24
  45. package/dist/server.d.mts +5 -5
  46. package/dist/server.d.ts +5 -5
  47. package/dist/sitemap.d.mts +5 -5
  48. package/dist/sitemap.d.ts +5 -5
  49. package/dist/sitemap.js +25 -14
  50. package/dist/sitemap.mjs +3 -2
  51. package/dist/skills.js +1 -1
  52. package/dist/skills.mjs +1 -1
  53. package/dist/suggest.d.mts +2 -2
  54. package/dist/suggest.d.ts +2 -2
  55. package/dist/suggest.js +17 -3
  56. package/dist/suggest.mjs +17 -3
  57. package/dist/well-known.js +23 -13
  58. package/dist/well-known.mjs +2 -2
  59. package/package.json +2 -4
  60. package/skills/cavuno-board-applications/SKILL.md +4 -1
  61. package/skills/cavuno-board-filters/SKILL.md +11 -12
  62. package/skills/cavuno-board-format/SKILL.md +68 -56
  63. package/skills/cavuno-board-i18n/SKILL.md +102 -21
  64. package/skills/cavuno-board-search-suggestions/SKILL.md +8 -3
  65. package/skills/cavuno-board-seo/BLOG.md +4 -1
  66. package/skills/cavuno-board-seo/JOB_AND_BREADCRUMBS.md +5 -2
  67. package/skills/cavuno-board-seo/LISTING.md +35 -12
  68. package/skills/cavuno-board-seo/SALARY.md +83 -18
  69. package/skills/cavuno-board-seo/SKILL.md +3 -2
  70. package/skills/manifest.json +3 -3
  71. package/dist/breadcrumbs-1hMjcsqA.d.mts +0 -171
  72. package/dist/breadcrumbs-DexU07TT.d.ts +0 -171
  73. package/dist/chunk-IJCJ26SQ.mjs +0 -596
  74. package/dist/chunk-L7ZOYWHW.mjs +0 -98
  75. package/dist/chunk-LUGJWOT7.mjs +0 -96
  76. package/dist/ui-copy-CCkz6CVF.d.mts +0 -230
  77. package/dist/ui-copy-CCkz6CVF.d.ts +0 -230
@@ -245,19 +245,9 @@ interface components {
245
245
  * @description The board's canonical base URL (honours a configured custom domain). Build `robots.txt`'s `Sitemap:` line (`${canonicalBase}/sitemap.xml`) and canonical links from it.
246
246
  */
247
247
  canonicalBase: string;
248
- /** @description Absolute URLs for the board's configured favicons / app icons (null when unset). The variant key implies the role + size; build `<link rel="icon">` tags + the web-manifest icon list from these. */
249
- icons: {
250
- ico: string | null;
251
- svg: string | null;
252
- appleTouch: string | null;
253
- icon192: string | null;
254
- icon512: string | null;
255
- iconMaskable512: string | null;
256
- };
257
- /** @description Web-manifest metadata; assemble `site.webmanifest` from this + `icons`. */
248
+ /** @description Web-manifest name only. Theme color and icons left the surface in 4.0.0: applications own brand assets and presentation tokens. */
258
249
  manifest: {
259
250
  name: string;
260
- themeColor: string;
261
251
  };
262
252
  };
263
253
  BoardUser: {
@@ -1339,23 +1329,6 @@ interface components {
1339
1329
  /** Format: email */
1340
1330
  email: string;
1341
1331
  };
1342
- LegalPage: {
1343
- /** @enum {string} */
1344
- object: "legal_page";
1345
- /** @description The resolved legal page type. */
1346
- type: string;
1347
- /** @description Page heading (H1), with `{{board_name}}` resolved. */
1348
- title: string;
1349
- /** @description Owner-authored prose as portable HTML. Empty string when the page has no text body. */
1350
- content: string;
1351
- /** @enum {string} */
1352
- contentFormat: "html";
1353
- /** @description Structured impressum legal-entity facts; `null` for non-impressum pages. */
1354
- legalEntity: {
1355
- legalName: string | null;
1356
- address: string | null;
1357
- } | null;
1358
- };
1359
1332
  LocationSalaryDetail: {
1360
1333
  /** @enum {string} */
1361
1334
  object: "location_salary_detail";
@@ -1465,6 +1438,23 @@ interface components {
1465
1438
  jobCount: number;
1466
1439
  }[];
1467
1440
  };
1441
+ MarketSuggestion: {
1442
+ /** @enum {string} */
1443
+ object: "suggestion";
1444
+ /**
1445
+ * @description discriminator enum property added by openapi-typescript
1446
+ * @enum {string}
1447
+ */
1448
+ type: "market";
1449
+ /** @description Stable market identity (source slug; markets are slug-keyed). */
1450
+ id: string;
1451
+ /** @description Public market URL slug. */
1452
+ slug: string;
1453
+ /** @description Market display name. */
1454
+ name: string;
1455
+ /** @description Number of companies on the board in this market. */
1456
+ companyCount: number;
1457
+ };
1468
1458
  Message: {
1469
1459
  id: string;
1470
1460
  /** @enum {string} */
@@ -1561,6 +1551,21 @@ interface components {
1561
1551
  messagesPerPeriod: string;
1562
1552
  };
1563
1553
  };
1554
+ PostSuggestion: {
1555
+ /** @enum {string} */
1556
+ object: "suggestion";
1557
+ /**
1558
+ * @description discriminator enum property added by openapi-typescript
1559
+ * @enum {string}
1560
+ */
1561
+ type: "post";
1562
+ /** @description Stable published blog post identity. */
1563
+ id: string;
1564
+ /** @description Public blog post URL slug. */
1565
+ slug: string;
1566
+ /** @description Post title. */
1567
+ title: string;
1568
+ };
1564
1569
  PublicBlogAdjacentPosts: {
1565
1570
  /** @enum {string} */
1566
1571
  object: "blog_adjacent_posts";
@@ -1651,7 +1656,11 @@ interface components {
1651
1656
  candidates: boolean;
1652
1657
  employers: boolean;
1653
1658
  blog: boolean;
1654
- talentDirectory: boolean;
1659
+ /**
1660
+ * @description Talent directory access mode. Link /talent whenever this is not `'off'`. An employers-only directory renders a sign-in upsell for anonymous visitors, matching the hosted chrome. Replaces the former top-level `talentDirectoryVisibility` and the boolean `features.talentDirectory`.
1661
+ * @enum {string}
1662
+ */
1663
+ talentDirectory: "off" | "public" | "employers_only";
1655
1664
  registrationWall: boolean;
1656
1665
  passwordProtected: boolean;
1657
1666
  publicJobSubmission: boolean;
@@ -1662,11 +1671,6 @@ interface components {
1662
1671
  /** @description Whether applicant↔employer messaging is enabled on the board. `false` means the `me/conversations` route family rejects with `messaging_disabled` (403). Hide inbox/dock/Message CTAs. */
1663
1672
  messaging: boolean;
1664
1673
  };
1665
- /**
1666
- * @description The tri-state behind `features.talentDirectory` (which is `visibility === 'public'`). Link /talent whenever this is not `'off'`. An employers-only directory renders a sign-in upsell for anonymous visitors, matching the hosted chrome.
1667
- * @enum {string}
1668
- */
1669
- talentDirectoryVisibility: "off" | "public" | "employers_only";
1670
1674
  analytics: {
1671
1675
  ga4MeasurementId: string | null;
1672
1676
  gtmId: string | null;
@@ -1674,33 +1678,23 @@ interface components {
1674
1678
  linkedInPartnerId: string | null;
1675
1679
  cookieConsentRequired: boolean;
1676
1680
  };
1677
- /** @description Operator-defined custom job-field definitions, in display order. Board-wide; the frontend uses these to render and localize each job's opaque `customFieldValues`. Empty when the board defines none. Display-only: not filterable or searchable in v1. */
1678
- customFields: components["schemas"]["CustomFieldDefinition"][];
1679
- /** @description Stored operator label overrides by config group (`jobCardLabels`, `navLabels`, `breadcrumbsLabels`, …): plain-text chrome copy to merge over the `@cavuno/board` `uiCopy(language)` catalog via `uiCopy(language, labels)`. Empty object when the board stores none. */
1680
- labels: {
1681
- [key: string]: {
1682
- [key: string]: string;
1683
- };
1681
+ /** @description Operator-defined custom field definitions keyed by model (currently only `job`). Each key holds that model's definitions in display order. Company and talent keys are added when those models ship. The frontend uses these to render and localize each record's opaque `customFieldValues`. Display-only: not filterable or searchable in v1. */
1682
+ customFields: {
1683
+ /** @description This model's custom-field definitions in display order. Empty when the board defines none for the model. */
1684
+ job: components["schemas"]["CustomFieldDefinition"][];
1684
1685
  };
1685
- /** @description Footer/brand data the hosted board footer renders (description, contact, website + social links, navigation order). The brand/social URLs (`websiteUrl`, `facebookUrl`, `linkedinUrl`, `xUrl`) are sanitized to absolute http(s); `customLinks[].url` is served verbatim (see its own note). */
1686
- footer: {
1687
- /** @description Operator-written footer brand description. May carry a `{{board_name}}` placeholder. Resolve it before rendering. When null, fall back to the label catalog's `footer.defaultDescription` template. */
1688
- description: string | null;
1689
- /** @description Public contact email for the footer About column (render as `mailto:`). */
1690
- contactEmail: string | null;
1686
+ /** @description Operator-authored contact and social identity (settings › Contact & company details). Extracted from the former `footer` group in 4.0.0: contact is identity data, not layout. Brand/social URLs are sanitized to absolute http(s). */
1687
+ contact: {
1688
+ /** @description Public contact email (render as `mailto:`). Operator-set in settings › Contact & company details. */
1689
+ email: string | null;
1690
+ /** @description Company website URL, sanitized to absolute http(s). Null when unset or non-http(s). */
1691
1691
  websiteUrl: string | null;
1692
1692
  /** @description X (Twitter) profile URL, normalized from the stored handle. */
1693
1693
  xUrl: string | null;
1694
+ /** @description Facebook profile URL, sanitized to absolute http(s). Null when unset or non-http(s). */
1694
1695
  facebookUrl: string | null;
1696
+ /** @description LinkedIn profile URL, sanitized to absolute http(s). Null when unset or non-http(s). */
1695
1697
  linkedinUrl: string | null;
1696
- /** @description Operator-configured navigation order: system item ids (`home`, `companies`, `pricing`, `blog`) and `custom:<id>` refs into `customLinks`. Empty when the operator never reordered. Render the system defaults. System items still gate on their feature flags (e.g. `blog` only when `features.blog`). */
1697
- navigationOrder: string[];
1698
- /** @description Operator-defined navigation links referenced from `navigationOrder` as `custom:<id>`; links not referenced there append after the system items (hosted-footer behavior). Each `url` is served verbatim (trimmed only) and may be a relative path (e.g. `/hub`): unlike the brand/social URLs it is NOT run through http(s) sanitization (matching the hosted footer, which supports relative links), so a consumer MUST sanitize it before binding to an anchor href. */
1699
- customLinks: {
1700
- id: string;
1701
- label: string;
1702
- url: string;
1703
- }[];
1704
1698
  };
1705
1699
  };
1706
1700
  PublicCompaniesSearchBody: {
@@ -1841,7 +1835,7 @@ interface components {
1841
1835
  slug: string;
1842
1836
  name: string;
1843
1837
  }[];
1844
- /** @description Opaque, display-only custom-field values, keyed by each field's `key`. Values are the option `key`(s) for select fields, or the raw boolean/number/text otherwise. Resolve labels via the board's `customFields` definitions (see `GET /v1/boards/:identifier`). `{}` when the board defines no custom fields. Not filterable or searchable in v1. */
1838
+ /** @description Opaque, display-only custom-field values, keyed by each field's `key`. Values are the option `key`(s) for select fields, or the raw boolean/number/text otherwise. Resolve labels via the board's `customFields.job` definitions (see `GET /v1/boards/:identifier`). `{}` when the board defines no custom fields. Not filterable or searchable in v1. */
1845
1839
  customFieldValues: {
1846
1840
  [key: string]: string | string[] | boolean | number;
1847
1841
  };
@@ -2186,7 +2180,7 @@ interface components {
2186
2180
  jobId: string;
2187
2181
  /** Format: date-time */
2188
2182
  savedAt: string;
2189
- job: components["schemas"]["PublicJob"];
2183
+ job: components["schemas"]["PublicJobCard"];
2190
2184
  };
2191
2185
  SendWorkEmailBody: {
2192
2186
  /** Format: email */
@@ -2347,10 +2341,25 @@ interface components {
2347
2341
  object: "suggest_result";
2348
2342
  /** @description The trimmed query string that produced these suggestions. */
2349
2343
  query: string;
2350
- /** @description Interleaved company + taxonomy-term suggestions. Order is server-ranked; clients must not re-sort. */
2344
+ /** @description Interleaved company, market, taxonomy-term, blog-post, and tag suggestions. Order is server-ranked; clients must not re-sort. When `types` is set, only the requested kinds appear and `limit` applies after that filter. */
2351
2345
  items: components["schemas"]["SuggestionItem"][];
2352
2346
  };
2353
- SuggestionItem: components["schemas"]["CompanySuggestion"] | components["schemas"]["TermSuggestion"];
2347
+ SuggestionItem: components["schemas"]["CompanySuggestion"] | components["schemas"]["MarketSuggestion"] | components["schemas"]["TermSuggestion"] | components["schemas"]["PostSuggestion"] | components["schemas"]["TagSuggestion"];
2348
+ TagSuggestion: {
2349
+ /** @enum {string} */
2350
+ object: "suggestion";
2351
+ /**
2352
+ * @description discriminator enum property added by openapi-typescript
2353
+ * @enum {string}
2354
+ */
2355
+ type: "tag";
2356
+ /** @description Stable tag identity (source slug; tags are slug-keyed). */
2357
+ id: string;
2358
+ /** @description Public blog tag URL slug. */
2359
+ slug: string;
2360
+ /** @description Tag display name. */
2361
+ name: string;
2362
+ };
2354
2363
  TalentAccess: {
2355
2364
  /** @enum {string} */
2356
2365
  object: "talent_access";
package/dist/bin.mjs CHANGED
@@ -29,7 +29,7 @@ function loadSkillCorpus(baseDir) {
29
29
  ).map((entry) => ({
30
30
  path: entry.name,
31
31
  content: readFileSync(resolve(skillDir, entry.name), "utf8")
32
- })).sort((a, b) => a.path.localeCompare(b.path));
32
+ })).sort((a, b) => a.path < b.path ? -1 : a.path > b.path ? 1 : 0);
33
33
  return {
34
34
  ...skill,
35
35
  content: readFileSync(skillPath, "utf8"),
@@ -575,7 +575,12 @@ function runSetup(cwd = process.cwd()) {
575
575
  if (!copied.includes(skill.name)) copied.push(skill.name);
576
576
  }
577
577
  }
578
- return { version: manifest.version, framework, targetDirs, copied };
578
+ return {
579
+ version: manifest.version,
580
+ framework,
581
+ targetDirs,
582
+ copied
583
+ };
579
584
  }
580
585
 
581
586
  // src/bin.ts
@@ -1,4 +1,4 @@
1
- import { S as Schemas } from './_spec-nkWAraS0.js';
1
+ import { S as Schemas } from './_spec-GVe6WAfT.js';
2
2
 
3
3
  /** Author shape embedded on posts (no `object` discriminator). */
4
4
  type BlogAuthorEmbed = Schemas['PublicBlogAuthorEmbed'];
@@ -1,4 +1,4 @@
1
- import { S as Schemas } from './_spec-nkWAraS0.mjs';
1
+ import { S as Schemas } from './_spec-GVe6WAfT.mjs';
2
2
 
3
3
  /** Author shape embedded on posts (no `object` discriminator). */
4
4
  type BlogAuthorEmbed = Schemas['PublicBlogAuthorEmbed'];
@@ -1,5 +1,5 @@
1
- import { S as Schemas } from './_spec-nkWAraS0.mjs';
2
- import { L as ListEnvelope, m as RelatedSearch } from './jobs-lVvKCBCU.mjs';
1
+ import { S as Schemas } from './_spec-GVe6WAfT.js';
2
+ import { L as ListEnvelope, m as RelatedSearch } from './jobs-QrbXOYB9.js';
3
3
 
4
4
  type PublicCompany = Schemas['CompanyPublic'];
5
5
  /** A market (sector) a company operates in — name + its source slug. */
@@ -92,10 +92,11 @@ type PublicBoard = Schemas['PublicBoardContext'];
92
92
  type PublicBoardFeatures = PublicBoard['features'];
93
93
  type PublicBoardAnalytics = PublicBoard['analytics'];
94
94
  /**
95
- * An operator-defined custom job-field definition. Board-wide;
96
- * use it to render and localize a job's opaque `customFieldValues` (resolve
97
- * option `key`s → labels, honour field `type` and display order). Shared with
98
- * the Operator API's custom-field surface (one canonical schema).
95
+ * An operator-defined custom field definition. Board-wide and
96
+ * model-scoped under `board.context().customFields` (today only `job`);
97
+ * use it to render and localize a record's opaque `customFieldValues`
98
+ * (resolve option `key`s → labels, honour field `type` and display order).
99
+ * Shared with the Operator API's custom-field surface (one canonical schema).
99
100
  */
100
101
  type CustomFieldDefinition = Schemas['CustomFieldDefinition'];
101
102
  type CustomFieldType = CustomFieldDefinition['type'];
@@ -1,5 +1,5 @@
1
- import { S as Schemas } from './_spec-nkWAraS0.js';
2
- import { L as ListEnvelope, m as RelatedSearch } from './jobs-BiEvL9d7.js';
1
+ import { S as Schemas } from './_spec-GVe6WAfT.mjs';
2
+ import { L as ListEnvelope, m as RelatedSearch } from './jobs-BuLpV8iy.mjs';
3
3
 
4
4
  type PublicCompany = Schemas['CompanyPublic'];
5
5
  /** A market (sector) a company operates in — name + its source slug. */
@@ -92,10 +92,11 @@ type PublicBoard = Schemas['PublicBoardContext'];
92
92
  type PublicBoardFeatures = PublicBoard['features'];
93
93
  type PublicBoardAnalytics = PublicBoard['analytics'];
94
94
  /**
95
- * An operator-defined custom job-field definition. Board-wide;
96
- * use it to render and localize a job's opaque `customFieldValues` (resolve
97
- * option `key`s → labels, honour field `type` and display order). Shared with
98
- * the Operator API's custom-field surface (one canonical schema).
95
+ * An operator-defined custom field definition. Board-wide and
96
+ * model-scoped under `board.context().customFields` (today only `job`);
97
+ * use it to render and localize a record's opaque `customFieldValues`
98
+ * (resolve option `key`s → labels, honour field `type` and display order).
99
+ * Shared with the Operator API's custom-field surface (one canonical schema).
99
100
  */
100
101
  type CustomFieldDefinition = Schemas['CustomFieldDefinition'];
101
102
  type CustomFieldType = CustomFieldDefinition['type'];