@jdcpuwiz/homelab-ui 0.10.3 → 0.10.4

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
@@ -72,9 +72,9 @@ wiring.
72
72
 
73
73
  **Copy-paste templates live in [`starter/`](./starter/):**
74
74
 
75
- - `starter/next-layout.tsx` — the `next/font/google` loader for all three faces
76
- (Next apps). Match the `variable:` names to the convention:
77
- `--font-poppins` / `--font-orbitron` / `--font-jetbrains-mono`.
75
+ - `starter/next-layout.tsx` — the Next root layout. One
76
+ `import "@jdcpuwiz/homelab-ui/fonts.css"` registers all three faces; there
77
+ are no loaders and no `--font-*` variables to match any more (C525/C541).
78
78
  - `starter/vite-fonts.ts` — the `@fontsource` imports for the two Vite apps
79
79
  (wiz3dtools, timesheet).
80
80
 
@@ -131,39 +131,44 @@ fix it, don't shrug it off.
131
131
 
132
132
  ## Setup (3 steps — copy-paste)
133
133
 
134
- ### 1. Import the token stylesheet + load the three faces in `app/layout.tsx`
134
+ ### 1. Import the faces + the token stylesheet in `app/layout.tsx`
135
135
 
136
- The stylesheet brings in the `--hl-*` tokens (including the `--hl-font-*`
137
- wiring); the `next/font` loaders bring in the actual faces and expose the vars
138
- they bind to. Import the package's stylesheet **before** your own `globals.css`
139
- so yours can override. This is the full copy-paste — the complete file is in
140
- [`starter/next-layout.tsx`](./starter/next-layout.tsx).
136
+ `fonts.css` registers Poppins / Orbitron / JetBrains Mono from woff2 files
137
+ shipped **inside this package**; `globals.css` brings in the `--hl-*` tokens
138
+ (including the `--hl-font-*` wiring). Import the package's stylesheet **before**
139
+ your own `globals.css` so yours can override. This is the full copy-paste — the
140
+ complete file is in [`starter/next-layout.tsx`](./starter/next-layout.tsx).
141
141
 
142
142
  ```tsx
143
143
  import type { Metadata } from "next";
144
- import { Poppins, Orbitron, JetBrains_Mono } from "next/font/google";
145
- import "@jdcpuwiz/homelab-ui/globals.css";
144
+ import "@jdcpuwiz/homelab-ui/fonts.css"; // the three faces, self-hosted
145
+ import "@jdcpuwiz/homelab-ui/globals.css"; // tokens + base rules
146
146
  import "./globals.css"; // optional, your own project styles
147
147
 
148
- const poppins = Poppins({ subsets: ["latin"], weight: ["300","400","500","600","700","800"], display: "swap", variable: "--font-poppins" });
149
- const orbitron = Orbitron({ subsets: ["latin"], weight: ["400","500","600","700","800","900"], display: "swap", variable: "--font-orbitron" });
150
- const jetbrainsMono = JetBrains_Mono({ subsets: ["latin"], weight: ["400","500","600","700"], display: "swap", variable: "--font-jetbrains-mono" });
151
-
152
148
  export const metadata: Metadata = { title: "My App" };
153
149
 
154
150
  export default function RootLayout({ children }: { children: React.ReactNode }) {
155
151
  return (
156
- <html lang="en" className={`dark ${poppins.variable} ${orbitron.variable} ${jetbrainsMono.variable}`}>
152
+ <html lang="en" className="dark">
157
153
  <body className="antialiased">{children}</body>
158
154
  </html>
159
155
  );
160
156
  }
161
157
  ```
162
158
 
163
- The three `.variable` classes are what make `font-sans` (Poppins),
164
- `font-display` (Orbitron), and `font-mono` (JetBrains Mono) resolve. Vite apps
165
- use `@fontsource` instead — see [`starter/vite-fonts.ts`](./starter/vite-fonts.ts).
166
- Self-hosted only; no runtime Google Fonts `<link>`.
159
+ No loaders, no `variable:` names, no `.variable` classes — `font-sans`
160
+ (Poppins), `font-display` (Orbitron) and `font-mono` (JetBrains Mono) resolve
161
+ from the tokens. Vite apps can import the same `fonts.css`, or use
162
+ `@fontsource` — see [`starter/vite-fonts.ts`](./starter/vite-fonts.ts).
163
+
164
+ **Do NOT use `next/font/google` here (C525).** It makes `next build` fetch from
165
+ fonts.gstatic.com, putting a Google dependency in every consumer's DEPLOY —
166
+ zoovault's died that way on 2026-08-15, on a commit that had built clean
167
+ locally. Self-hosting removes the build-time fetch, not just the runtime
168
+ `<link>`. And do not reference `--font-poppins` / `--font-orbitron` /
169
+ `--font-jetbrains-mono`: those existed only under `next/font`, and `var(--x)`
170
+ with no fallback ARGUMENT is invalid at computed-value time — the whole
171
+ declaration is discarded and the element inherits its parent's face.
167
172
 
