@supertype.ai/foundations 0.1.26 → 0.1.28

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/README.md CHANGED
@@ -1,15 +1,17 @@
1
1
  # @supertype.ai/foundations
2
2
 
3
- The shared design layer behind the Supertype projects: typography primitives,
4
- content blocks, the long-form essay shell, the token and theme CSS, and the
5
- build-time tooling that checks it all (SEO, OG cards, lint rules, contrast
6
- checks).
3
+ [![ci](https://github.com/supertypeai/foundations/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/supertypeai/foundations/actions/workflows/ci.yml)
4
+ [![npm](https://img.shields.io/npm/v/%40supertype.ai%2Ffoundations?logo=npm&color=cb3837)](https://www.npmjs.com/package/@supertype.ai/foundations)
5
+ [![license](https://img.shields.io/npm/l/%40supertype.ai%2Ffoundations?color=blue)](LICENSE)
6
+
7
+ [The foundations philosophy](https://supertypeai.github.io/foundations/philosophy/) lays out the Raison d'être better, but the crux is that it is a reusable design system that binds typography primitives, content blocks, the long-form essay shell, the token and theme CSS, and the build-time tooling that keep baseline quality high (SEO, OG cards, lint rules, contrast
8
+ checks) in a single package. Used by Supertype's own projects like [Viably work operating system](https://viably.app) and [supertype.ai](https://supertype.ai), it is also MIT-licensed and available for any Next.js 15+ project built atop Tailwind and Shadcn.
7
9
 
8
10
  ```sh
9
11
  yarn add @supertype.ai/foundations
10
12
  ```
11
13
 
12
- **Start here:** [Install](#install) [Your first page](#your-first-page).
14
+ **Start here:** [Install](#install), then [Your first page](#your-first-page).
13
15
 
14
16
  **Reference:** [Typography](docs/typography.md) · [Blocks](docs/blocks.md) ·
15
17
  [The essay shell](docs/essay.md) · [Build-time tooling](docs/tooling.md) ·
@@ -18,18 +20,18 @@ yarn add @supertype.ai/foundations
18
20
  **Working on the package itself:** [Contributing](docs/contributing.md), for
19
21
  local iteration against a consumer and for releasing.
20
22
 
23
+ Like the project? ⭐ Star it on [GitHub](https://github.com/supertypeai/foundations)
24
+
21
25
  ## See it running
22
26
 
23
- Run the example site locally:
27
+ Check out: [the documentation site](https://supertypeai.github.io/foundations/), or alternatively run the example site locally:
24
28
 
25
29
  ```sh
26
30
  yarn example:install # once, to install Next, the peers and the package
27
31
  yarn example # then open http://localhost:3000
28
32
  ```
29
33
 
30
- [`examples/site`](examples/site) renders every component along with the code, and include whole-page [recipes](examples/site/app/_recipes) to copy into your project along with the `dark` and `.editorial` switches.
31
-
32
- ## Alternatively, check out: [the documentation site](https://supertypeai.github.io/foundations/)
34
+ [`examples/site`](examples/site) renders every component along with the code, and include whole-page [recipes](examples/site/app/_recipes) to copy into your project. Comes with the `dark` and `.editorial` switches.
33
35
 
34
36
  ## Initialization and Diagnostics
35
37
 
@@ -41,9 +43,7 @@ npx @supertype.ai/foundations doctor # checks this app against everything bel
41
43
  ```
42
44
 
43
45
  `init` edits one file: the CSS entry that imports Tailwind. It adds the imports
44
- you are missing and reorders anything that is out of place. Run it with `--dry-run` first to see the patch. Everything else it
45
- prints for you to paste — the font binding, and the `llms.txt` line for a coding
46
- agent.
46
+ you are missing and reorders anything that is out of place. Run it with `--dry-run` first to see the patch. Everything else it prints for you to paste (the font binding, and the `llms.txt` lines for a coding agent).
47
47
 
48
48
  The steps performed by `init` are written out below anyway. See [the CLI](docs/cli.md) for the full list of checks and details.
49
49
 
@@ -65,7 +65,7 @@ untagged git dependency re-resolves to a different commit on any fresh install.
65
65
 
66
66
  ```jsonc
67
67
  // package.json
68
- "@supertype.ai/foundations": "https://github.com/supertypeai/foundations.git#v0.1.26"
68
+ "@supertype.ai/foundations": "https://github.com/supertypeai/foundations.git#v0.1.28"
69
69
  ```
70
70
 
71
71
  </details>
@@ -89,8 +89,7 @@ default, so without it every class is purged and the components
89
89
  render with no styles at all.
90
90
 
91
91
  **`theme.css` is required.** `tokens.css` names the colour roles; `theme.css` is
92
- what gives them values. Without it every colour utility still generates and
93
- resolves to nothing, so the page renders unpainted with no error. It also carries
92
+ what gives them values. Without it color utility can't be resolved, so the page renders unpainted with no error. It also carries
94
93
  `--secondary-ink`, `--subtle-foreground`, the four earth tones the marker
95
94
  highlight uses, and the `accordion-down` and `accordion-up` keyframes. Skip it
96
95
  only if you declare every role yourself; `foundations doctor` fails when neither
@@ -114,9 +113,7 @@ const serif = Average({ variable: "--font-average", weight: "400", subsets: ["la
114
113
  ```
115
114
 
116
115
  **Bind with `.variable`, never `.className`.** A className sets `font-family` on
117
- the element itself and leaves the roles unresolved, so the page renders one
118
- typeface while every `font-sans` and `font-heading` utility on it renders
119
- another.
116
+ the element itself and leaves the roles unresolved, causing a mismatch where the page renders one typeface while every `font-sans` and `font-heading` utility on it renders another.
120
117
 
121
118
  ### 4. Check the wiring
122
119
 
@@ -195,8 +192,7 @@ Two rules cover most of the API:
195
192
  `text-sm text-muted-foreground` is `<TypographyMuted>`. Using the primitives
196
193
  keeps a size and a colour from drifting apart across a few hundred call sites.
197
194
  - **Retune with CSS variables, not classes.** The package owns its own
198
- classnames. Change a `--text-*` rung, `--heading-weight` or a colour token and
199
- everything moves together.
195
+ classnames. Change a `--text-*`, `--heading-weight`, or a colour specification in `theme.css` to retune the whole package. Read [Tokens and theming](#tokens-and-theming) for full instructions.
200
196
 
201
197
  ---
202
198
 
@@ -205,18 +201,13 @@ Two rules cover most of the API:
205
201
  `yarn example` (above) builds the package, syncs it in and starts the dev
206
202
  server. `yarn example:build` is what CI would run.
207
203
 
208
- It installs the package from a git tag rather than from the registry the
209
- install path that has no lockfile-independent proof anywhere else — and updates
210
- it with `yarn sync`, with no workspace and no symlink. Its `global.css`
211
- and `layout.tsx` are the blocks above, unchanged, so an install instruction that
212
- stops being true breaks the site.
204
+ It installs the package from a git tag rather than from the registry and updates
205
+ it with `yarn sync`.
213
206
 
214
207
  `/recipes` holds whole pages rather than single components: a marketing hero, a
215
- metrics panel, pricing tiers, a docs page, an article index, and the three files
216
- that wire up MDX. Each one lives in
208
+ metrics panel, pricing tiers, a docs page, an article index, and examples of MDX-rendered pages. Each one lives in
217
209
  [`app/_recipes/`](examples/site/app/_recipes) as a complete file that imports
218
210
  only from this package, so you can paste it into your app and it compiles.
219
- `yarn example:build` fails if a recipe reaches for a local helper.
220
211
 
221
212
  ---
222
213
 
@@ -253,15 +244,6 @@ package.
253
244
  | `./tokens.css` `./theme.css` `./type.css` `./prose.css` `./shiki.css` | the style layer | [Tokens and theming](#tokens-and-theming) |
254
245
  | `foundations` (bin) | `init` and `doctor` | [The CLI](docs/cli.md) |
255
246
 
256
- The entries are split by what they pull in. Blocks and the MDX map stay out of
257
- the root barrel so that importing a heading does not resolve `@base-ui/react` or
258
- `next/image`, and `/rehype` and `/contrast` stay out of both so they can run in
259
- bare Node, where React cannot be resolved.
260
-
261
- None of the entry points can be imported from plain Node, though: typography
262
- reaches `next/link` through `next-view-transitions`. Import them from a Next app,
263
- or from a test runner that resolves Next — both consumers' vitest suites do.
264
-
265
247
  ---
266
248
 
267
249
  ## Tokens and theming
@@ -274,18 +256,18 @@ only ever one palette in play.
274
256
 
275
257
  Each status hue ships twice, on the same rule as the categorical tints:
276
258
  `--success`, `--warn` and `--info` are **fills**, held to 3:1 against the page
277
- and a card because a dot or a bar is a mark rather than words; `--success-ink`,
259
+ and a card; `--success-ink`,
278
260
  `--warn-ink` and `--info-ink` are the same hues as **text**, held to 4.5:1.
279
261
  `--danger` ships as an ink only. `--destructive` keeps shadcn's shape, where
280
262
  `--destructive-foreground` is the label printed on the fill — that is what
281
263
  `-foreground` means throughout, and `-ink` means the hue used as words.
282
- `checkSignals` in `@supertype.ai/foundations/contrast` measures all three bars.
264
+ `checkSignals` in `@supertype.ai/foundations/contrast` measures all of them and fails if any are below the threshold.
283
265
 
284
266
  `tokens.css` also binds the `dark:` variant to the `.dark` class. Do not skip
285
267
  that import: Tailwind v4 otherwise follows the OS setting and quietly ignores
286
268
  your toggle.
287
269
 
288
- `theme.css` gives those roles the house latte and espresso palette, and adds the
270
+ `theme.css` gives those roles the latte and espresso palette, and adds the
289
271
  editorial inks (`--secondary-ink`, `--subtle-foreground`, and the ochre,
290
272
  terracotta, sage and fig pairs) along with the elevation shadows.
291
273
 
@@ -306,25 +288,21 @@ than patching the utilities:
306
288
 
307
289
  `type.css` names three font roles (`--font-sans`, `--font-mono` and
308
290
  `--font-heading`) and the weight that goes with the heading face. `.editorial`
309
- gives the heading role to the serif and drops the weight to 400, since Average
310
- only has one:
291
+ gives the heading role to the serif and drops the weight to 400.
311
292
 
312
293
  ```tsx
313
294
  <div className="editorial">…</div> {/* or on <html> for an editorial site */}
314
295
  ```
315
296
 
316
- It also retunes the whole heading ladder, which is the larger part of what it
317
- does. Heading sizes are a _ratio_ to the body text under them, and the two
318
- surfaces set body at different sizes: 13px in the product, 18px on `.editorial`. Scope the
319
- class to whichever surfaces should be editorial, whether that is a marketing and
320
- docs section or the whole site.
297
+ Heading sizes are a _ratio_ to the body text under them, and the two
298
+ surfaces set body at different sizes: 13px in the product, 18px on `.editorial`. Scope the class to whichever surfaces should be editorial, whether that is a marketing and docs section or the whole site.
321
299
 
322
300
  ---
323
301
 
324
302
  ## Design rules
325
303
 
326
304
  1. **The package owns its final classnames.** Retune with CSS custom properties
327
- (the `--text-*` ramp, `--heading-weight`, the colour tokens) rather than by
305
+ (the `--text-*`, `--heading-weight`, the colour tokens) rather than by
328
306
  patching classes. A property the package declares is read by the package —
329
307
  `test/tokens-live.test.ts` fails on one that is not, because a knob that
330
308
  turns nothing is worse than no knob at all.
@@ -351,7 +329,7 @@ Sites running the package:
351
329
  - [supertype.ai](https://supertype.ai) — Supertype, a regional-leading analytics engineering and data science consulting firm.
352
330
  - [viably.app](https://viably.app) — Viably, an observability-first business operating system and CRM for automation-obsessed teams.
353
331
 
354
- ---
332
+ ## ![](https://assets.viably.app/app_assets/screen/usage_dark.webp)
355
333
 
356
334
  ## License
357
335
 
package/dist/seo.d.ts CHANGED
@@ -76,9 +76,10 @@ export declare function createSeo(config: SeoConfig): {
76
76
  "@type": string;
77
77
  url: string;
78
78
  } | undefined;
79
- "@type": string;
80
79
  name: string;
81
80
  url: string;
81
+ "@id"?: string | undefined;
82
+ "@type": string;
82
83
  };
83
84
  mainEntityOfPage: {
84
85
  "@type": string;
@@ -154,9 +155,10 @@ export declare function createSeo(config: SeoConfig): {
154
155
  "@type": string;
155
156
  url: string;
156
157
  } | undefined;
157
- "@type": string;
158
158
  name: string;
159
159
  url: string;
160
+ "@id"?: string | undefined;
161
+ "@type": string;
160
162
  };
161
163
  author?: {
162
164
  jobTitle?: string | undefined;
package/dist/seo.js CHANGED
@@ -7,11 +7,6 @@ export function createSeo(config) {
7
7
  const { baseUrl, siteName, defaultOgImage, logoUrl, articleBasePath = "notes", publisherUrl, trailingSlash = false, } = config;
8
8
  /** Resolves a possibly-relative URL against the site origin. */
9
9
  const absolute = (url) => url.startsWith("http") ? url : `${baseUrl}${url.startsWith("/") ? "" : "/"}${url}`;
10
- /**
11
- * Stable `@id` anchors for the site's core entities. Pages reference these
12
- * rather than re-declaring an Organization node, so crawlers merge them into
13
- * one entity instead of collecting near-duplicates.
14
- */
15
10
  /**
16
11
  * A page route in the shape this site actually serves. A URL already carrying
17
12
  * a query, a fragment or a file extension is left alone — only a route gets
@@ -34,10 +29,24 @@ export function createSeo(config) {
34
29
  ...(author.jobTitle ? { jobTitle: author.jobTitle } : {}),
35
30
  };
36
31
  };
32
+ /**
33
+ * Stable `@id` anchors for the site's core entities. Pages reference these
34
+ * rather than re-declaring an Organization node, so crawlers merge them into
35
+ * one entity instead of collecting near-duplicates.
36
+ */
37
37
  const ORG_ID = `${baseUrl}/#organization`;
38
38
  const WEBSITE_ID = `${baseUrl}/#website`;
39
+ /**
40
+ * The publisher every Article and WebPage node points at. It carries `@id`
41
+ * only when the publisher is this site: without one, each page declares a
42
+ * fresh Organization and a crawler has no way to merge a corpus of them into
43
+ * the canonical entity the site emits once. A `publisherUrl` naming a
44
+ * different site gets no `@id` — `ORG_ID` is derived from `baseUrl`, so
45
+ * stamping it there would claim someone else's publisher as this one.
46
+ */
39
47
  const publisher = {
40
48
  "@type": "Organization",
49
+ ...(!publisherUrl || publisherUrl === baseUrl ? { "@id": ORG_ID } : {}),
41
50
  name: siteName,
42
51
  url: publisherUrl ?? baseUrl,
43
52
  ...(logoUrl
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@supertype.ai/foundations",
3
- "version": "0.1.26",
3
+ "version": "0.1.28",
4
4
  "license": "MIT",
5
5
  "publishConfig": {
6
6
  "access": "public",