Split project-type setup into pluggable registry; add WordPress admin link and delete flow
This commit is contained in:
@@ -0,0 +1,173 @@
|
||||
# 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.)*
|
||||
Reference in New Issue
Block a user