March Docs

Bastion.Dev

lib/dev.march — Bastion.Dev: development-only tools.

Provides live reload (browser refresh on server restart), dev timing middleware, and conn inspection logging. These tools should only be activated when MARCH_ENV is "dev".

── Live Reload ────────────────────────────────────────────────────────────────

When the dev server restarts (forge dev detects a .march change and kills the process), all browser WebSocket connections to /_bastion/reload are dropped. The injected client-side script detects the drop and reloads the page.

Setup (add to your endpoint in dev mode):

-- 1. Add the Dev plugs to your pipeline:
let app = fn conn ->
  let c = Bastion.Dev.live_reload(conn)  -- handles /_bastion/reload and /_bastion/live-reload.js
  ...

-- 2. Add the script tag to your root layout:
<script src="/_bastion/live-reload.js"></script>

Or use the combined helper that checks MARCH_ENV automatically:

let c = if Bastion.Dev.dev_env?() do Bastion.Dev.live_reload(conn) else conn end

Functions

fnconn_inspectorconn_inspector(conn)#

Middleware that logs the full conn state to stdout.

Prints method, path, headers, assigns, and query params.
Useful for debugging request handling.

    conn |> Bastion.Dev.conn_inspector
fndashboarddashboard(conn)#

Plug that serves a dev dashboard at /_bastion.

Shows live request metrics (from Bastion.Metrics), Vault table stats,
and recent request log.

Add this to your dev pipeline before the router:

    let c = Bastion.Dev.dashboard(conn)
fndev_envdev_env() : Bool#

Returns true when MARCH_ENV is "dev" or "development" (or unset, since dev is the default when no environment is specified).

fnlive_reloadlive_reload(conn)#

Plug that handles both the live-reload WebSocket endpoint and the browser JS client file.

  • GET /_bastion/reload (Upgrade: websocket) — keep-alive WebSocket. When the
  dev server restarts and drops the connection, the client reloads the page.
- GET /_bastion/live-reload.js — serves the client-side JavaScript.

Other paths pass through unchanged.

    let c = Bastion.Dev.live_reload(conn)
fnlive_reload_taglive_reload_tag() : String#

Return a <script> HTML tag pointing to the live-reload client JS.

Add this to your root layout when in dev mode:

    if Bastion.Dev.dev_env?() do
      Bastion.Dev.live_reload_tag()
    end
fnrequest_timerrequest_timer(conn)#

Middleware that logs detailed timing for each request.

Adds an X-Request-Time header with the wall-clock time spent.

    let app = fn conn ->
      Bastion.Dev.request_timer(conn)
      |> router_plug
fnserver_timingserver_timing(conn)#

Middleware that adds a Server-Timing response header.

Useful for measuring time spent in the browser DevTools Network panel.

    conn |> Bastion.Dev.server_timing