168
173
  ### 2. Apply the Tailwind preset in `tailwind.config.{js,ts}`
169
174
 
package/globals.css CHANGED
@@ -114,16 +114,19 @@
114
114
  dense small cell — the size line is the hard
115
115
  boundary.
116
116
 
117
- LOADING IS PER-APP. A next/font loader cannot be re-exported from this
118
- package (Next's SWC plugin scans the app's own source for literal
119
- `const Foo = Font({...})` calls, and bundling rewrites `const`→`var`),
120
- so each app self-hosts its OWN faces and binds them here. This package
121
- only owns the CSS-var wiring below. The convention each app follows:
122
-
123
- Next apps: next/font/google, `variable: "--font-poppins"` /
124
- "--font-orbitron" / "--font-jetbrains-mono", weights 300–800 on
125
- Poppins, `display: "swap"`. (See starter/ in this package.)
126
- Vite apps: @fontsource/poppins etc. — the plain family name resolves.
117
+ THE FACES SHIP IN THIS PACKAGE (C525). One
118
+ `import "@jdcpuwiz/homelab-ui/fonts.css"` registers all three from woff2
119
+ files under fonts/, so no consumer needs a loader and no build reaches
120
+ fonts.gstatic.com. This block used to say loading was necessarily
121
+ per-app; that was only ever true of next/font (its SWC plugin scans the
122
+ app's own source for literal `const Foo = Font({...})` calls, and
123
+ bundling rewrites `const`→`var`, so a re-exported LOADER genuinely
124
+ cannot work). It was never true of plain @font-face.
125
+
126
+ LEGACY, still supported: apps mid-rollout set --font-poppins /
127
+ --font-orbitron / --font-jetbrains-mono via next/font, and the vars
128
+ below still read those FIRST so both mechanisms work side by side. Do
129
+ not reference them in new code — see the fallback-argument note below.
127
130
 
128
131
  Each var references the app's next/font variable first, then the literal
129
132
  family name (covers @fontsource / a system-installed face), then the
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jdcpuwiz/homelab-ui",
3
- "version": "0.10.3",
3
+ "version": "0.10.4",
4
4
  "description": "Shared dark-theme UI primitives for the JdCpuWiz homelab — Sidebar, Button, Modal, PageHeader, TagChips, plus the canonical Tailwind preset, CSS vars, and the sanctioned three-face typography (Poppins / Orbitron / JetBrains Mono) on one flat #f0f1f4 text color.",
5
5
  "license": "MIT",
6
6
  "author": "Wiz <shad@deckerzoo.com>",
package/starter/README.md CHANGED
@@ -21,58 +21,66 @@ Text is two colors only: flat **`#f0f1f4`** for everything you read (no opacity
21
21
  ramp — hierarchy is size/weight), **`#ff9900`** for numeric values. Status pills
22
22
  keep their solid semantic bg + white text.
23
23
 
24
- The app-side variable names are a convention (`FONT_APP_VARIABLES` in the
25
- package): `--font-poppins`, `--font-orbitron`, `--font-jetbrains-mono`. The
26
- package's `globals.css` reads exactly these, so following the naming means zero
27
- extra config.
24
+ Fonts need no per-app config: `import "@jdcpuwiz/homelab-ui/fonts.css"` and
25
+ `globals.css` does the rest. (The old `--font-poppins` / `--font-orbitron` /
26
+ `--font-jetbrains-mono` convention is LEGACY — still read first for apps
27
+ mid-rollout, but not for new code. See below.)
28
28
 
29
29
  ---
30
30
 
31
- ## Next apps (`next/font/google`)
31
+ ## Next apps — one import
32
32
 
33
- See [`next-layout.tsx`](./next-layout.tsx). The shape:
33
+ See [`next-layout.tsx`](./next-layout.tsx). The whole shape:
34
34
 
