Skip to content

feat: add client-foldkit to catalog#130

Merged
lloydrichards merged 4 commits into
mainfrom
feat/client-foldkit-scaffold
May 21, 2026
Merged

feat: add client-foldkit to catalog#130
lloydrichards merged 4 commits into
mainfrom
feat/client-foldkit-scaffold

Conversation

@lloydrichards

@lloydrichards lloydrichards commented May 21, 2026

Copy link
Copy Markdown
Owner

Goals/Scope

Adds client-foldkit as a new target kind for scaffolding frontend client using foldkit. Introduces two new composition primitives (ts-object-field, namespaceImport) to support foldkit's pattern of deterministic AST-based module composition.

Description

Domain (@repo/domain)

  • Added ts-object-field contribution type to Catalog.ts — injects a property into an object literal argument of a function call (e.g., Schema.Struct, M.tagsExhaustive)
  • Added namespaceImport field to ts-call-arg, jsx-slot, and import operation schemas — enables import * as X from "..." patterns
  • Added TsObjectFieldOp to Plan.ts composition operations

Scaffold (@repo/scaffold)

  • Implemented applyTsObjectField in TypeScriptComposer — finds variable → function call → object literal → adds property via ts-morph
  • Added curried call expression handling to applyTsAppendCallArg — correctly targets the outer () in patterns like Subscription.aggregate<M, Msg>()()
  • Updated ContributionResolver, PlanAssessor, PlanService, and PlanRenderer for the new contribution types

Catalog (@repo/catalog)

  • Added client-foldkit target definition (path: apps/client-foldkit-{name})
  • Added 4 foldkit modules: http-api-foldkit-client, http-rpc-foldkit-client, ws-presence-foldkit-client, chat-foldkit-client
  • Added content templates for base target files (main.ts, compose.ts, theme.ts, entry.ts, etc.) and all module features/services
  • Extended config-typescript-vite module to support client-foldkit kind

Comments

Modules compose into main.ts via ts-object-field (Model fields, update cases) and ts-call-arg (Message union, Init.compose, Subscription.aggregate, Views.compose).

Can see the template in its full on the block/foldkit branch

 bun start -- add -r .temp --dry-run
$ bun apps/cli/src/index.ts add -r .temp --dry-run
✔ What kind of target do you want to add? Client Foldkit Application
✔ What should this client-foldkit target be called? 
✔ Which modules do you want to add to "client-foldkit/"? HTTP API Client (Foldkit), HTTP RPC Client (Foldkit), WebSocket Presence (Foldkit), Chat Client (Foldkit)
✔ Module "HTTP API Client (Foldkit)" requires a server target. What should it be called? 
╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ Current targets and modules:                                                                                          │
│                                                                                                                       │
│ ✓  client-foldkit/  http-api-foldkit-client, http-rpc-foldkit-client, ws-presence-foldkit-client, chat-foldkit-client │
│ ○  server/          http-api-server, http-rpc-server, ws-presence-server, chat-server                                 │
╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
✔ What would you like to do? Confirm all

