Skip to content

Latest commit

Β 

History

History
285 lines (221 loc) Β· 11 KB

File metadata and controls

285 lines (221 loc) Β· 11 KB

DevMagic Architecture

This document describes the architecture, design decisions, and separation of concerns in DevMagic.

Overview

DevMagic provides portable development environments using VS Code Dev Containers. The goal is to enable developers to go from "fresh OS" to "coding" in minutes with zero host installation (except container runtime + VS Code).

Design Principles

  1. Zero friction - Minimize steps from "fresh OS" to "coding"
  2. Consistency - Same environment on every machine
  3. Modularity - Start minimal, add services as needed
  4. Transparency - Open source, well-documented, no magic
  5. Portability - Works on Windows, Linux, macOS identically
  6. Separation of concerns - Container infrastructure vs personal preferences

Separation of Concerns

DevMagic deliberately separates container infrastructure from personal environment preferences:

Container Concerns (DevMagic)    ↔️   User Concerns (Dotfiles)
──────────────────────────────────────────────────────────────
.devcontainer/Dockerfile              dotfiles/shell/install.sh
β”œβ”€ Base image (typescript-node)       β”œβ”€ Homebrew installation
└─ System packages (tmux, nvim, ...)  β”œβ”€ fzf, hugo, babashka
                                      β”œβ”€ Zsh plugins
.devcontainer/docker-compose.yml      β”œβ”€ VS Code settings symlinks
β”œβ”€ Workspace + dotfiles mounts        └─ Shell configuration
β”œβ”€ tmpfs /tmp, hostname, network
└─ Example extra services (profiles)  dotfiles/shell/init.sh
                                      β”œβ”€ Runtime shell behavior
.devcontainer/devcontainer.json       β”œβ”€ PATHs, aliases, functions
β”œβ”€ Features, extensions               └─ Sourced on every shell start
└─ Host env forwarding (localEnv)

Why This Separation?

DevMagic stays focused on container infrastructure:

  • Works for anyone using DevMagic
  • No personal preferences baked in
  • Minimal and maintainable

Dotfiles handle personal environment:

  • Your settings follow you everywhere (not just containers)
  • Editor-agnostic (VS Code, Neovim, Cursor, etc.)
  • Full version control of your preferences
  • Works on any machine, not just dev containers

The Install Script Location

Q: Should install.sh be in DevMagic or dotfiles?

A: It should stay in your dotfiles repo.

The current design is correct:

  • DevMagic = portable dev container infrastructure (works for anyone)
  • Dotfiles = your personal preferences (only applies to you)

Dotfiles are bind-mounted from the host instead of cloned inside the container:

# .devcontainer/docker-compose.yml (dev service; <project> is filled in by
# the installer from your project folder name)
volumes:
    - ..:/workspaces/<project>
    - ${HOME}${USERPROFILE}/.config/dotfiles:/home/node/.config/dotfiles