35
35
  ```tsx
36
- import { Poppins, Orbitron, JetBrains_Mono } from "next/font/google";
37
- import "@jdcpuwiz/homelab-ui/globals.css";
38
- import "./globals.css"; // your own overrides, AFTER the package
39
-
40
- const poppins = Poppins({
41
- subsets: ["latin"],
42
- weight: ["300", "400", "500", "600", "700", "800"],
43
- display: "swap",
44
- variable: "--font-poppins",
45
- });
46
- const orbitron = Orbitron({
47
- subsets: ["latin"],
48
- weight: ["400", "500", "600", "700", "800", "900"],
49
- display: "swap",
50
- variable: "--font-orbitron",
51
- });
52
- const jetbrainsMono = JetBrains_Mono({
53
- subsets: ["latin"],
54
- weight: ["400", "500", "600", "700"],
55
- display: "swap",
56
- variable: "--font-jetbrains-mono",
57
- });
36
+ import "@jdcpuwiz/homelab-ui/fonts.css"; // registers all three faces
37
+ import "@jdcpuwiz/homelab-ui/globals.css"; // tokens + base rules
38
+ import "./globals.css"; // your own overrides, AFTER the package
58
39
 
59
40
  export default function RootLayout({ children }: { children: React.ReactNode }) {
60
41
  return (
61
- <html
62
- lang="en"
63
- className={`dark ${poppins.variable} ${orbitron.variable} ${jetbrainsMono.variable}`}
64
- >
42
+ <html lang="en" className="dark">
65
43
  <body className="antialiased">{children}</body>
66
44
  </html>
67
45
  );
68
46
  }
69
47
  ```
70
48
 
71
- That's it. The three `.variable` classes put `--font-poppins` /
72
- `--font-orbitron` / `--font-jetbrains-mono` on the tree; `globals.css` already
73
- references them, so `font-sans` / `font-display` / `font-mono` resolve to the
74
- real faces. Body text is Poppins with no extra style — the package sets
75
- `font-family: var(--hl-font-sans)` on `body`.
49
+ That's it. No loaders, no `variable:` names, no `.variable` classes on `<html>`.
50
+ `fonts.css` registers Poppins / Orbitron / JetBrains Mono from woff2 files
51
+ shipped **inside this package**, and `globals.css` binds them to
52
+ `--hl-font-sans` / `--hl-font-display` / `--hl-font-mono`. Body text is Poppins
53
+ with no extra style — the package sets `font-family: var(--hl-font-sans)` on
54
+ `body`.
55
+
56
+ ### Why not `next/font/google` (C525)
57
+
58
+ It makes `next build` fetch from fonts.gstatic.com, so every consuming app's
59
+ DEPLOY carries a network dependency on Google. That is not theoretical: on
60
+ 2026-08-15 zoovault's image floated `next` to a release whose
61
+ `next/font/google` requests started 404ing, and the deploy died on a commit
62
+ that had built clean locally. Nothing warns you — a build that CAN reach Google
63
+ looks identical to one that never needed to.
64
+
65
+ ### ⚠ Do NOT reference `--font-poppins` / `--font-orbitron` / `--font-jetbrains-mono`
66
+
67
+ Those variables existed only because `next/font` defined them. Under
68
+ `fonts.css` they do not exist, and referencing one is worse than a no-op:
69
+ `var(--x)` with **no fallback argument** is invalid at computed-value time, so
70
+ the entire `font-family` declaration is discarded and the element inherits its
71
+ parent's face — the fallbacks you wrote after the comma never engage. The text
72
+ still renders, in a plausible font, with nothing in the console. Tailwind's
73
+ `font-[family-name:var(--x)]` fails identically. Use the `--hl-font-*` tokens.
74
+
75
+ (`FONT_APP_VARIABLES` in `src/lib/fonts.ts` still names the old vars and
76
+ `globals.css` still reads them FIRST. That is deliberate legacy support for
77
+ apps mid-rollout — not a pattern for new code.)
78
+
79
+ ### Still mandatory, separately
80
+
81
+ PIN your dependencies from a committed lockfile inside the image (`npm ci`, not
82
+ a bare `npm install`). Self-hosting the fonts removes one network dependency at
83
+ build time; it does not make a floating install safe.
76
84
 
77
85
  **Use the faces by job:**
78
86