╭────────────────────────────────────────────────────────────────╮──────────────────────────────────────────────╮────────────────────╮
│  Blueprint                                                     │  Apply                                       │  Finalize          │
│                                                                │                                              │                    │
│  - apps/client-foldkit (client-foldkit)                        │  .                                           │  Install & Format  │
│    ├╌> apps/client-foldkit#chat-foldkit-client                 │  ├── apps                                    │  > bun install     │
│    │   ├─> packages/domain#domain-chat [required-module]       │  │   ├── client-foldkit                      │  > bun run lint    │
│    │   ├─> packages/domain#domain-rpc [required-module]        │  │   │   ├── public                          │  > bun run format  │
│    │   ╰─> packages/domain [required-target]                   │  │   │   │   ╰── [+] theme-init.js           │                    │
│    ├╌> apps/client-foldkit#config-typescript-vite              │  │   │   ├── src                             │                    │
│    ├╌> apps/client-foldkit#http-api-foldkit-client             │  │   │   │   ├── features                    │                    │
│    │   ├─> packages/domain#domain-api [required-module]        │  │   │   │   │   ├── [+] chat.ts             │                    │
│    │   ╰─> packages/domain [required-target]                   │  │   │   │   │   ├── [+] presence.ts         │                    │
│    ├╌> apps/client-foldkit#http-rpc-foldkit-client             │  │   │   │   │   ├── [+] rest.ts             │                    │
│    │   ├─> packages/domain#domain-rpc [required-module]        │  │   │   │   │   ├── [+] theme.ts            │                    │
│    │   ╰─> packages/domain [required-target]                   │  │   │   │   │   ╰── [+] ticks.ts            │                    │
│    ╰╌> apps/client-foldkit#ws-presence-foldkit-client          │  │   │   │   ├── lib                         │                    │
│        ├─> packages/domain#domain-websocket [required-module]  │  │   │   │   │   ╰── [+] compose.ts          │                    │
│        ╰─> packages/domain [required-target]                   │  │   │   │   ├── services                    │                    │
│                                                                │  │   │   │   │   ├── [+] chat-client.ts      │                    │
│  - apps/server (server)                                        │  │   │   │   │   ├── [+] rpc-client.ts       │                    │
│    ├╌> apps/server#chat-server                                 │  │   │   │   │   ╰── [+] ws-client.ts        │                    │
│    │   ├─> packages/ai#ai-chat-service [required-module]       │  │   │   │   ├── [+] entry.ts                │                    │
│    │   ├─> packages/domain#domain-chat [required-module]       │  │   │   │   ├── [+] main.ts                 │                    │
│    │   ├─> packages/ai [required-target]                       │  │   │   │   ╰── [+] styles.css              │                    │
│    │   ╰─> packages/domain [required-target]                   │  │   │   ├── [+] index.html                  │                    │
│    ├╌> apps/server#http-api-server                             │  │   │   ├── [+] package.json                │                    │
│    │   ├─> packages/domain#domain-api [required-module]        │  │   │   ├── [+] tsconfig.config.json        │                    │
│    │   ╰─> packages/domain [required-target]                   │  │   │   ├── [+] tsconfig.json               │                    │
│    ├╌> apps/server#http-rpc-server                             │  │   │   ╰── [+] vite.config.ts              │                    │
│    │   ├─> packages/domain#domain-rpc [required-module]        │  │   ╰── server                              │                    │
│    │   ╰─> packages/domain [required-target]                   │  │       ├── src                             │                    │
│    ╰╌> apps/server#ws-presence-server                          │  │       │   ├── Api                         │                    │
│        ├─> packages/domain#domain-websocket [required-module]  │  │       │   │   ├── [+] Health.ts           │                    │
│        ├─> packages/presence#presence [required-module]        │  │       │   │   ╰── [+] Hello.ts            │                    │
│        ├─> packages/domain [required-target]                   │  │       │   ├── Rpc                         │                    │
│        ╰─> packages/presence [required-target]                 │  │       │   │   ├── [+] Chat.ts             │                    │
│                                                                │  │       │   │   ├── [+] Event.ts            │                    │
│  - packages/ai (package)                                       │  │       │   │   ╰── [+] Presence.ts         │                    │
│    ├╌> packages/ai#ai                                          │  │       │   ╰── [+] index.ts                │                    │
│    │   ├─> packages/domain#domain-chat [required-module]       │  │       ├── [+] package.json                │                    │
│    │   ╰─> packages/domain [required-target]                   │  │       ╰── [+] tsconfig.json               │                    │
│    ├╌> packages/ai#ai-chat-service                             │  ╰── packages                                │                    │
│    │   ├─> packages/ai#ai [required-module]                    │      ├── ai                                  │                    │
│    │   ├─> packages/ai#ai-sample-toolkit [required-module]     │      │   ├── src                             │                    │
│    │   ├─> packages/domain#domain-chat [required-module]       │      │   │   ├── services                    │                    │
│    │   ╰─> packages/domain [required-target]                   │      │   │   │   ╰── [+] ChatService.ts      │                    │
│    ╰╌> packages/ai#ai-sample-toolkit                           │      │   │   ├── toolkits                    │                    │
│                                                                │      │   │   │   ╰── [+] SampleToolkit.ts    │                    │
│  - packages/domain (package)                                   │      │   │   ├── workflow                    │                    │
│    ├╌> packages/domain#domain-api                              │      │   │   │   ├── [+] AgenticLoop.ts      │                    │
│    ├╌> packages/domain#domain-chat                             │      │   │   │   ╰── [+] MailboxEvents.ts    │                    │
│    ├╌> packages/domain#domain-rpc                              │      │   │   ├── [+] index.ts                │                    │
│    ╰╌> packages/domain#domain-websocket                        │      │   │   ╰── [+] LanguageModel.ts        │                    │
│                                                                │      │   ├── [+] package.json                │                    │
│  - packages/presence (package)                                 │      │   ╰── [+] tsconfig.json               │                    │
│    ╰╌> packages/presence#presence                              │      ├── config-typescript                   │                    │
│        ├─> packages/domain#domain-websocket [required-module]  │      │   ├── [~] package.json                │                    │
│        ╰─> packages/domain [required-target]                   │      │   ╰── [+] vite.json                   │                    │
│                                                                │      ├── domain                              │                    │
│                                                                │      │   ├── src                             │                    │
│                                                                │      │   │   ├── [+] Api.ts                  │                    │
│                                                                │      │   │   ├── [+] Chat.ts                 │                    │
│                                                                │      │   │   ├── [+] ChatRpc.ts              │                    │
│                                                                │      │   │   ├── [+] index.ts                │                    │
│                                                                │      │   │   ├── [+] Rpc.ts                  │                    │
│                                                                │      │   │   ╰── [+] WebSocket.ts            │                    │
│                                                                │      │   ├── [+] package.json                │                    │
│                                                                │      │   ╰── [+] tsconfig.json               │                    │
│                                                                │      ╰── presence                            │                    │
│                                                                │          ├── src                             │                    │
│                                                                │          │   ├── services                    │                    │
│                                                                │          │   │   ├── [+] ClientGenerator.ts  │                    │
│                                                                │          │   │   ╰── [+] PresenceService.ts  │                    │
│                                                                │          │   ╰── [+] index.ts                │                    │
│                                                                │          ├── [+] package.json                │                    │
│                                                                │          ╰── [+] tsconfig.json               │                    │
│                                                                │                                              │                    │
│                                                                │  48 create 1 modify 0 skip                   │                    │
╰────────────────────────────────────────────────────────────────╯──────────────────────────────────────────────╯────────────────────╯

