todo: resurrect projects/apps, with the archaeology attached

the idea is not settled. the card exists so the history is not dug out
twice: user apps were born 2026-02-27 as a publishing system that made a
personal app a first-class workspace panel, /projects was its authoring
surface, and both went a day apart at the end of july — 1440 deletions.

the part worth knowing before rebuilding: the app registry used to be
mutable at runtime, registerApp keyed on email/slug, and the note left
where it stood argues well against it. the plugin system solved the same
problem afterwards by generating at build time, so the first question is
whether a user app is just a plugin with a different author.

nothing on disk was ever touched.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-25 03:58:56 +00:00
co-authored by Claude Fable 5
parent 9dfa83e607
commit 887f702c05
2 changed files with 136 additions and 35 deletions
+35 -35
View File
@@ -20,41 +20,41 @@ the owner's OS user and can never be granted. Indirection there really is accide
## Themes
**89 open, 29 closed**, across 31 themes.
**90 open, 29 closed**, across 31 themes.
| Theme | Open | Closed |
| ------------------------------------------------------------------------------------------ | ---- | ------ |
| [Affordances](todo/affordances/) | 1 | 0 |
| [Agents coordinating agents](todo/agent-coordination/) | 2 | 0 |
| [Speaking into a session from the backend](todo/agent-delivery/) | 1 | 1 |
| [Backburner](todo/backburner/) | 2 | 0 |
| [Background jobs](todo/background-jobs/) | 2 | 1 |
| [Chat interface](todo/chat/) | 1 | 0 |
| [Code editor](todo/code-editor/) | 1 | 0 |
| [Components — the shared UI layer](todo/components/) | 1 | 0 |
| [File watchers](todo/file-watchers/) | 1 | 0 |
| [Fleet — one command across every server](todo/fleet/) | 5 | 2 |
| [Headscale](todo/headscale/) | 0 | 5 |
| [Infra (alpha)](todo/infra/) | 7 | 0 |
| [Known bugs](todo/known-bugs/) | 3 | 2 |
| [Mobile apps](todo/mobile-apps/) | 3 | 0 |
| [Multi-user](todo/multi-user/) | 16 | 5 |
| [Notifications](todo/notifications/) | 1 | 0 |
| [Plugin ecosystem — before it opens to third parties (2026-08-18)](todo/plugin-ecosystem/) | 3 | 0 |
| [Plugin infrastructure](todo/plugin-infrastructure/) | 2 | 0 |
| [Plugin repos — what writing their READMEs turned up](todo/plugin-repos/) | 10 | 9 |
| [Plugin system — gaps the email extraction found (2026-08-18)](todo/plugin-system/) | 3 | 0 |
| [Prompt library](todo/prompt-library/) | 1 | 0 |
| [SendOff](todo/sendoff/) | 1 | 0 |
| [Settings — portable, and readable by an agent](todo/settings/) | 2 | 0 |
| [Shell — spotlight and the dock](todo/shell/) | 4 | 1 |
| [Sub-agents — agents spawning agents](todo/sub-agents/) | 0 | 2 |
| [Sudo terminal modal](todo/sudo-terminal-modal/) | 1 | 0 |
| [Tooling — the list about the list](todo/tooling/) | 0 | 1 |
| [Transmission](todo/transmission/) | 6 | 0 |
| [URL state — routing, query strings and selection](todo/url-state/) | 4 | 0 |
| [Waiting on the owner to run it](todo/waiting-on-owner/) | 3 | 0 |
| [Workspaces & Panels](todo/workspaces-panels/) | 2 | 0 |
| Theme | Open | Closed |
| --- | --- | --- |
| [Affordances](todo/affordances/) | 1 | 0 |
| [Agents coordinating agents](todo/agent-coordination/) | 2 | 0 |
| [Speaking into a session from the backend](todo/agent-delivery/) | 1 | 1 |
| [Backburner](todo/backburner/) | 3 | 0 |
| [Background jobs](todo/background-jobs/) | 2 | 1 |
| [Chat interface](todo/chat/) | 1 | 0 |
| [Code editor](todo/code-editor/) | 1 | 0 |
| [Components — the shared UI layer](todo/components/) | 1 | 0 |
| [File watchers](todo/file-watchers/) | 1 | 0 |
| [Fleet — one command across every server](todo/fleet/) | 5 | 2 |
| [Headscale](todo/headscale/) | 0 | 5 |
| [Infra (alpha)](todo/infra/) | 7 | 0 |
| [Known bugs](todo/known-bugs/) | 3 | 2 |
| [Mobile apps](todo/mobile-apps/) | 3 | 0 |
| [Multi-user](todo/multi-user/) | 16 | 5 |
| [Notifications](todo/notifications/) | 1 | 0 |
| [Plugin ecosystem — before it opens to third parties (2026-08-18)](todo/plugin-ecosystem/) | 3 | 0 |
| [Plugin infrastructure](todo/plugin-infrastructure/) | 2 | 0 |
| [Plugin repos — what writing their READMEs turned up](todo/plugin-repos/) | 10 | 9 |
| [Plugin system — gaps the email extraction found (2026-08-18)](todo/plugin-system/) | 3 | 0 |
| [Prompt library](todo/prompt-library/) | 1 | 0 |
| [SendOff](todo/sendoff/) | 1 | 0 |
| [Settings — portable, and readable by an agent](todo/settings/) | 2 | 0 |
| [Shell — spotlight and the dock](todo/shell/) | 4 | 1 |
| [Sub-agents — agents spawning agents](todo/sub-agents/) | 0 | 2 |
| [Sudo terminal modal](todo/sudo-terminal-modal/) | 1 | 0 |
| [Tooling — the list about the list](todo/tooling/) | 0 | 1 |
| [Transmission](todo/transmission/) | 6 | 0 |
| [URL state — routing, query strings and selection](todo/url-state/) | 4 | 0 |
| [Waiting on the owner to run it](todo/waiting-on-owner/) | 3 | 0 |
| [Workspaces & Panels](todo/workspaces-panels/) | 2 | 0 |
## Records — no items, kept for the reasoning
@@ -65,6 +65,7 @@ the owner's OS user and can never be granted. Indirection there really is accide
## Newest ten
- `2026-08-25` **Resurrect Projects/Apps** — [backburner/resurrect-projects-apps](todo/backburner/resurrect-projects-apps.md)
- `2026-08-23` **A worker cannot verify that the owner delegated to a manager, so it has to ask every time** — [agent-coordination/a-peer-cannot-verify-a-delegation](todo/agent-coordination/a-peer-cannot-verify-a-delegation.md)
- `2026-08-23` **An agent cannot learn its own transcript id, so it cannot sign its own work** — [agent-coordination/an-agent-cannot-learn-its-own-session-id](todo/agent-coordination/an-agent-cannot-learn-its-own-session-id.md)
- `2026-08-23` **The SendOff file size limit is one constant for everybody** — [sendoff/per-user-size-limit](todo/sendoff/per-user-size-limit.md)
@@ -74,4 +75,3 @@ the owner's OS user and can never be granted. Indirection there really is accide
- `2026-08-22` **A user's settings should export and import as a plain file** — [settings/a-user-s-settings-should-export-and-import-as](todo/settings/a-user-s-settings-should-export-and-import-as.md)
- `2026-08-22` **The same for system settings, owned by the Super Admin** — [settings/the-same-for-system-settings-owned-by-the](todo/settings/the-same-for-system-settings-owned-by-the.md)
- `2026-08-22` **All keyboard shortcuts configurable** — [shell/all-keyboard-shortcuts-configurable](todo/shell/all-keyboard-shortcuts-configurable.md)
- `2026-08-22` **Ctrl+? shows every keyboard shortcut in a modal** — [shell/ctrl-shows-every-keyboard-shortcut-in-a-modal](todo/shell/ctrl-shows-every-keyboard-shortcut-in-a-modal.md)
+101
View File
@@ -0,0 +1,101 @@
---
id: backburner/resurrect-projects-apps
title: "Resurrect Projects/Apps"
theme: backburner
status: open
created: 2026-08-25
date_source: stated
order: 3
---
**Resurrect Projects/Apps.** The idea is not settled — this card exists so the archaeology is not done
twice. Everything below was read out of git on 2026-08-25.
## What existed
Two features, one cluster, removed a day apart.
**User apps — born `fd4d77a3`, 2026-02-27:** *"user app publishing system — build, serve, and use
personal apps in workspace panels."* You wrote an app, published it, and it appeared as a **first-class
workspace panel** beside Terminal and Chat. `/api/apps` (298 lines) built and served it; `/api/app-serve`
served the built output; `/api/dev-server` (314 lines) plus a websocket proxy ran it live; a shared
`html-rewrite.ts` made both viewable through the platform's own origin.
**`/projects` — the authoring surface.** A list screen and a project screen, a 244-line list panel, a
**612-line preview panel**, a publish dialog. Projects had a *type*, a *template*, and
`hasBackend` / `hasAuth` flags — so it was scaffolding as well as hosting. A `projects` table, and
`proj-meta` / `proj-layout` / `proj-terminals` / `proj-host-terminals` branches in the dashboards
endpoint.
## Why each went
**`/projects`, `5a1e3d7e`, 2026-07-30.** Not a design failure — a scheduling one:
> Being retired, so it is deleted rather than fixed — it had both defects dashboards just had (edit
> dropping `?selected=`, an abandoned edit following you onto the next item) and repairing them was
> work for something on its way out.
**Apps, `188b45c1`, 2026-07-31.** The rest of the cluster, **1,440 deletions**: `/api/apps`,
`/api/app-serve`, `/api/dev-server` and its websocket proxy, `html-rewrite`, the Preview panel, the
UserApp panel and header, `useUserApps`, `/settings/apps`, `getUserProjectsDir`, `getUserAppsDir`, the
`ProjectType` and `ProjectDefinition` types, and the `dev-server` websocket provider.
**Nothing on disk was touched.** Both commits say so explicitly. Whatever was under `Projects/` is still
there.
## The interesting part: the App Registry used to be dynamic
This is the piece worth understanding before rebuilding anything. Alongside the compiled-in apps:
```tsx
const { registerApp } = useAppRegistry(apps);
const { apps: userApps, email } = useUserApps();
registerApp(`${email}/${app.slug}`, {
name: app.name,
icon: resolveIcon(app.icon),
component: createUserAppPanel(app.slug),
header: createUserAppHeader(app.name, resolveIcon(app.icon)),
});
```
Keyed per user, with the icon resolved from a **string name** at runtime (`utils/resolve-icon.ts`, 116
lines — also deleted).
**That capability is gone, and the argument against it is good.** The note left where it stood:
> there is no `registerApp` any more because nothing ever called one, and a registry that can be added
> to at runtime is a registry whose contents depend on what has mounted so far.
Today `seedAppRegistry` writes the registry once, before anything renders, from 17 static meta lists.
**So the constraint to design around, rather than re-litigate: user apps need to reach the registry
without making it mutable at runtime.** The plugin system — which arrived *after* this was deleted —
already solved a version of exactly this by generating `Plugins.gen` at build time and mounting plugin
routers at boot. Any resurrection should start by asking whether a user app is just a plugin with a
different author, rather than a second mechanism beside it.
## What survived, and is still working
**`dev-proxy`** (`/api/dev-proxy/5173/…` → `127.0.0.1:5173`). The reasoning in its header is worth
reading before rebuilding the dev-server half — it explains why neither obvious approach works:
`http://localhost:5173` resolves on the *viewer's* machine, and `http://<server>:5173` is mixed content
inside an https page. So the bytes must arrive over the platform's own origin. It costs no certificate,
no proxy-host entry, and no open port, and it lets a dev server stay bound to loopback.
Its stated limit: the app believes it is at `/` and is not. Absolute paths are rewritten on the way out,
which covers Bun's dev server and ordinary relative assets, but not an app that builds URLs in ways the
rewrite cannot see.
## Open questions, if this is picked up
1. **Is a user app a plugin?** The app store, the plugin manifest, `ownerOnly`, sidecars and
`Plugins.gen` all landed after this was removed. Rebuilding a parallel mechanism would be the
expensive mistake.
2. **What is the scaffolding half worth?** Templates, `hasBackend`, `hasAuth` — the agent can now write
an app from a prompt, which may make a template picker the least valuable part of what was lost.
3. **Multi-user changes the shape.** The old key was `${email}/${slug}`, written when the platform was
effectively single-user. Whose apps appear in whose dock is now a permissions question, not a
namespacing one.
4. **Does it need its own theme?** It is in `backburner` because the idea is not settled. If it becomes
real it is bigger than one card.