@humanforest/fonts 0.1.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.
package/LICENSE ADDED
@@ -0,0 +1,67 @@
1
+ Forest Design System — Licence
2
+ Copyright (c) 2026 HumanForest Ltd. All rights reserved.
3
+
4
+ This software is published openly so that people building Forest products can install it
5
+ without access to its source repository. It is not open-source software.
6
+
7
+
8
+ 1. GRANT
9
+
10
+ You may install, use, copy and modify this software, and incorporate it into applications,
11
+ prototypes, documents and presentations, for the purpose of building or operating Forest
12
+ products, services and communications.
13
+
14
+ This grant is free of charge and requires no separate agreement. It runs to anyone who
15
+ obtains the software from a public registry.
16
+
17
+
18
+ 2. RESERVED
19
+
20
+ All rights not granted above are reserved. In particular, you may not:
21
+
22
+ (a) redistribute this software, modified or unmodified, as a design system, component
23
+ library, template or theme of your own;
24
+
25
+ (b) use the HumanForest and Forest names, logos, wordmarks, sub-brand marks or any
26
+ confusingly similar mark. Nothing here grants any trademark right. The brand marks
27
+ included in these packages are provided to render Forest's own products correctly,
28
+ not as artwork you may adopt;
29
+
30
+ (c) represent your product as being made, endorsed or approved by HumanForest.
31
+
32
+
33
+ 3. THIRD-PARTY MATERIAL
34
+
35
+ Parts of these packages are not HumanForest's to license, and the grant in section 1 does
36
+ not extend to them. Each keeps its own terms:
37
+
38
+ TYPEFACES — Mohr and GT Haptik are licensed to HumanForest by their foundries and are NOT
39
+ sublicensed to you. No font binary is included in any published package. The stylesheets
40
+ reference https://assets.forest.bike/fonts/, which serves them to those entitled to use
41
+ them. If you are not covered by Forest's licences, substitute your own faces. JetBrains
42
+ Mono is licensed under the SIL Open Font License 1.1 and may be used under those terms.
43
+
44
+ GLYPH OUTLINES — packages/tokens ships `glyphs/glyphs.json`, letterforms of the above
45
+ typefaces outlined as vector paths so sub-brand lockups can be composed at runtime. It is
46
+ covered by the same foundry terms as the typefaces themselves, not by section 1.
47
+
48
+ DEVICE ARTWORK — packages/frames ships device renders from Wikimedia Commons under the
49
+ Creative Commons Attribution-ShareAlike 4.0 International licence
50
+ (https://creativecommons.org/licenses/by-sa/4.0/). They are unmodified. Attribution is a
51
+ condition of that licence: see ATTRIBUTION.md in that package, and keep it with the art
52
+ wherever the art travels. Works derived from the artwork must themselves be CC BY-SA 4.0.
53
+
54
+ DEPENDENCIES — third-party packages installed alongside these keep their own licences.
55
+
56
+
57
+ 4. NO WARRANTY
58
+
59
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
60
+ INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
61
+ PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
62
+ FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
63
+ OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
64
+ DEALINGS IN THE SOFTWARE.
65
+
66
+
67
+ Questions about use beyond this grant: design@forest.bike
package/README.md ADDED
@@ -0,0 +1,109 @@
1
+ # @humanforest/fonts
2
+
3
+ Brand fonts for Forest: **GT Haptik** (body/UI), **Mohr** (display), **JetBrains Mono**
4
+ (code). This package is **built for public npm but not published yet** — `npm publish` has
5
+ never been run, so it currently 404s on the registry. When it does ship it is **CSS-only**:
6
+ only `forest-fonts.cdn.css`, never the `files/*` woff/woff2 themselves and never the other
7
+ generated stylesheets (those are repo-internal, see below). The Mohr licence limits
8
+ redistribution of the actual font files, so those stay out of the published tarball; they
9
+ are consumed internally as a *build source* (e.g. by the private Nuxt layer, which bundles
10
+ them directly — see `packages/nuxt-layer/README.md`).
11
+
12
+ Licence, in short:
13
+ - **GT Haptik** — unrestricted (body/labels/UI).
14
+ - **Mohr** — used only **Black + UPPERCASE**. `MohrAlt` (upright) web only; `Mohr-BlackIt`
15
+ (italic) mobile/core. Do **not** redistribute the files without written rights.
16
+ - **JetBrains Mono** — OFL, free to redistribute.
17
+
18
+ ## Three stylesheet builds (from the same `files/*.woff2`)
19
+
20
+ `bun run build:fonts` (→ `scripts/fonts.ts`) emits, alongside the hand-kept relative one. Only
21
+ `forest-fonts.cdn.css` ships in the published package — the other two are repo-internal (used
22
+ by the docs app and the artifact kit respectively, never installed by a consumer). All three:
23
+
24
+ | File | `@font-face src` | Use | Published? |
25
+ |---|---|---|---|
26
+ | `forest-fonts.css` | `url('./files/…')` relative | self-hosting via a bundler (docs, real apps) | no — repo-internal |
27
+ | `forest-fonts.cdn.css` | absolute CDN urls | runnable pages — fonts stay on the CDN | yes |
28
+
29
+ CDN base is `FOREST_FONT_CDN` (default `https://assets.forest.bike/fonts`; `assets.forest.me`
30
+ serves the same bucket). The bucket has an R2 CORS policy returning
31
+ `Access-Control-Allow-Origin: *`, which is what makes cross-origin `@font-face` work — verified by
32
+ loading all three families cross-origin from a different host. Without it the file still returns
33
+ `200` but the browser rejects it and silently paints the fallback, so if fonts ever go missing,
34
+ check the CORS header before anything else:
35
+
36
+ ```bash
37
+ curl -sI -H "Origin: https://example.com" https://assets.forest.bike/fonts/GTHaptik-Bold.woff2 | grep -i access-control
38
+ ```
39
+
40
+ Because the responses carry `Vary: Origin`, each origin is cached separately — a request made
41
+ *before* a CORS change keeps its header-less cached copy until it expires or is purged.
42
+
43
+ ---
44
+
45
+ ## If you *have* installed the package
46
+
47
+ One line in your entry CSS — the stylesheet comes from npm, the font binaries from the CDN:
48
+
49
+ ```css
50
+ @import "@humanforest/fonts/forest-fonts.cdn.css";
51
+ ```
52
+
53
+ This is the companion to the public npm packages: `@humanforest/ui` and friends ship no font files
54
+ (the licence forbids redistributing Mohr publicly), so the fonts arrive over the CDN instead.
55
+
56
+ ---
57
+
58
+ ## Using the fonts in a Nuxt project **without this package**
59
+
60
+ You don't need `@humanforest/fonts` installed. Two options.
61
+
62
+ ### Option A — load from the CDN (recommended, EULA-clean)
63
+
64
+ Fonts live on the CDN and are never copied into your repo. In `nuxt.config.ts`:
65
+
66
+ ```ts
67
+ export default defineNuxtConfig({
68
+ app: {
69
+ head: {
70
+ link: [
71
+ { rel: 'stylesheet', href: 'https://assets.forest.bike/fonts/forest-fonts.cdn.css' },
72
+ ],
73
+ },
74
+ },
75
+ })
76
+ ```
77
+
78
+ Then reference the families in your CSS / Tailwind theme:
79
+
80
+ ```css
81
+ @theme {
82
+ --font-sans: 'GT Haptik', system-ui, sans-serif;
83
+ --font-display: 'MohrAlt', 'GT Haptik', system-ui, sans-serif; /* uppercase only */
84
+ --font-mono: 'JetBrains Mono', ui-monospace, monospace;
85
+ }
86
+ ```
87
+
88
+ Requires `Access-Control-Allow-Origin` on the CDN. This is the only route that renders
89
+ **real Mohr** without shipping the files.
90
+
91
+ ### Option B — self-host the woff2 files
92
+
93
+ Copy the `woff2` files into your app (e.g. `public/fonts/`) and declare `@font-face`
94
+ yourself, pointing `src` at your own paths. Keep Mohr to Black + UPPERCASE per licence.
95
+ This redistributes the files into your app — only do it for internal/authorised apps.
96
+
97
+ ```css
98
+ @font-face {
99
+ font-family: 'GT Haptik';
100
+ src: url('/fonts/GTHaptik-Regular.woff2') format('woff2');
101
+ font-weight: normal; font-style: normal; font-display: swap;
102
+ }
103
+ /* …repeat for bold/italic, MohrAlt (900), JetBrains Mono… */
104
+ ```
105
+
106
+ Bring your own licensed woff/woff2 files and write your own `@font-face` rules — the
107
+ installed package does not carry them. The canonical `@font-face` set lives in the repo's
108
+ `packages/fonts/forest-fonts.css`, not in the installed package; use it as a reference for the
109
+ family names, weights and styles to declare.
@@ -0,0 +1,83 @@
1
+ /* Forest brand fonts — CDN build (absolute urls — host must send Access-Control-Allow-Origin).
2
+ GENERATED by scripts/fonts.ts from packages/fonts/files/*. Do not edit by hand.
3
+ Licence: Mohr = Black + UPPERCASE only; GT Haptik unrestricted; JetBrains Mono OFL. */
4
+
5
+ /* Mohr's caps sit above its own box centre; these re-hang the face so the box matches
6
+ GT Haptik's (ascent + descent) and the cap band lands centred (ascent − descent = cap height). */
7
+ @font-face {
8
+ font-family: 'MohrAlt';
9
+ src: url('https://assets.forest.bike/fonts/MohrAlt-Black.woff2') format('woff2'),
10
+ url('https://assets.forest.bike/fonts/MohrAlt-Black.woff') format('woff');
11
+ font-weight: 900;
12
+ font-style: normal;
13
+ ascent-override: 98.7549%;
14
+ descent-override: 26.7334%;
15
+ line-gap-override: 0%;
16
+ font-display: swap;
17
+ }
18
+
19
+ /* Mohr's caps sit above its own box centre; these re-hang the face so the box matches
20
+ GT Haptik's (ascent + descent) and the cap band lands centred (ascent − descent = cap height). */
21
+ @font-face {
22
+ font-family: 'Mohr-BlackIt';
23
+ src: url('https://assets.forest.bike/fonts/Mohr-BlackIt.woff2') format('woff2'),
24
+ url('https://assets.forest.bike/fonts/Mohr-BlackIt.woff') format('woff');
25
+ font-weight: 900;
26
+ font-style: italic;
27
+ ascent-override: 98.7549%;
28
+ descent-override: 26.7334%;
29
+ line-gap-override: 0%;
30
+ font-display: swap;
31
+ }
32
+
33
+ @font-face {
34
+ font-family: 'GT Haptik';
35
+ src: url('https://assets.forest.bike/fonts/GTHaptik-Regular.woff2') format('woff2'),
36
+ url('https://assets.forest.bike/fonts/GTHaptik-Regular.woff') format('woff');
37
+ font-weight: normal;
38
+ font-style: normal;
39
+ font-display: swap;
40
+ }
41
+
42
+ @font-face {
43
+ font-family: 'GT Haptik';
44
+ src: url('https://assets.forest.bike/fonts/GTHaptik-RegularOblique.woff2') format('woff2'),
45
+ url('https://assets.forest.bike/fonts/GTHaptik-RegularOblique.woff') format('woff');
46
+ font-weight: normal;
47
+ font-style: italic;
48
+ font-display: swap;
49
+ }
50
+
51
+ @font-face {
52
+ font-family: 'GT Haptik';
53
+ src: url('https://assets.forest.bike/fonts/GTHaptik-Bold.woff2') format('woff2'),
54
+ url('https://assets.forest.bike/fonts/GTHaptik-Bold.woff') format('woff');
55
+ font-weight: bold;
56
+ font-style: normal;
57
+ font-display: swap;
58
+ }
59
+
60
+ @font-face {
61
+ font-family: 'GT Haptik';
62
+ src: url('https://assets.forest.bike/fonts/GTHaptik-BoldOblique.woff2') format('woff2'),
63
+ url('https://assets.forest.bike/fonts/GTHaptik-BoldOblique.woff') format('woff');
64
+ font-weight: bold;
65
+ font-style: italic;
66
+ font-display: swap;
67
+ }
68
+
69
+ @font-face {
70
+ font-family: 'JetBrains Mono';
71
+ src: url('https://assets.forest.bike/fonts/JetBrainsMono-Regular.woff2') format('woff2');
72
+ font-weight: 400;
73
+ font-style: normal;
74
+ font-display: swap;
75
+ }
76
+
77
+ @font-face {
78
+ font-family: 'JetBrains Mono';
79
+ src: url('https://assets.forest.bike/fonts/JetBrainsMono-Bold.woff2') format('woff2');
80
+ font-weight: 700;
81
+ font-style: normal;
82
+ font-display: swap;
83
+ }
package/package.json ADDED
@@ -0,0 +1,15 @@
1
+ {
2
+ "name": "@humanforest/fonts",
3
+ "version": "0.1.0",
4
+ "files": [
5
+ "forest-fonts.cdn.css",
6
+ "README.md"
7
+ ],
8
+ "exports": {
9
+ "./forest-fonts.cdn.css": "./forest-fonts.cdn.css"
10
+ },
11
+ "publishConfig": {
12
+ "access": "public"
13
+ },
14
+ "license": "SEE LICENSE IN LICENSE"
15
+ }