Skip to main content
ClaudeWave
Skill82.2k repo starsupdated 2d ago

split-micro-app

Use when splitting a monorepo surface into a standalone micro app (React Router SSR on Cloudflare Workers), splitting a surface whose rendering code lives in the lobehub-cloud business overlay, fighting SSR bundle bloat from main-src imports, deploying its assets to CDN/R2, adding SEO/OG meta to an SSR page, adding a target and route rules for it in the lobehub gateway (torii), wiring it into the OSS Docker image, or deciding whether Cloud Next should still build or rewrite it.

Install in Claude Code
Copy
git clone --depth 1 https://github.com/lobehub/lobehub /tmp/split-micro-app && cp -r /tmp/split-micro-app/.agents/skills/split-micro-app ~/.claude/skills/split-micro-app
Then start a new Claude Code session; the skill loads automatically.

SKILL.md

# Micro App: Split, SSR, SEO, Gateway

Canonical living examples, both extracted 2026-08 — read the real files, this skill records
the decisions and landmines, not copies of the code:

- **`apps/workbench`** (`/verify`, `/acceptance`) — all code in this repo, builds and deploys from OSS CI.
- **`apps/share`** (`/share/t/:id`, `/share/page/:id`) — renders Cloud-only surfaces, so it
  builds and deploys from **lobehub-cloud** CI. See §1b before touching it.

## Hosting

One app, two serve paths. Do not mix them.

| Surface             | Who serves it                           | Build                                                                                                                                                                                               |
| ------------------- | --------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Cloud               | Gateway (torii) → Worker (SSR)          | Cloud Next does **not** `build:spa:<name>`, copy `_spa-<name>`, rewrite to `/spa-<name>`, or CDN-upload that prefix                                                                                 |
| OSS / 子部署 Docker | Next in the same image, client-rendered | `build:docker` runs `build:spa:<name>`; `<NAME>_REQUIRED=1` on `generateSpaTemplates`; Dockerfile copies `apps/<name>/package.json` before `pnpm i` and `public/_spa-<name>` into the runtime image |

`generateSpaTemplates` skips a missing `dist/<name>` HTML unless `<NAME>_REQUIRED=1`. Cloud must skip. Docker must require.

Do not revive Cloud `SPA_TARGET=<name>` Vite builds or a `/spa-<name>` middleware rewrite.

The Docker chain per app, all five links or the route is dead: root `build:docker` script →
`copySpaBuildCore.ts` target entry (`dist/<name>` → `public/_spa-<name>`) → `spaHtmlPaths.ts`
resolver + `generateSpaTemplates` block → `src/app/spa-<name>/[locale]/[[...path]]/route.ts` →
middleware rewrite (`src/libs/next/<name>Routes.ts` + `define-config.ts`) plus the path in
`src/proxy.ts`'s matcher and, for public pages, in `isPublicRoute`.

**Self-hosted loses per-page SSR.** The Next shell serves the built SPA HTML with a brand OG
card and `noindex, nofollow`; per-subject title/OG only exists in the Worker build. That is the
accepted trade, not a bug to chase.

**Dev shells — a 200 that lies.** A `/spa-<name>` handler may only call
`fetchViteDevTemplate('/index.<name>.html')` if that file exists at the repo **root** (workbench
has one; it differs from `apps/<name>/index.html` only in the entry path, which must point at
`/apps/<name>/src/entry.tsx`). Miss it and Vite's HTML fallback answers **200 with the main SPA
shell** — the micro app never loads, nothing errors, and the main SPA no longer has those routes.
An app developed against its own Vite server (share: `dev:spa:share`) carries **no dev branch at
all**. `scripts/spaDevShells.test.ts` guards both directions.

## Crossing from the main SPA

Only markdown internal entity links leave the main SPA (`InternalEntityLink` → `window.location.assign` when `shouldHardNavigateToWorkbench`). `Link` and `useWorkspaceAwareNavigate` stay in-router. Electron never hard-navs (portal). Do not add a `__WORKBENCH__` Vite define — the helper keys off the path (and skips Electron).

Share needed none of this: the only producer builds an **absolute** URL for copy/open
(`${appOrigin}/share/t/${id}` in `SharePopover`), which is already a hard navigation. Before
deleting `src/routes/<x>/**`, grep for in-router links to those paths — a surviving `Link` lands
on the main SPA's 404. Then drop the routes from `desktopRouter.config.tsx` /
`mobileRouter.config.tsx` and update `desktopRouter.sync.test.tsx` + `routeScope.test.ts`.

## 1. Splitting & Artifacts

App layout (`apps/<name>/`):

```
app/            # RR framework mode: root.tsx, routes.ts, entry.server.tsx, routes/, lib/, stubs/
workers/app.ts  # worker entry: API reverse proxy + createRequestHandler
src/            # app-owned features/shell (may coexist with a legacy SPA entry)
vite.config.rr.mts   # RR pipeline; legacy vite.config.ts can coexist (RR CLI: -c vite.config.rr.mts)
wrangler.jsonc  # name, account_id, nodejs_compat, vars (API base / app home)
staticCssOptions.mjs # ONE source for static-css hrefTemplate (vite plugin + emit + dev middleware)
```

Reuse main-src code via `@/*` deep imports + Vite 8 native `resolve.tsconfigPaths: true`
(the vite-tsconfig-paths **plugin** breaks dev SSR module-runner resolution; the app's
tsconfig `include` must cover `app/`). Stack: `@react-router/dev@8` + `@cloudflare/vite-plugin`

- repo Vite 8 (rolldown) — officially compatible.

**SSR bundle weight is the whole battle.** Main-src imports drag the app universe
(store web → chat/agent/electron). Tools and cuts, in order:

| Tool / cut                    | How                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                |
| ----------------------------- | -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
add-provider-docSkill

Add documentation for a new AI provider — usage docs, env vars, Docker config, image resources.

add-setting-envSkill

Add server-side environment variables that control default values for user settings.

agent-runtime-hooksSkill

Agent runtime lifecycle hooks. Use for before/after tool or step hooks, tool mocks, human intervention, sub-agent calls, context compression, evals, callAgent, or lifecycle events.

agent-signalSkill

Build or extend LobeHub Agent Signal pipelines. Use for signal sources, signal/action types, policies, middleware, workflow handoff, dedupe, scope behavior, or observability.

agent-tracingSkill

Agent tracing CLI for execution snapshots. Use for agent-tracing, traces, snapshots, LLM call inspection, context engine data, agent step analysis, execution debugging, or pulling remote/production traces ("拉线上 tracing") by operation id. Also the first stop for debugging agent tool calls — wrong or missing tool_calls, unexpected tool arguments or results, which tools were available at a step, or why a tool ran where it did.

builtin-toolSkill

Build LobeHub builtin tool packages. Use when adding agent-callable tools, manifests, executors, runtimes, inspectors, renders, placeholders, streaming, interventions, portals, or tool registries.

chat-sdkSkill

Build multi-platform chat bots with the chat SDK. Use for Slack, Teams, Google Chat, Discord, GitHub, Linear bots, webhooks, mentions, slash commands, cards, modals, or streaming responses.

cli-backend-testingSkill

>