create-theokit 1.23.5 → 1.23.6

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": "create-theokit",
3
- "version": "1.23.5",
3
+ "version": "1.23.6",
4
4
  "type": "module",
5
5
  "description": "Scaffold a new TheoKit project",
6
6
  "license": "Apache-2.0",
@@ -0,0 +1,83 @@
1
+ # Cross-platform desktop release — builds {{name}} for macOS (Apple Silicon + Intel),
2
+ # Linux (x64 + arm64) and Windows, then drafts a GitHub release with the installers.
3
+ #
4
+ # WHY a matrix of native runners: Tauri does NOT support cross-compiling between operating
5
+ # systems (macOS/Linux bundles REQUIRE their own host; only Windows-NSIS-from-Linux is a
6
+ # last-resort exception). Each target therefore builds on its own runner — the documented
7
+ # best practice: https://v2.tauri.app/distribute/pipelines/github/
8
+ #
9
+ # ⚠️ PREREQUISITE — the sidecar must be a real binary, not the dev shim.
10
+ # `tauri build` runs `scripts/build-sidecar.mjs`, which in DEV writes a POSIX shell shim
11
+ # that execs this repo's local `tsx` (absolute build-time paths, requires Node on the user's
12
+ # machine). That shim is NOT portable to end users, and `build-sidecar.mjs` intentionally
13
+ # FAILS on Windows (Tauri needs a `.exe`). Before this workflow can ship a working app you
14
+ # MUST compile `sidecar/sidecar.ts` to a self-contained per-platform binary at
15
+ # `src-tauri/binaries/theo-sidecar-<target-triple>[.exe]`. See README-surface.md § Packaging.
16
+ #
17
+ # Trigger: push to the `release` branch, or run manually (Actions → Run workflow).
18
+ name: release-desktop
19
+
20
+ on:
21
+ workflow_dispatch:
22
+ push:
23
+ branches: [release]
24
+
25
+ jobs:
26
+ build:
27
+ permissions:
28
+ contents: write
29
+ strategy:
30
+ fail-fast: false
31
+ matrix:
32
+ include:
33
+ - platform: macos-latest # Apple Silicon → .app / .dmg
34
+ args: --target aarch64-apple-darwin
35
+ - platform: macos-latest # Intel → .app / .dmg
36
+ args: --target x86_64-apple-darwin
37
+ - platform: ubuntu-22.04 # Linux x64 → .deb / .AppImage / .rpm
38
+ args: ''
39
+ - platform: ubuntu-22.04-arm # Linux arm64
40
+ args: ''
41
+ - platform: windows-latest # Windows → .exe (NSIS) / .msi
42
+ args: ''
43
+
44
+ runs-on: ${{ matrix.platform }}
45
+ steps:
46
+ - uses: actions/checkout@v4
47
+
48
+ - name: Install Linux system dependencies
49
+ if: startsWith(matrix.platform, 'ubuntu')
50
+ run: |
51
+ sudo apt-get update
52
+ sudo apt-get install -y libwebkit2gtk-4.1-dev libappindicator3-dev librsvg2-dev patchelf xdg-utils
53
+
54
+ - name: Setup Node
55
+ uses: actions/setup-node@v4
56
+ with:
57
+ node-version: lts/*
58
+ cache: npm
59
+
60
+ - name: Install Rust (stable)
61
+ uses: dtolnay/rust-toolchain@stable
62
+ with:
63
+ targets: ${{ matrix.platform == 'macos-latest' && 'aarch64-apple-darwin,x86_64-apple-darwin' || '' }}
64
+
65
+ - name: Rust cache
66
+ uses: swatinem/rust-cache@v2
67
+ with:
68
+ workspaces: ./src-tauri -> target
69
+
70
+ - name: Install frontend dependencies
71
+ run: npm install
72
+
73
+ - name: Build + release with Tauri
74
+ uses: tauri-apps/tauri-action@v0
75
+ env:
76
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
77
+ with:
78
+ tagName: {{name}}-v__VERSION__
79
+ releaseName: '{{name}} v__VERSION__'
80
+ releaseBody: 'See the assets below to download and install this version.'
81
+ releaseDraft: true
82
+ prerelease: false
83
+ args: ${{ matrix.args }}
@@ -53,3 +53,17 @@ externalBin that a shell shim cannot satisfy (`build:sidecar` fails loud on win3
53
53
  before building. Options: **Node SEA** (single-executable app — runs under Node, where the stream works),
54
54
  or `bun build --compile`/`pkg` (verify the ai-sdk token stream survives your bundler first). Replace the
55
55
  `build:sidecar` script with your compile command and keep the same output path.
56
+
57
+ ### Cross-platform release (macOS · Linux · Windows)
58
+
59
+ Tauri does **not** cross-compile between operating systems — macOS/Linux bundles must be built on their own
60
+ host, and only Windows-NSIS-from-Linux is a fragile last resort ([docs](https://v2.tauri.app/distribute/pipelines/github/)).
61
+ The best practice is a **matrix of native CI runners**, so this surface ships
62
+ `.github/workflows/release.yml`: on push to a `release` branch (or a manual run) it builds `{{name}}` on
63
+ `macos-latest` (Apple Silicon **and** Intel), `ubuntu-22.04` (x64 + arm64) and `windows-latest`, then drafts
64
+ a GitHub release with the installers (`.dmg`/`.app`, `.deb`/`.AppImage`/`.rpm`, `.msi`/NSIS `.exe`).
65
+
66
+ Before that workflow can ship a **working** app, resolve the sidecar gap above (the CI `tauri build` runs the
67
+ same `build:sidecar`, which fails on the Windows runner and produces a non-portable shim on macOS/Linux). For
68
+ public distribution you also need **code signing** — macOS notarization (Apple Developer ID) and a Windows
69
+ signing certificate; see [Tauri › Distribute](https://v2.tauri.app/distribute/).
@@ -42,7 +42,6 @@ const transport = new ChannelTransport({ source: createTauriChannelSource(tauri.
42
42
 
43
43
  // The window is frameless (`decorations: false` in tauri.conf.json) so the OS title bar can't clash with
44
44
  // the app background — the app owns its top bar. These drive the native window from our custom controls.
45
- // (The drag + these calls need `core:window:*` permissions in `src-tauri/capabilities/default.json`.)
46
45
  const appWindow = (
47
46
  globalThis as {
48
47
  __TAURI__?: {
@@ -75,40 +74,30 @@ const STARTERS: QuickAction[] = [
75
74
  ]
76
75
 
77
76
  // App-level layout in inline styles (the desktop bundle has no Tailwind). Colors read the theme CSS vars
78
- // `@theokit/ui` sets, so light/dark + the theme switcher cascade exactly like the web surface.
77
+ // `@theokit/ui` sets and those vars are `oklch()` colors, so wrap them in `color-mix(in oklch, …)` for
78
+ // alpha (NOT `hsl(var(--x) / a)`, which is invalid CSS and silently renders transparent).
79
79
  const styles = {
80
80
  page: {
81
81
  display: 'flex',
82
82
  flexDirection: 'column',
83
83
  height: '100vh',
84
- background: 'hsl(var(--background))',
85
- color: 'hsl(var(--foreground))',
84
+ background: 'var(--background)',
85
+ color: 'var(--foreground)',
86
86
  },
87
87
  header: {
88
88
  display: 'flex',
89
89
  alignItems: 'center',
90
90
  justifyContent: 'space-between',
91
- // A faint gray wash (4% of the text color over the background) makes the frameless title bar
92
- // read as a distinct strip in BOTH themes, without breaking the seamless feel.
93
- background: 'hsl(var(--foreground) / 0.04)',
94
- borderBottom: '1px solid hsl(var(--border) / 0.6)',
95
- padding: '8px 16px',
91
+ // The frameless title bar is its own DISTINCT band: the `--muted` surface reads clearly apart
92
+ // from the content background (adapts to light/dark), with a border to seal the strip.
93
+ background: 'var(--muted)',
94
+ borderBottom: '1px solid var(--border)',
95
+ // Slim title bar — thin vertical padding keeps the strip compact.
96
+ padding: '3px 12px',
96
97
  },
97
98
  brand: { display: 'inline-flex', alignItems: 'center', gap: 8 },
98
- brandName: { fontWeight: 600, fontSize: 13, letterSpacing: '-0.01em' },
99
- headerRight: { display: 'inline-flex', alignItems: 'center', gap: 4 },
100
- winBtn: {
101
- display: 'inline-flex',
102
- alignItems: 'center',
103
- justifyContent: 'center',
104
- width: 28,
105
- height: 28,
106
- border: 'none',
107
- borderRadius: 6,
108
- background: 'transparent',
109
- color: 'hsl(var(--muted-foreground))',
110
- cursor: 'pointer',
111
- },
99
+ brandName: { fontWeight: 600, fontSize: 12, letterSpacing: '-0.01em' },
100
+ headerRight: { display: 'inline-flex', alignItems: 'center', gap: 2 },
112
101
  scroll: { flex: 1, overflowY: 'auto', minHeight: 0 },
113
102
  column: {
114
103
  margin: '0 auto',
@@ -120,8 +109,8 @@ const styles = {
120
109
  padding: 24,
121
110
  },
122
111
  composerBar: {
123
- borderTop: '1px solid hsl(var(--border) / 0.6)',
124
- background: 'hsl(var(--background) / 0.5)',
112
+ borderTop: '1px solid color-mix(in oklch, var(--border) 60%, transparent)',
113
+ background: 'color-mix(in oklch, var(--background) 50%, transparent)',
125
114
  },
126
115
  composerInner: { margin: '0 auto', width: '100%', maxWidth: 768, padding: '16px 24px' },
127
116
  } satisfies Record<string, CSSProperties>
@@ -151,43 +140,55 @@ export function App(): ReactElement {
151
140
 
152
141
  return (
153
142
  <TheoUIProvider>
143
+ {/* Window controls need :hover feedback — inline styles can't do pseudo-classes, so the button
144
+ appearance (incl. hover, and the classic red close) lives in this small stylesheet. */}
145
+ <style>{`
146
+ .tk-winbtn {
147
+ display: inline-flex; align-items: center; justify-content: center;
148
+ width: 20px; height: 20px; border: none; border-radius: 6px;
149
+ background: transparent; color: var(--muted-foreground); cursor: pointer;
150
+ transition: background 0.12s ease, color 0.12s ease;
151
+ }
152
+ .tk-winbtn:hover { background: color-mix(in oklch, var(--foreground) 12%, transparent); color: var(--foreground); }
153
+ .tk-winbtn--close:hover { background: #e5484d; color: #fff; }
154
+ `}</style>
154
155
  <div style={styles.page}>
