duxt dev

duxt dev#

Start the development server with hot reload, automatic route generation, and live browser updates.

Usage#

duxt dev [options]

What It Does#

When you run duxt dev, the CLI:

  1. Generates Routes - Scans pages/ directories and creates route mappings
  2. Starts API Server - Launches server/main.dart if it exists
  3. Starts Frontend Server - Runs jaspr serve for the Jaspr application
  4. Watches for Changes - Monitors files and triggers rebuilds
  5. Updates Browser - Sends live updates via WebSocket

Options#

OptionDescriptionDefault
--port, -p Base port (api=+1, jaspr=+2, webdev=+3) 4000
--no-apiSkip API serverfalse
--desktop Open in native desktop window (Tauri) false
--verbose, -v Show detailed logs false
--perfPrint rebuild stage timingsfalse
--reload Use module reload mode (faster, experimental) false
--desktop Run in a native desktop window (Tauri) false

Examples#

# Default ports
duxt dev

# Custom base port (api=3001, jaspr=3002, etc.)
duxt dev --port=3000

# Frontend only (no API server)
duxt dev --no-api

# Show rebuild performance timings
duxt dev --perf

# Use module reload mode for faster hot reloads
duxt dev --reload

# Run multiple apps simultaneously
duxt dev --port=4000   # App 1
duxt dev --port=5000   # App 2

# Desktop mode - opens native window
duxt dev --desktop

Output#

When the server starts successfully:

╭─────────────────────────────────────╮
│  Duxt Development Server            │
╰─────────────────────────────────────╯

→ Generating routes...Found 8 pages in 4 modules
  ✓ Generated .generated/routes.dart

→ Starting API server...API running at http://localhost:3001Starting Jaspr server...Compiling...Ready!

  App:  http://localhost:4000
  API:  http://localhost:3001

Watching for changes...

Route Generation#

The dev server automatically generates routes from your pages/ directories:

lib/
  home/pages/index.dart        -> /
  about/pages/index.dart       -> /about
  blog/pages/
    index.dart                 -> /blog
    _id_.dart                  -> /blog/:id
    _id_/edit.dart             -> /blog/:id/edit
  contact/pages/index.dart     -> /contact

Route files are generated to .generated/routes.dart. The generator only rewrites the file when routes actually change, preventing unnecessary build_runner rebuild cycles. Only structural file changes (adding or removing pages) trigger route regeneration — editing existing pages does not.

Namespace Routes#

Namespaced modules are discovered recursively:

lib/
  admin/
    layouts/default.dart       AdminLayout (auto-wraps)
    posts/pages/index.dart     -> /admin/posts
    users/pages/index.dart     -> /admin/users
  theme/
    home/pages/index.dart      -> /
    blog/pages/index.dart      -> /blog

See Namespaces for details.

Dynamic Routes#

Use underscores for dynamic segments:

FileRoute
_id_.dart:id
_slug_.dart:slug
_...all_.dart*all (catch-all)

Performance Tracing#

Use --perf to diagnose slow rebuilds:

duxt dev --perf

Each rebuild prints stage timings:

Rebuild: save→build 1.2s | build→compile 3.4s | compile→reload 0.1s | total 4.7s

This helps identify whether slowness comes from build_runner analysis, compilation, or browser reload.

Hot Reload#

The dev server supports two types of updates:

Hot Reload (Stateful)#

When you modify component code, the browser updates without losing state:

  • Component changes
  • Style changes
  • Minor logic changes

Use --reload for experimental module-level reload (faster but can be less stable):

duxt dev --reload

Full Reload#

Some changes require a full page reload:

  • Route changes (pages added or removed)
  • Layout changes
  • Server restart

Content Hot Reload#

Markdown and YAML files in content/ directories are reloaded instantly without triggering a full build_runner cycle.

Browser Overlay#

A development overlay appears in the browser showing build status:

  • Building - Code is compiling
  • Ready - Build complete, app is ready
  • Error - Build failed with error details

The overlay automatically hides after successful builds.

API Proxy#

In development, the frontend server proxies API requests to the API server:

Browser → localhost:4000/api/* → localhost:3001/api/*

This allows same-origin requests without CORS configuration.

Environment Variables#

Set environment variables for development:

# Using shell
API_URL=http://localhost:3001 duxt dev

# Or in .env file (auto-loaded)
API_URL=http://localhost:3001

Desktop Development#

Run duxt dev --desktop to launch your app in a native Tauri window instead of the browser.

duxt dev --desktop

This starts the normal Duxt dev server and additionally:

  • Compiles the Tauri native shell
  • Opens a native window pointing at the dev server
  • Hot reloads both Dart and CSS in the native window

On first run, the src-tauri/ directory is auto-scaffolded if it doesn't exist. Requires Rust from rustup.rs.

Tauri output is prefixed with [desktop]:

[desktop] Running cargo tauri dev...
[desktop] Compiling my-app v0.1.0
[desktop] Finished dev [unoptimized + debuginfo]

Use --verbose to see full Rust compilation progress:

duxt dev --desktop --verbose

See Desktop Apps for full documentation.

Troubleshooting#

Port Already in Use#

Error: Port 4000 is already in use

Either stop the other process or use a different port:

duxt dev --port=4001

API Server Not Starting#

Ensure server/main.dart exists and has correct syntax:

dart analyze server/main.dart

Build Stuck#

If the build seems stuck, check for:

  • Syntax errors in your code
  • Missing dependencies
  • Circular imports

Run with verbose mode for more details:

duxt dev --verbose

Database Issues#

For server mode projects, ensure the database is initialized:

// server/main.dart
await DuxtOrm.init(SqliteDatabase('data.db'));
await DuxtOrm.migrate();