create-theokit 1.23.11 → 1.24.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 +1 -1
- package/templates/default/README.md.tmpl +18 -0
- package/templates/default/app/layout.tsx +14 -4
- package/templates/default/app/page.tsx +25 -15
- package/templates/default/dot-claude/skills/theokit-frontend/SKILL.md +21 -6
- package/templates/default/dot-claude/skills/theokit-ui/SKILL.md +17 -1
- package/templates/default/package.json.tmpl +1 -1
- package/templates/default/tsconfig.json +1 -0
package/package.json
CHANGED
|
@@ -79,6 +79,24 @@ your environment.
|
|
|
79
79
|
Deeper detail lives in [`docs/ARCHITECTURE.md`](./docs/ARCHITECTURE.md);
|
|
80
80
|
customization and environment variables have their own pages beside it.
|
|
81
81
|
|
|
82
|
+
## What is already installed
|
|
83
|
+
|
|
84
|
+
Two component libraries come with this template, and the split is by **what a component is for**,
|
|
85
|
+
not by how generic it looks:
|
|
86
|
+
|
|
87
|
+
| You need | Import from | Examples |
|
|
88
|
+
| --- | --- | --- |
|
|
89
|
+
| Agent surfaces — chat, streaming, tool calls, approvals | **`@theokit/ui`** | `ChatThread`, `ChatMessage`, `ChatComposer`, `ToolCallCard`, `AgentStream` |
|
|
90
|
+
| App chrome — shell, navigation, tables, forms, feedback | **`@usetheo/ui`** | `Sidebar`, `PageShell`, `DataTable`, `Select`, `FormField`, `Badge`, `EmptyState`, `Alert`, `Dialog`, `CommandPalette` |
|
|
91
|
+
|
|
92
|
+
This template uses a handful of them. The rest are installed and waiting — **check before you write
|
|
93
|
+
markup by hand.** A real app built on this scaffold hand-wrote around 600 lines of navigation, rows,
|
|
94
|
+
filters, badges and empty states that already existed in these two packages
|
|
95
|
+
(usetheokit/theokit#471).
|
|
96
|
+
|
|
97
|
+
The catalogue is `node_modules/@theokit/ui/llms.txt` — written to be read by an agent, and it
|
|
98
|
+
carries the routing table above in full.
|
|
99
|
+
|
|
82
100
|
## Adding a screen
|
|
83
101
|
|
|
84
102
|
Routing is file-based: a screen is a folder under `app/` with a `page.tsx`.
|
|
@@ -15,13 +15,23 @@ export default function RootLayout() {
|
|
|
15
15
|
<div className="grid h-screen w-screen grid-rows-[auto_1fr] bg-background text-foreground">
|
|
16
16
|
<Header />
|
|
17
17
|
{/*
|
|
18
|
+
`<main>` SCROLLS. The shell pins itself to the viewport (`h-screen`), so the document never
|
|
19
|
+
scrolls and something inside has to — and the default is here, where an ordinary page gets
|
|
20
|
+
it for free. It used to be `overflow-hidden`, which is right for the chat and wrong for
|
|
21
|
+
every other page: content below the fold was simply unreachable, with nothing to explain it
|
|
22
|
+
(usetheokit/theokit#484). A page with the unusual requirement declares it; the common one
|
|
23
|
+
should not have to.
|
|
24
|
+
|
|
25
|
+
`min-h-0` is the non-obvious half. This is a grid child, and a grid/flex child defaults to
|
|
26
|
+
`min-height: auto` — it refuses to shrink below its content, so `overflow-y-auto` alone does
|
|
27
|
+
nothing at all. Whatever you scroll, it needs both.
|
|
28
|
+
|
|
18
29
|
`data-theo-scroll` marks this as a scroll container, so its offset is restored on back
|
|
19
30
|
navigation (usetheokit/theokit#421). Browsers and react-router only ever restore the
|
|
20
|
-
DOCUMENT
|
|
21
|
-
|
|
22
|
-
scroll, with a different value.
|
|
31
|
+
DOCUMENT, which here never scrolls, so without the marker there is nothing to restore. The
|
|
32
|
+
value is the id — add the attribute to any other element you scroll, with a different value.
|
|
23
33
|
*/}
|
|
24
|
-
<main data-theo-scroll="main" className="
|
|
34
|
+
<main data-theo-scroll="main" className="min-h-0 overflow-y-auto">
|
|
25
35
|
<Outlet />
|
|
26
36
|
</main>
|
|
27
37
|
</div>
|
|
@@ -39,21 +39,31 @@ export default function Page() {
|
|
|
39
39
|
return (
|
|
40
40
|
<>
|
|
41
41
|
<Metadata title="TheoKit agent" description="Chat with your TheoKit agent." />
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
42
|
+
{/*
|
|
43
|
+
The chat is the page that does NOT want the shell's scroll: the log scrolls inside itself
|
|
44
|
+
and the composer stays pinned to the bottom, which `overflow-hidden` is what produces. So it
|
|
45
|
+
declares that here rather than imposing it on every other page from the layout (#484).
|
|
46
|
+
|
|
47
|
+
`h-full` fills the routed slot; `min-h-0` lets this box shrink below its content so the
|
|
48
|
+
child's own scroll works — the same pair the layout comment describes.
|
|
49
|
+
*/}
|
|
50
|
+
<div className="flex h-full min-h-0 flex-col overflow-hidden">
|
|
51
|
+
<ChatPanel
|
|
52
|
+
thread={thread}
|
|
53
|
+
isStreaming={isStreaming}
|
|
54
|
+
onlyGreeting={onlyGreeting}
|
|
55
|
+
onStarter={handleSubmit}
|
|
56
|
+
/>
|
|
57
|
+
<Composer
|
|
58
|
+
value={composerValue}
|
|
59
|
+
onValueChange={setComposerValue}
|
|
60
|
+
onSubmit={handleSubmit}
|
|
61
|
+
running={isStreaming}
|
|
62
|
+
hasError={hasError}
|
|
63
|
+
error={error}
|
|
64
|
+
onNewChat={newChat}
|
|
65
|
+
/>
|
|
66
|
+
</div>
|
|
57
67
|
</>
|
|
58
68
|
)
|
|
59
69
|
}
|
|
@@ -25,17 +25,21 @@ paths:
|
|
|
25
25
|
```typescript
|
|
26
26
|
import { theoFetch } from 'theokit/client'
|
|
27
27
|
|
|
28
|
-
//
|
|
28
|
+
// The URL is used literally — build it yourself for a dynamic route.
|
|
29
29
|
const tasks = await theoFetch('/api/tasks')
|
|
30
|
-
const task = await theoFetch(
|
|
30
|
+
const task = await theoFetch(`/api/tasks/${id}`)
|
|
31
31
|
|
|
32
|
-
// POST with body
|
|
32
|
+
// POST with body. `method` is REQUIRED when the route declares one.
|
|
33
33
|
const created = await theoFetch('/api/tasks', {
|
|
34
34
|
method: 'POST',
|
|
35
35
|
body: { title: 'New task' },
|
|
36
36
|
})
|
|
37
37
|
```
|
|
38
38
|
|
|
39
|
+
`theoFetch` has **no `params` option.** Its options are `RequestInit` minus `body`/`method`, plus a
|
|
40
|
+
conditional `query` and `body` — nothing interpolates a `:id` segment for you. Reach for the
|
|
41
|
+
generated client below when you want that; it is the half that knows your route tree.
|
|
42
|
+
|
|
39
43
|
## App Client (proxy-based)
|
|
40
44
|
|
|
41
45
|
```typescript
|
|
@@ -43,11 +47,22 @@ import { createAppClient } from 'theokit/client'
|
|
|
43
47
|
|
|
44
48
|
const client = createAppClient()
|
|
45
49
|
|
|
46
|
-
const tasks = await client.tasks.
|
|
47
|
-
const task = await client.tasks
|
|
48
|
-
const created = await client.tasks.
|
|
50
|
+
const tasks = await client.tasks.get()
|
|
51
|
+
const task = await client.tasks.id.get({ params: { id: '42' } }) // → GET /api/tasks/42
|
|
52
|
+
const created = await client.tasks.post({ body: { title: 'New' } })
|
|
49
53
|
```
|
|
50
54
|
|
|
55
|
+
Three details the generator decides for you, and each is easy to guess wrong:
|
|
56
|
+
|
|
57
|
+
- **methods are lowercase** — `get`, `post`; the export in your route file stays `GET`
|
|
58
|
+
- **a dynamic segment loses its colon** — `app/tasks/[id]` is reached as `client.tasks.id`, not
|
|
59
|
+
`client.tasks[':id']`
|
|
60
|
+
- **`params` values are strings** — `{ id: '42' }`; a URL segment has no other type
|
|
61
|
+
|
|
62
|
+
Segments are otherwise kept **literal**, so a hyphenated route needs bracket access:
|
|
63
|
+
`client['agents-config'].get()`. The client mirrors your URLs rather than prettifying them — a
|
|
64
|
+
camelCased key once produced a request to a path no route served.
|
|
65
|
+
|
|
51
66
|
## Agent Streaming
|
|
52
67
|
|
|
53
68
|
Two client APIs from `theokit/client`:
|
|
@@ -16,9 +16,25 @@ paths:
|
|
|
16
16
|
|
|
17
17
|
`@theokit/ui` is an optional peer dependency. If installed, it provides ready-made AI components for chat + coding-agent surfaces (chat thread, agent events, tool calls, diff viewer, build logs), plus theming. **Never build custom equivalents** of components it provides. Generic primitives (Button, Input, Card, CodeBlock, PageShell, Sidebar, Avatar, Alert, etc.) live in `@usetheo/ui`, which `@theokit/ui` depends on — import those from `@usetheo/ui`.
|
|
18
18
|
|
|
19
|
+
## Read the catalogue before writing markup
|
|
20
|
+
|
|
21
|
+
`@theokit/ui` ships **`llms.txt`** — a file written for an agent to read, at
|
|
22
|
+
`node_modules/@theokit/ui/llms.txt`. It lists every component with its purpose and, in a
|
|
23
|
+
**"Which package has what"** table, routes each need to the right package. Read it before building a
|
|
24
|
+
sidebar, a table, a select, a badge or an empty state by hand.
|
|
25
|
+
|
|
26
|
+
That is not a style preference. A real app built on this scaffold hand-wrote ~600 lines of markup —
|
|
27
|
+
navigation, queue rows, filters, status badges, empty states, a composer — and **every one of them
|
|
28
|
+
already existed** in the two packages the scaffold had installed (usetheokit/theokit#471). The
|
|
29
|
+
components were there; nothing pointed at them.
|
|
30
|
+
|
|
31
|
+
`@usetheo/ui` has no `llms.txt`; its surface is in its own README and its type definitions.
|
|
32
|
+
|
|
19
33
|
## Package Identity
|
|
20
34
|
|
|
21
|
-
`@theokit/ui`
|
|
35
|
+
`@theokit/ui` provides the AI-agent-surface components. (The version this project uses is in
|
|
36
|
+
`package.json`; a number written here goes stale the first time anyone upgrades, and this one
|
|
37
|
+
said `1.0.0` while npm served `1.5.1`.) Its generic foundation was split into `@usetheo/ui` in the 2026-07-03 AI-exclusive pivot; `@theokit/ui` depends on `@usetheo/ui`, so installing `@theokit/ui` pulls the foundation transitively.
|
|
22
38
|
|
|
23
39
|
```bash
|
|
24
40
|
# Install from npm (preferred)
|