155
156
  {/* Frameless title bar: `data-tauri-drag-region` makes the whole strip drag the window; the
156
- background is the app background (with a faint wash), so the bar reads as one with the
157
- content. Interactive children (theme switcher, window buttons) still receive clicks. */}
157
+ background is the `--muted` band, so the bar reads as a distinct strip. Interactive
158
+ children (theme switcher, window buttons) still receive clicks. */}
158
159
  <header style={styles.header} data-tauri-drag-region>
159
160
  <span style={styles.brand}>
160
- <Bot size={18} style={{ color: 'hsl(var(--primary))' }} aria-hidden />
161
- <span style={styles.brandName}>{{name}} — TheoKit agent</span>
161
+ <Bot size={18} style={{ color: 'var(--primary)' }} aria-hidden />
162
+ <span style={styles.brandName}>{{name}}</span>
162
163
  </span>
163
164
  <span style={styles.headerRight}>
164
165
  <ThemeSwitcher />
165
166
  <button
166
167
  type="button"
167
- style={styles.winBtn}
168
+ className="tk-winbtn"
168
169
  onClick={minimizeWindow}
169
170
  aria-label="Minimize"
170
171
  title="Minimize"
171
172
  >
172
- <Minus size={16} />
173
+ <Minus size={15} />
173
174
  </button>
174
175
  <button
175
176
  type="button"
176
- style={styles.winBtn}
177
+ className="tk-winbtn"
177
178
  onClick={maximizeWindow}
178
179
  aria-label="Maximize"
179
180
  title="Maximize"
180
181
  >
181
- <Square size={13} />
182
+ <Square size={12} />
182
183
  </button>
183
184
  <button
184
185
  type="button"
185
- style={styles.winBtn}
186
+ className="tk-winbtn tk-winbtn--close"
186
187
  onClick={closeWindow}
187
188
  aria-label="Close"
188
189
  title="Close"
189
190
  >
190
- <X size={16} />
191
+ <X size={15} />
191
192
  </button>
192
193
  </span>
193
194
  </header>