Deployment Lessons: Vanilla JS UI + Caddy + 1Password
This case study is the mdBook version of the website post:
- https://terraphim.ai/posts/deployment-lessons-vanilla-js-caddy/
It includes the same narrative plus additional technical appendices.
The Problem
We needed to ship a simple UI quickly. The first instinct was to add new infrastructure (Docker, nginx, a frontend framework). That was the wrong move.
The Turning Point
The repo already had a deployment pattern. The lesson was not about tooling. It was about reading and following the existing operational contract.
The Pattern: Boring UI, Fast Deployment
- Vanilla JS means no build step and faster iteration.
- Caddy handles static hosting, HTTPS, and reverse proxying with minimal configuration.
Hybrid Delivery: Polling + WebSocket
Polling provides reliability. WebSocket provides UX.
Combining both yields a system that still works when the real-time channel is flaky.
Secrets: 1Password Runtime Injection
Operational secrets should not land in .env files committed to disk.
The pattern that scales is runtime injection via op run.
Appendix A: Deployment Flow (Mermaid)
flowchart TD
A[Read existing scripts] --> B[Choose minimal UI]
B --> C[Deploy static assets]
C --> D[Configure Caddy]
D --> E[Validate + reload]
F[Secrets] --> G[op run injection]
G --> H[systemd ExecStart]
I[Result delivery] --> J[Polling]
I --> K[WebSocket]
J --> L[Reliable completion]
K --> M[Realtime progress]Appendix B: Primary Sources
- Source notes:
lessons-learned.md
References
- Website case study: https://terraphim.ai/posts/deployment-lessons-vanilla-js-caddy/