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 endFunctions
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_inspectorPlug 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)Returns true when MARCH_ENV is "dev" or "development" (or unset, since dev is the default when no environment is specified).
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)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()
endMiddleware 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_plugMiddleware that adds a Server-Timing response header.
Useful for measuring time spent in the browser DevTools Network panel.
conn |> Bastion.Dev.server_timing