{service.name}
-- {detail} -
- ) : null} -
- {service.command}
-
-
- {service.cwd}
-
- diff --git a/AGENTS.md b/AGENTS.md index 329adee..b7b8d6e 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -3,7 +3,8 @@ READ ~/Code/agent-scripts/AGENTS.MD BEFORE ANYTHING (skip if file missing). Anton owns this project. Say hi when you start! -Any changes made should update the Unreleased section in CHANGELOG.md. +Only user-facing changes should update the Unreleased section in CHANGELOG.md. +Internal notes, planning docs, repo instructions, and similar housekeeping changes do not need changelog entries. If a changelog entry is later fixed by a follow-up change, merge the follow-up into the original entry instead of adding a new bullet. Any code or docs change should be followed immediately by a fresh build so local testing uses current artifacts. Keep the local `devservers` binary in `$PATH` and any `pnpm link` usage pointed at the latest repo build output so CLI testing always exercises the newest changes. diff --git a/CHANGELOG.md b/CHANGELOG.md index 65358e8..02ddd36 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,17 @@ ## Unreleased +### Changed +- Success notifications in the UI now dismiss automatically after five seconds, while actionable error notifications remain until dismissed manually. +- Refreshed the compact service dashboard with `@24letters/ui`, accessible forms and confirmations, responsive navigation, and clearer service actions and log connection states. +- CLI mutations verify daemon identity and canonical config paths. HTTP failures no longer trigger implicit daemon startup or restart, and requests have bounded deadlines and validated responses. +- Catalog reads no longer unregister missing projects or stop their services. Project removal is explicit, and invalid compose reloads retain the last valid service catalog. + +### Fixed +- Serialized config updates, port reservations, and lifecycle cascades to prevent lost updates, duplicate allocations, and overlapping start/stop operations. Daemons acquire storage ownership locks to prevent competing writers. +- Project registration validates before saving, and project removal only targets its own services. Interrupted service startup cleans up partially initialized panes. +- Log streams reject unknown services, bound polling and buffering, and stop work on disconnect. Stale port detection cannot update a replacement service, and daemon shutdown cancels its own work while preserving service panes. + ## 0.6.0 - 2026-07-15 ### Added diff --git a/IDEAS.md b/IDEAS.md new file mode 100644 index 0000000..f306a18 --- /dev/null +++ b/IDEAS.md @@ -0,0 +1,15 @@ +# Ideas + +## Fully Managed Environment Variable Onboarding + +When a project is fully all-in on `devservers`, onboarding can become fully guided. +When the user first tries to start the project, `devservers` can ask for any missing +`.env` variables or secrets in a wizard-style flow. + +In the command line, this could use a prompt style similar to `create-t3-app`, +asking the user questions about the required environment variables. In the UI, the +experience can be richer: the app can ask for the variables, store them, and keep +them managed from then on. + +The user then never has to worry about the contents of `.env.local`, `.env`, or +similar files. Environment variables are always fully managed by `devservers`. diff --git a/apps/ui/README.md b/apps/ui/README.md index d2e7761..99cb51b 100644 --- a/apps/ui/README.md +++ b/apps/ui/README.md @@ -1,73 +1,32 @@ -# React + TypeScript + Vite +# Devservers UI -This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules. +React dashboard for the Devservers daemon. Built with Vite, Tailwind CSS v4, and the +[`@24letters/ui`](https://github.com/atimmer/ui) component library (Base UI primitives, +Phosphor icons, Inter and Newsreader fonts). -Currently, two official plugins are available: +## Structure -- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react) uses [Babel](https://babeljs.io/) (or [oxc](https://oxc.rs) when used in [rolldown-vite](https://vite.dev/guide/rolldown)) for Fast Refresh -- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh +- `src/App.tsx` composes the shell, dialogs, and confirmation flow. +- `src/hooks/` owns data flow: `use-services` polls the daemon with cancellation, + `use-selection` persists the main-pane target, `use-service-actions` runs lifecycle + actions with cascade confirmation, and `use-log-stream` keeps the log websocket alive + with reconnects. +- `src/components/` holds presentational pieces; `components/dialogs/` holds the add, + edit, project, and compose-definition dialogs. +- `src/lib/status.ts` maps service statuses to the `--status-*` tokens defined in + `src/index.css`. `src/lib/notify.ts` wraps Sonner toasts: successes dismiss after five + seconds, errors stay until dismissed. +- `src/api.ts`, `src/dashboard.ts`, and `src/logs.ts` are transport and pure helpers. -## React Compiler +## Development -The React Compiler is not enabled on this template because of its impact on dev & build performances. To add it, see [this documentation](https://react.dev/learn/react-compiler/installation). +Do not run `pnpm dev` directly; the dev server is managed by the `devservers` CLI. +Point the UI at a different daemon or mock with `VITE_DAEMON_URL`. -## Expanding the ESLint configuration +Keyboard: `/` focuses the service filter, `Cmd+B` toggles the sidebar. -If you are developing a production application, we recommend updating the configuration to enable type-aware lint rules: - -```js -export default defineConfig([ - globalIgnores(['dist']), - { - files: ['**/*.{ts,tsx}'], - extends: [ - // Other configs... - - // Remove tseslint.configs.recommended and replace with this - tseslint.configs.recommendedTypeChecked, - // Alternatively, use this for stricter rules - tseslint.configs.strictTypeChecked, - // Optionally, add this for stylistic rules - tseslint.configs.stylisticTypeChecked, - - // Other configs... - ], - languageOptions: { - parserOptions: { - project: ['./tsconfig.node.json', './tsconfig.app.json'], - tsconfigRootDir: import.meta.dirname, - }, - // other options... - }, - }, -]) -``` - -You can also install [eslint-plugin-react-x](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-x) and [eslint-plugin-react-dom](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-dom) for React-specific lint rules: - -```js -// eslint.config.js -import reactX from 'eslint-plugin-react-x' -import reactDom from 'eslint-plugin-react-dom' - -export default defineConfig([ - globalIgnores(['dist']), - { - files: ['**/*.{ts,tsx}'], - extends: [ - // Other configs... - // Enable lint rules for React - reactX.configs['recommended-typescript'], - // Enable lint rules for React DOM - reactDom.configs.recommended, - ], - languageOptions: { - parserOptions: { - project: ['./tsconfig.node.json', './tsconfig.app.json'], - tsconfigRootDir: import.meta.dirname, - }, - // other options... - }, - }, -]) +```sh +pnpm typecheck +pnpm lint +pnpm build ``` diff --git a/apps/ui/index.html b/apps/ui/index.html index 592716b..a13b507 100644 --- a/apps/ui/index.html +++ b/apps/ui/index.html @@ -1,10 +1,11 @@ - +
- + -
- {subtitle}
-
-
+ {subtitle}
+
+ ) : null}
+ - {error} -
- ) : null} -- {error} -
- ) : null} -
- {definition?.path}
-
-
- {loading ? "Loading…" : JSON.stringify(definition?.definition ?? {}, null, 2)}
-
-
- {this.state.error.stack}
-
- ) : null}
- {command}
- - {streamError} -
- ) : null} -- {detail} -
- ) : null} -
- {service.command}
-
-
- {service.cwd}
-
-
+ {this.state.error.stack}
+
+ ) : null}
+ {command}
+ + {service.status === "running" || service.status === "starting" + ? "Waiting for output…" + : "No output captured."} +
+ ) : null} +{service.command}}
+ {service.command}
+ {service.cwd}
+ + {services.length === 0 ? "No services registered." : "No matching services."} +
+ ) : ( +