camox 0.53.1 → 0.54.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "camox",
3
- "version": "0.53.1",
3
+ "version": "0.54.0",
4
4
  "license": "MIT",
5
5
  "bin": {
6
6
  "camox": "./bin/camox.mjs"
@@ -112,7 +112,6 @@
112
112
  "@shikijs/langs": "^4.5.0",
113
113
  "@shikijs/themes": "^4.5.0",
114
114
  "@sinclair/typebox": "^0.34.52",
115
- "@takumi-rs/image-response": "^2.16.3",
116
115
  "@tanstack/react-form": "^1.33.5",
117
116
  "@tanstack/react-hotkeys": "^0.16.0",
118
117
  "@tanstack/react-query-devtools": "^5.104.3",
@@ -133,11 +132,12 @@
133
132
  "react-dom": "^19.3.1",
134
133
  "react-og-preview": "^0.2.0",
135
134
  "shiki": "^4.5.0",
135
+ "takumi-js": "^2.18.1",
136
136
  "unhead": "^3.4.3",
137
137
  "zod": "^4.6.7",
138
- "@camox/api-contract": "0.53.1",
139
- "@camox/cli": "0.53.1",
140
- "@camox/ui": "0.53.1"
138
+ "@camox/api-contract": "0.54.0",
139
+ "@camox/cli": "0.54.0",
140
+ "@camox/ui": "0.54.0"
141
141
  },
142
142
  "devDependencies": {
143
143
  "@earendil-works/pi-ai": "1.3.0",
@@ -85,25 +85,20 @@ Singleton and derived layouts also receive `data` and `params`, and record pages
85
85
 
86
86
  ## OG Image — `toImage` (optional)
87
87
 
88
- Returns JSX rendered as a 1200×630 image. Use **inline styles, not Tailwind**, and `display: "flex"` for layout: this runs in an image-generation engine, not a browser.
88
+ Returns JSX rendered as a 1200×630 image. Style it with the Theme's utilities, like a block: the image renders with the site's compiled `src/styles.css` and the Google Fonts that `src/document.ts` loads. It runs in an image engine, not a browser, so:
89
+
90
+ - Size the root with `h-full w-full`, and lay out with flexbox or grid.
91
+ - Put the color scheme class (`dark`, `brand`, …) and `font-body` on the root: the document's `<html>` classes and base styles don't apply.
92
+ - Only class, id and descendant selectors match, so `hover:` and other state variants do nothing. Breakpoints see a 1200px-wide viewport.
89
93
 
90
94
  ```tsx
91
95
  toImage: ({ page, project }) => (
92
- <div
93
- style={{
94
- display: "flex",
95
- flexDirection: "column",
96
- width: "100%",
97
- height: "100%",
98
- padding: 60,
99
- backgroundColor: "#09090b",
100
- color: "#fafafa",
101
- fontFamily: "sans-serif",
102
- }}
103
- >
104
- {project.name && <div style={{ fontSize: 24 }}>{project.name}</div>}
105
- <div style={{ fontSize: 64 }}>{page.title}</div>
106
- {page.description && <div style={{ fontSize: 28 }}>{page.description}</div>}
96
+ <div className="dark bg-canvas text-ink font-body flex h-full w-full flex-col justify-center px-20 py-16">
97
+ {project.name && <div className="text-brand mb-6 text-2xl uppercase">{project.name}</div>}
98
+ <div className="font-heading line-clamp-2 text-6xl font-semibold">{page.title}</div>
99
+ {page.description && (
100
+ <div className="text-ink-muted mt-6 line-clamp-2 text-3xl">{page.description}</div>
101
+ )}
107
102
  </div>
108
103
  ),
109
104
  ```
@@ -1,31 +0,0 @@
1
- import { GEIST_VARIABLE_TTF_BASE64 } from "./geist-variable-ttf-base64.js";
2
-
3
- //#region src/features/og/defaultFonts.ts
4
- /**
5
- * Decoded default fonts for the OG image wrapper.
6
- *
7
- * Takumi's wasm renderer ships with no embedded fonts — rendering without
8
- * `fonts` produces zero text runs and OG images come out as featureless
9
- * rectangles. We always inject Geist Variable so text has something to render
10
- * with; the user can still pass their own `fonts:` through the ImageResponse
11
- * constructor and override this default.
12
- *
13
- * Decoded once at module load. Takumi keys registered fonts by their bytes, so
14
- * passing the same `data` on every render registers Geist only once per
15
- * isolate.
16
- */
17
- function decodeBase64(b64) {
18
- const binary = atob(b64);
19
- const bytes = new Uint8Array(binary.length);
20
- for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i);
21
- return bytes;
22
- }
23
- const DEFAULT_FONTS = [{
24
- name: "Geist",
25
- data: decodeBase64(GEIST_VARIABLE_TTF_BASE64),
26
- weight: 400,
27
- style: "normal"
28
- }];
29
-
30
- //#endregion
31
- export { DEFAULT_FONTS };