No changes written.

This is part 2 of 2 in a stack made with GitButler:

@changeset-bot

changeset-bot Bot commented May 21, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: a3cc22b

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
stack-effect Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@lloydrichards lloydrichards force-pushed the refactor/client-react-rename branch from 10e9354 to 00ce8f4 Compare May 21, 2026 09:27
@lloydrichards lloydrichards force-pushed the feat/client-foldkit-scaffold branch 2 times, most recently from 5131d04 to e1e49dd Compare May 21, 2026 09:53
Base automatically changed from refactor/client-react-rename to main May 21, 2026 09:54
@lloydrichards lloydrichards force-pushed the feat/client-foldkit-scaffold branch from e1e49dd to a3cc22b Compare May 21, 2026 09:59
@lloydrichards lloydrichards merged commit 03b31ce into main May 21, 2026
6 checks passed
@lloydrichards lloydrichards deleted the feat/client-foldkit-scaffold branch May 21, 2026 10:05
@github-actions github-actions Bot mentioned this pull request May 21, 2026
@lloydrichards

Copy link
Copy Markdown
Owner Author
flowchart LR

  classDef new fill:#10b981,color:#000

  0["init"]
  1["client-react"]
  2["client-foldkit"]:::new
  3["server"]
  4["cli"]
  5["package"]
  6["turbo"]
  7["biome"]
  8["dprint"]
  9["oxlint"]
  10["vitest"]
  11["git-init"]
  12["config-typescript-vite"]
  13["domain-api"]
  14["domain-rpc"]
  15["domain-chat"]
  16["domain-websocket"]
  17["http-api-server"]
  18["http-rpc-server"]
  19["chat-server"]
  20["ws-presence-server"]
  21["http-api-react-client"]
  22["http-rpc-react-client"]
  23["chat-react-client"]
  24["ws-presence-react-client"]
  25["http-api-foldkit-client"]:::new
  26["http-rpc-foldkit-client"]:::new
  27["ws-presence-foldkit-client"]:::new
  28["chat-foldkit-client"]:::new
  29["ai"]
  30["ai-sample-toolkit"]
  31["ai-chat-service"]
  32["presence"]
  33["hello-command"]
  6 -->|"supportedOn"| 0
  7 -->|"supportedOn"| 0
  8 -->|"supportedOn"| 0
  9 -->|"supportedOn"| 0
  10 -->|"supportedOn"| 0
  11 -->|"supportedOn"| 0
  12 -->|"supportedOn"| 1
  12 -->|"supportedOn"| 2
  13 -->|"supportedOn"| 5
  14 -->|"supportedOn"| 5
  15 -->|"supportedOn"| 5
  16 -->|"supportedOn"| 5
  17 -->|"supportedOn"| 3
  17 -->|"requiredModule"| 13
  18 -->|"supportedOn"| 3
  18 -->|"requiredModule"| 14
  19 -->|"supportedOn"| 3
  19 -->|"requiredModule"| 15
  19 -->|"requiredModule"| 31
  20 -->|"supportedOn"| 3
  20 -->|"requiredModule"| 16
  20 -->|"requiredModule"| 32
  21 -->|"supportedOn"| 1
  21 -->|"requiredModule"| 13
  21 -->|"implies"| 17
  22 -->|"supportedOn"| 1
  22 -->|"requiredModule"| 14
  22 -->|"implies"| 18
  23 -->|"supportedOn"| 1
  23 -->|"requiredModule"| 15
  23 -->|"implies"| 19
  24 -->|"supportedOn"| 1
  24 -->|"requiredModule"| 16
  24 -->|"implies"| 20
  25 -->|"supportedOn"| 2
  25 -->|"requiredModule"| 13
  25 -->|"implies"| 17
  26 -->|"supportedOn"| 2
  26 -->|"requiredModule"| 14
  26 -->|"implies"| 18
  27 -->|"supportedOn"| 2
  27 -->|"requiredModule"| 16
  27 -->|"implies"| 20
  28 -->|"supportedOn"| 2
  28 -->|"requiredModule"| 15
  28 -->|"requiredModule"| 14
  28 -->|"implies"| 19
  29 -->|"supportedOn"| 5
  29 -->|"requiredModule"| 15
  30 -->|"supportedOn"| 5
  31 -->|"supportedOn"| 5
  31 -->|"requiredModule"| 15
  31 -->|"requiredModule"| 30
  31 -->|"requiredModule"| 29
  32 -->|"supportedOn"| 5
  32 -->|"requiredModule"| 16
  33 -->|"supportedOn"| 4
Loading

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant