dev
ajs dms dev serves the dashboard with hot reload. It reads the frontend modules in place, from the backend's own directories, so the backend runs on the same machine.
$ ajs dms dev --help
Usage: ajs dms dev [options]
Run the dev server with hot reload. It reads the frontend modules in place, from
the backend's own directories, so the backend runs on this machine.
Options:
-b, --backend-url <url> Backend URL; when omitted, discovered from the
enclosing antelope project's .antelope/dev.json
(env: DMS_API_BASE_URL)
-p, --port <port> Port to serve on (default: "3001", env: PORT)
-f, --force Reinstall the workspace dependencies
--offline Reuse the last cached manifest instead of
fetching it (env: DMS_OFFLINE)
--bootstrap-secret <secret> Credential for the backend's layer endpoints;
prefer the variable, a command line is visible to
other processes. Discovered from
.antelope/dms-dev.json for the project's own
backend (env: DMS_BOOTSTRAP_SECRET)
-h, --help Show help for a command
Finding the backend
Without -b or DMS_API_BASE_URL, dev walks up from the current directory to the first .antelope/dev.json, the file a running ajs project dev writes. It checks that the process that wrote it is still alive, then reads the API server's address from it. It stops at the first file it finds, so it never attaches to a parent project's backend.
$ ajs dms dev
✖ No backend URL provided and no running antelope project found
Searched for .antelope/dev.json from the current directory upward.
→ Run this command inside an antelope project started with 'ajs project dev'
→ Or pass the backend explicitly with -b <url> (env: DMS_API_BASE_URL)
The bootstrap credential comes the same way: when the backend it calls is the one .antelope/dev.json names, dev reads the credential the development backend publishes in .antelope/dms-dev.json. A credential found this way is never sent to any other backend. An explicit --bootstrap-secret or DMS_BOOTSTRAP_SECRET always wins.
ajs dms dev -b <url> keys it on the URL instead, and shares it with build and start for that URL. See Workspaces and cache.The port
dev reserves its port before it asks the backend for the manifest, and sends the resulting address to the development backend, which serves a matching client URL and allows that origin. When the port is busy, dev moves to the next free one and says so: Port 3001 is busy, using 3002. -p 0 asks for any free port.
The server listens on 127.0.0.1 unless HOST says otherwise. HOST=0.0.0.0 opens it to the network.
Sessions and secrets
dev generates a random session secret when DMS_SESSION_SECRET is not set at all, so every restart signs everyone out. A value you set is kept, but an empty value or one shorter than 32 characters is refused. Cookies are not Secure unless DMS_COOKIE_SECURE says so, since the development server runs over HTTP.
The e-mail render and OAuth relay secrets come from the manifest the backend serves; the Secrets line of the ready block says where each one came from, never its value. A variable you set wins over the manifest. See Configuration.
What reloads, and how
dev copies each module into the workspace and watches its sources, mirroring every edit.
| You change | What happens |
|---|---|
A .vue file, a composable, a style | Vite hot module replacement |
| A component a layer registers | The next server render sets every module up again, into empty registries, so it uses the edited component without a restart |
i18n/locales/*.json | The merged catalogs are regenerated; the open page applies them in place. Adding or removing a locale reloads the page. |
app/app.config.ts | The next server render uses it; the open page updates useDmsAppConfig() and Nuxt UI's config in place |
A file under public/ | Served, or no longer served, at once |
Adding or removing dms.frontend.ts or app/config/shortcuts-registry.ts | The module loader or the aggregated shortcuts are regenerated, and the page reloads |
dms.frontend.build.ts | Vite restarts |
dms.server.ts or a file it imports | The next request uses the edited handler |
| An e-mail template | The e-mail bundle rebuilds in a separate, low-priority process; a render waits for a build in progress |
A layer directory added to or removed from layers/ | The dev server says it needs a restart: Vite reads layer aliases and auto-imported directories at startup only |
When the backend starts serving another set of frontend modules, because a module was installed or removed from the Modules page, dev stops the server, rebuilds the workspace and starts again:
ℹ Frontend modules changed on the backend: rebuilding the workspace
When the backend is down
dev falls back to the last manifest it cached for the workspace, with a warning, and API calls fail until the backend is back. --offline uses the cache without trying the backend. A refused credential never falls back: the cache can hold private options from an earlier authorized run.
Seeing who answers a path
In development, every answer carries an x-dms-route-owner header: renderer, module:<id>, backend:<pattern>, page or not-found.
$ curl -sI http://localhost:3005/api/dms/nothing | grep x-dms-route-owner
x-dms-route-owner: backend:/api/**
See Routing and the backend proxy for the order the server follows.
Stopping
Ctrl+C stops the server and exits with code 130:
■ Stopped the dev server · ran 3.2s