Optionally, the commented postCreateCommand in devcontainer.json (curl -fsSL https://devmagic.run/setup | bash) installs extras (oh-my-zsh, fzf) and links the mounted dotfiles' shell/init.sh into the container's .bashrc/.zshrc.

This means:

  • βœ… Your machine: One dotfiles folder shared by the host and every container, always in sync
  • βœ… Someone else using DevMagic: Gets a working container (no dotfiles folder β†’ Docker creates an empty one; nothing breaks)
  • βœ… No coupling: DevMagic works without dotfiles; dotfiles are optional enhancement

Installation Flow

User runs: curl -fsSL https://devmagic.run/install | bash
    β”‚
    β–Ό
/install endpoint β†’ fetches setup/devmagic.sh from GitHub
    β”‚
    β–Ό
devmagic.sh downloads the templates (templates/devcontainer/), fills in
the project folder name (sanitized), and writes ready-to-use files into
.devcontainer/ in the current dir:
  β”œβ”€ devcontainer.json
  β”œβ”€ docker-compose.yml
  └─ Dockerfile
(every shared value β€” mount path, Compose project name, hostname, image
tag β€” is baked in consistently; no .env, no placeholders left)
    β”‚
    β–Ό
User opens in VS Code and chooses "Reopen in Container"
    β”‚
    β–Ό
Container starts:
  β”œβ”€ Docker Compose builds the image from the Dockerfile
  β”œβ”€ devcontainer.json forwards host TZ/locale via ${localEnv:*}
  β”œβ”€ ~/.config/dotfiles is mounted from the host (optional)
  └─ Optional postCreateCommand: curl -fsSL https://devmagic.run/setup | bash
        β”‚
        β–Ό
    devcontainer-setup.sh (opt-in, commented out by default):
      β”œβ”€ Extra system packages (jq, ripgrep, fd, ...)
      β”œβ”€ oh-my-zsh and fzf
      └─ Links dotfiles' shell/init.sh into .bashrc/.zshrc
View as Mermaid diagram
flowchart TD
    A["User runs: curl devmagic.run/install | bash"] --> B["/install endpoint<br/>fetches setup/devmagic.sh"]
    B --> C["devmagic.sh downloads templates from<br/>templates/devcontainer/"]
    C --> C2["Fills in the project folder name and writes<br/>devcontainer.json, docker-compose.yml,<br/>Dockerfile into .devcontainer/"]
    C2 --> D["User opens in VS Code<br/>and reopens in container"]
    D --> E["Docker Compose builds<br/>the image from the Dockerfile"]
    E --> F["devcontainer.json forwards host<br/>TZ/locale via localEnv"]
    F --> G["~/.config/dotfiles mounted<br/>from the host (optional)"]
    G --> H["Optional postCreateCommand:<br/>curl devmagic.run/setup | bash"]

    H --> I["Extra system packages"]
    H --> J["oh-my-zsh and fzf"]
    H --> K["Links dotfiles shell/init.sh<br/>into .bashrc/.zshrc"]

    style A fill:#e1f5ff
    style E fill:#fff4e1
    style H fill:#f0f0f0
Loading

Homebrew vs Conda

For CLI tools like fzf, babashka, and hugo, Homebrew is recommended over Conda:

Aspect Homebrew βœ… Conda
Purpose CLI tools and system packages Python-centric ecosystem
Package availability Wide (fzf, babashka, hugo) Limited for non-Python tools
Licensing Free and open Commercial license concerns
Conflicts N/A Known conflicts with Homebrew

Custom Forks for Security

Security-critical tools are installed from custom forks for auditability:

  • fzf: marcelocra/fzf β†’ Fuzzy finder
  • zsh-autosuggestions: marcelocra/zsh-autosuggestions
  • zsh-syntax-highlighting: marcelocra/zsh-syntax-highlighting

This allows:

  • Code review before updates
  • Version pinning for stability
  • No supply chain attacks from upstream

VS Code Configuration Strategy

VS Code settings and keybindings are stored in the dotfiles repo and symlinked:

Dotfiles: ~/.config/dotfiles/apps/vscode/User/
β”œβ”€ settings.json
└─ keybindings.json
        β”‚
        β–Ό (symlinked by install.sh)

Container: ~/.vscode-server/data/User/
β”œβ”€ settings.json β†’ ~/.config/dotfiles/apps/vscode/User/settings.json
└─ keybindings.json β†’ ~/.config/dotfiles/apps/vscode/User/keybindings.json

The install.sh script detects the VS Code environment and symlinks accordingly:

  • Remote container: ~/.vscode-server/data/User/
  • Native Linux: ~/.config/Code/User/
  • Native macOS: ~/Library/Application Support/Code/User/

Scripts Overview

setup/devmagic.sh

  • Entry point for curl https://devmagic.run/install | bash
  • Downloads the templates from templates/devcontainer/, fills in the project folder name (sanitized to Compose naming rules), and writes ready-to-use files into the user's .devcontainer/
  • Every value shared between devcontainer.json and docker-compose.yml is baked in consistently β€” no .env files or placeholders left behind (see ADR 0005)

setup/devcontainer-setup.sh

  • Optional postCreateCommand (ships commented out in devcontainer.json)
  • Installs extra packages, oh-my-zsh and fzf
  • Links the mounted dotfiles' shell/init.sh into .bashrc/.zshrc if present

dotfiles/shell/install.sh (in user's dotfiles repo)

  • One-time setup for personal tools and preferences
  • Installs Homebrew, CLI tools, zsh plugins
  • Creates shell config symlinks
  • Symlinks VS Code settings/keybindings
  • Idempotent (safe to run multiple times)
  • Environment-aware (detects container vs native)

dotfiles/shell/init.sh (in user's dotfiles repo)

  • Runtime shell configuration
  • Sourced on every shell start (must be fast!)
  • Sets up PATHs, aliases, functions
  • No installation logic (that's in install.sh)

Feature Flags

The dotfiles install.sh supports feature flags for customization:

# Skip specific components
DOTFILES_SKIP_HOMEBREW=true ./install.sh
DOTFILES_SKIP_CLI_TOOLS=true ./install.sh
DOTFILES_SKIP_ZSH_PLUGINS=true ./install.sh
DOTFILES_SKIP_VSCODE=true ./install.sh

# Enable debug logging
DOTFILES_DEBUG=1 ./install.sh

File Organization

devmagic/
β”œβ”€β”€ templates/
β”‚   └── devcontainer/        # The source of truth ({{PROJECT_NAME}} placeholder)
β”‚       β”œβ”€β”€ devcontainer.json
β”‚       β”œβ”€β”€ docker-compose.yml
β”‚       └── Dockerfile
β”œβ”€β”€ .devcontainer/           # Filled copy for this repo (project name: devmagic),
β”‚   β”‚                        # so standalone/maintainer clones work out of the box.
β”‚   β”‚                        # Regenerate with ./setup/generate.sh after editing
β”‚   β”‚                        # the templates.
β”‚   β”œβ”€β”€ devcontainer.json   # Dev Container definition (Compose based)
β”‚   β”œβ”€β”€ docker-compose.yml  # dev service + commented example service
β”‚   └── Dockerfile          # Dev image (typescript-node + CLI tools)
β”œβ”€β”€ setup/
β”‚   β”œβ”€β”€ devmagic.sh         # Installer: downloads templates, fills project name
β”‚   β”œβ”€β”€ generate.sh         # Fills templates locally (repo checkouts)
β”‚   └── devcontainer-setup.sh # Optional container extras (opt-in postCreate)
β”œβ”€β”€ www/                     # Website source (devmagic.run)
β”‚   β”œβ”€β”€ app/
β”‚   β”‚   β”œβ”€β”€ install/route.ts # Serves devmagic.sh
β”‚   β”‚   └── setup/route.ts   # Serves devcontainer-setup.sh
β”‚   └── ...
└── docs/                    # Documentation
    └── ARCHITECTURE.md     # This file

dotfiles/ (separate repo, mounted at ~/.config/dotfiles)
β”œβ”€β”€ shell/
β”‚   β”œβ”€β”€ init.sh             # Runtime configuration (sourced)
β”‚   └── install.sh          # One-time setup (run once)
└── apps/
    └── vscode/
        └── User/
            β”œβ”€β”€ settings.json
            └── keybindings.json

Related Documents