# Aurora Dockside — Build Session Log

A record of the conversation that produced this project: an Electron + React +
TypeScript desktop GUI for managing [DDEV](https://ddev.com) local development
environments, built as an independent clone of
[DDEV Manager](https://github.com/DDEV-Manager/ddev-manager) (Tauri + React + Rust).

## Origin

The session started with an unrelated request — install and configure DDEV
itself (Homebrew, OrbStack as the container runtime, mkcert for trusted local
HTTPS). Partway through, the idea came up: rather than using the existing
DDEV Manager app, build an equivalent from scratch, in our own code.

### Tech stack decisions (asked up front)

- **Framework**: Electron + React + TypeScript, chosen over matching the
  original's Tauri/Rust stack — no Rust toolchain required.
- **Scope**: Full feature parity with DDEV Manager, built incrementally
  (each step runnable/testable) rather than scaffolding everything blind.
- **Package manager**: pnpm, enabled via `corepack enable`.
- **Name**: Aurora Dockside (chosen by the user over a couple of suggested
  alternatives).

A formal plan was written (Plan Mode) covering architecture (Electron main
process owns all `ddev` CLI execution; typed `window.api` surface via
contextBridge; TanStack Query + Zustand on the renderer side) and a 9-step
build order before any code was written.

## Build steps (each committed separately, each verified against a real
running DDEV project — not just typechecked)

1. **Scaffold** — `electron-vite` + React 19 + TypeScript template via
   `@quick-start/create-electron`, git-initialized on `main`.
2. **Tailwind CSS 4, Vitest, core libraries** — Tailwind via the Vite
   plugin, Vitest + React Testing Library, Zustand, TanStack Query,
   Lucide icons. Stripped the electron-vite demo boilerplate.
3. **Core project management** — `ddev.ts` CLI wrapper (execFile +
   JSON envelope parsing), IPC handlers, typed preload API, TanStack Query
   hooks, two-pane UI (project list + detail panel). Includes a PATH
   fallback in the main process, since GUI apps launched outside a
   terminal don't inherit the shell's PATH and can't find Homebrew's
   `ddev` binary otherwise.
4. **Terminal panel, status bar, toasts** — long-running commands
   (start/stop/restart) now spawn via a `commandRunner.ts` module and
   stream stdout/stderr to the renderer over IPC instead of waiting for
   the whole command to finish. Cancel support kills the tracked child
   process by operation id.
5. **Database tools** — snapshot create/list/restore/delete, DB
   import/export via native file dialogs. `ddev snapshot restore` has no
   project-name flag (unlike other ddev commands), so it runs with
   `cwd` set to the project's approot instead.
6. **Add-on management** — registry browser (~270 third-party add-ons)
   with search, install/remove via `ddev add-on get/remove`. Verified
   working with the project stopped.
7. **Log viewer** — `ddev logs -f` streamed over a dedicated IPC channel
   (decoupled from the terminal/status-bar model, since log tailing runs
   indefinitely rather than completing). Service switcher, text filter.
8. **Project creation wizard** — native directory picker, project name,
   project type selector, optional docroot, streamed `ddev config`.
9. **Settings** — theme (light/dark/system, persisted), zoom controls via
   a small main-process IPC (`webContents.setZoomLevel`), keyboard
   shortcuts (Cmd/Ctrl+N, +comma, +=/-/0).
10. **Packaging** — cleaned up `electron-builder.yml` (correct appId/
    productName, removed irrelevant camera/mic/Documents/Downloads
    Info.plist entries, removed a placeholder auto-update publish
    config). Verified with a real `pnpm build:unpack` run, launching the
    packaged (unsigned, no Developer ID cert available) `.app` directly
    and confirming it could still find and run `ddev`.

Scoped down from full parity, on purpose: composer/wp-cli-based CMS
scaffolding for Drupal/Laravel/Shopware, and auto-update infrastructure.

## Bugs found via live testing (not just code review)

Every feature was verified by actually driving the running app — mostly via
a small CDP (Chrome DevTools Protocol) driver script that clicked real
buttons in the real Electron window, since a lot of this app's correctness
depends on real subprocess/IPC/timing behavior that static review can't
catch. This caught several real defects:

- **`window.prompt()` doesn't work in Electron's renderer** — it returns
  `null` immediately with no dialog, unlike `window.confirm()` which does
  show a real native dialog. The snapshot-naming UI was rewritten to use
  an inline text input instead.
- **`ddev addon list --installed` omits the `raw` JSON key entirely** when
  nothing is installed (unlike `ddev list`/`ddev snapshot --list`, which
  include `raw: null`). The shared JSON-parsing helper treated a missing
  `raw` as an error, so after removing the last add-on the query would
  error on refetch and React Query kept showing the stale cached row.
  Fixed by splitting the helper into a strict variant (for `describe`,
  where missing data really is an error) and a lenient list variant.
- **Log filtering operated on raw stream chunks, not lines** — a single
  chunk of stdout/stderr can bundle many lines or split one across chunk
  boundaries, so filtering by chunk let unrelated lines through. Fixed by
  buffering partial lines per stream and only filtering once full lines
  are assembled.
- **A `react-hooks/set-state-in-effect` lint violation** in the log-stream
  hook, from resetting state synchronously inside an effect body. Fixed
  by keying the streaming component by `service` so switching services
  remounts it — state resets via fresh `useState` initializers instead,
  which is the React-recommended pattern for this.

## Post-launch bug reports and fixes

After the initial 9-step build was declared done, real usage surfaced three
more gaps:

1. **"I created a new container for wordpress, only wp-content was
   created."** — `ddev config --project-type=wordpress` only scaffolds the
   DDEV-managed `wp-config.php` bridge and `wp-content/uploads`; it never
   downloads WordPress core (`wp-admin/`, `wp-includes/`, `index.php`,
   etc.). Fixed the user's existing project directly (`ddev wp core
   download`), then added the missing step to the wizard.
2. **"Now I get 403 Forbidden. Shouldn't we have an option to set admin
   username, password, and email while setting it up?"** — right call:
   `wp core download` only fetches files, `wp core install` is what
   actually creates the database tables and admin user. The wizard's
   WordPress path now chains `configure → start → wp core download →
   wp core install`, with site title/admin username/password/email
   fields shown only for that project type. wp-cli needs the containers
   running, so this path always starts the project regardless of the
   generic "start after creating" checkbox.
3. **"What about the ability to delete the site? I can create all day
   long but not able to delete them from the software."** — a real gap;
   the original DDEV Manager has this and it hadn't been built yet. Added
   a Delete button (`ddev delete <name> --yes`, keeping ddev's default
   database snapshot as a safety net) with a confirmation dialog that
   clarifies it only removes DDEV's registration/containers/database, not
   the project's files on disk.
4. Also added, per a follow-up request: a **WP Admin quick-link** button
   for running WordPress-type projects, opening `{primary_url}/wp-admin/`
   directly.

All three were verified end-to-end against a fresh throwaway project:
full configure→start→download→install chain producing a genuinely working
site (200 on the homepage, correct login redirect on `/wp-admin`), and
delete actually removing the project from `ddev list`. Two apparent bugs
that came up during that verification turned out to be the *test script*
reading DOM state before React had re-rendered, or before ddev's
multi-step delete (build + start + snapshot + teardown) had actually
finished — not real defects.

## Final artifact

A packaged, distributable build was produced on request:

- `dist/aurora-dockside-1.0.0.dmg` — installer
- `dist/Aurora Dockside-1.0.0-arm64-mac.zip` — zipped `.app`

Both unsigned (no Developer ID certificate on this machine) — macOS
Gatekeeper requires right-click → Open on first launch.

## Repository state

10 commits on `main`, one per build step plus the post-launch fixes:

```
Scaffold Aurora Dockside with electron-vite + React + TypeScript
Wire up Tailwind CSS 4, Vitest, and core app libraries
Add core DDEV project management (list/describe/start/stop/restart)
Add streaming terminal panel, status bar, and toast notifications
Add database tools: snapshots and import/export (step 4)
Add add-on management: registry browser, install, remove (step 5)
Add streaming log viewer with service switching and filtering (step 6)
Add project creation wizard (step 7)
Add settings: theme, zoom controls, keyboard shortcuts (step 8)
Finalize packaging config and verify a real build (step 9)
Fix WordPress scaffolding gap; add delete project + WP admin link
```

*(Note: some project files show further edits beyond this log's cutoff —
work continued in the project after this session.)*
