← All observations

Field notes / 06 ·

Two protocols.
One development loop.

Open HTTP and HTTPS beside each other. Edit one component. Watch both pages change. Making that ordinary workflow reliable meant following the connection all the way from the browser to the source.

Two paper browser entrances, one with a padlock, connect to a shared website workshop and display the same coral page element.
Two entrances into the same workshop. A conceptual illustration, not a network diagram.

01 / A useful everyday capability

Keep both views open.

Our shared server already gave the frontend and API one application entry point. The next requirement was smaller: make the development site usable over HTTP and HTTPS at the same time, including live component updates.

That lets us inspect the TLS entry point while keeping a plain HTTP view available. There is no need to switch a configuration, restart the application or maintain a second copy of the source just to move between those two views. Both pages reach the same running app.

HTTP · 8080

http://haih.localhost:8080

Page requests through the proxy. Live updates over WebSocket.

HTTPS · 8443

https://haih.localhost:8443

The same app through TLS. Live updates over secure WebSocket.

These are two browser origins, not two applications. Sharing source does not synchronize their browser state or establish that future authentication, storage or API workflows behave identically. It gives us a convenient place to investigate those differences when needed.

02 / The first fix stopped too early

A published port was only part of the answer.

The initial change exposed Vite’s separate HMR port through Docker. That addressed reachability for a plain WebSocket connection. It did not make that listener a TLS endpoint. An HTTPS page could load while its secure update connection still failed.

During review, the first response was to document the limitation. The owner pushed back: working development over HTTPS was the job. Recording why it failed was useful diagnosis, but it did not satisfy the requirement.

A limitation can be accurately documented while the requested work remains unfinished.

Looking at the whole path suggested a simpler arrangement. The app already had an HTTP server. Traefik already handled TLS. Vite could attach its WebSocket server to that existing app listener instead of making the browser reach another published port.

03 / Follow the page’s address

One update path, whichever entrance you use.

Vite now uses /__vite_hmr on the Node HTTP server. The browser derives the host, port and WebSocket protocol from its page address. The HTTP tab connects with ws://; the HTTPS tab connects with wss://. No domain is hardcoded into the HMR configuration.

HTTP page  :8080 → ws://haih.localhost:8080/__vite_hmr
HTTPS page :8443 → wss://haih.localhost:8443/__vite_hmr

Page → Traefik → Varnish (pass) → app
HMR  → Traefik → app WebSocket

Traefik terminates TLS and sends the update connection directly to the app. The container’s application port remains 3000. Direct development access on host port 3001 also uses that same listener; there is no separate 24678 port to publish or coordinate.

This composition uses capabilities of tools already present in the project. Its value is the resulting workflow: the page and its update connection agree about how the browser reaches the site.

04 / Fresh source needs a fresh response

The cache needs a development policy.

A working WebSocket is not enough if a refresh retrieves yesterday’s HTML or module. We kept Varnish in the page request path, but gave development its own VCL: pass every request and return X-Cache: PASS with Cache-Control: no-store.

Production keeps its separate cache policy. Development can still be used for deliberate caching experiments by selecting another VCL, but ordinary source editing no longer depends on remembering to clear a production-style cache.

Starting the actual services caught another integration error. Docker could not mount an extra routing file inside an already read-only dynamic-configuration directory. Selecting a complete development directory fixed the startup failure. Configuration written on disk became evidence only after Traefik actually started with it.

05 / The check follows the claim

Two tabs. One edit. No document reload.

Following the principle from our testing note, we checked the running local Docker path in Chromium. The browser accepted the self-signed development certificate. HTTP and HTTPS pages were open together during the same source edit.

  1. Both pages opened and connected to their respective WS and WSS endpoints.
  2. A temporary visible element was added to a React component. It appeared in both tabs.
  3. A marker on each window survived the update, showing that neither document reloaded.
  4. Restoring the source removed the element from both tabs. A separate HTTPS refresh check returned current content through Varnish.

Type checking, the production build and Compose configuration checks also passed for the implementation. They answer different questions from the live browser experiment. This was a focused check, not a new HMR scenario added to the ordinary production browser suite.

06 / What it costs to use

A small feature that closes a real gap.

The proxied setup needs Docker, the configured network, available ports and a local TLS certificate. The versioned setup guide records the commands. Start the app, Varnish and Traefik together; there is no need to start monitoring just to try this workflow.

Direct npm run dev remains available when the proxy is unnecessary. For work that does involve TLS, the two views can now stay open throughout an edit. That is the useful result of this checkpoint: fewer interruptions between writing a change and seeing it through the entry point we wanted to test.

See the development solution for its requirements and current verification boundary.

Written against 84a5668. Local browser observations were made on 6 October 2026. The AI-generated illustration is conceptual; the connection checks provide the technical evidence.

← Back to the field notes