No description
Find a file
2026-07-11 01:25:17 -04:00
app Replace JSZip with system 7z for archive extraction 2026-06-17 17:00:14 -04:00
bin Migrate from Python/FastAPI to unified Bun/Hono application 2026-06-17 16:52:37 -04:00
fake-data Fix operation status polling and multiple selection handling; add GameCube test fixtures 2026-06-16 20:40:39 -04:00
public Migrate from Python/FastAPI to unified Bun/Hono application 2026-06-17 16:52:37 -04:00
tests Replace JSZip with system 7z for archive extraction 2026-06-17 17:00:14 -04:00
.gitignore Consolidate backend and frontend into single Bun app 2026-06-17 17:06:57 -04:00
AGENTS.md Remove install/uninstall scripts, simplify to docker compose 2026-06-17 17:11:56 -04:00
bun.lock Consolidate backend and frontend into single Bun app 2026-06-17 17:06:57 -04:00
bunfig.toml Migrate from Python/FastAPI to unified Bun/Hono application 2026-06-17 16:52:37 -04:00
docker-compose.dev.yml Install wit via apt instead of host volume mount 2026-06-17 17:14:47 -04:00
docker-compose.prod.yml Install wit via apt instead of host volume mount 2026-06-17 17:14:47 -04:00
docker-compose.yml edited docker-compose 2026-07-11 01:25:17 -04:00
Dockerfile Install wit via apt instead of host volume mount 2026-06-17 17:14:47 -04:00
package.json Replace JSZip with system 7z for archive extraction 2026-06-17 17:00:14 -04:00
README.md Install wit via apt instead of host volume mount 2026-06-17 17:14:47 -04:00
tsconfig.json Migrate from Python/FastAPI to unified Bun/Hono application 2026-06-17 16:52:37 -04:00

ROM Loader

Web app for safely managing Wii and GameCube ROMs on backup drives.

Stack

  • Runtime: Bun (single monolithic app)
  • Server/Frontend: Hono + HTMX + Tailwind CSS v4
  • External tools: wit (Wii WBFS) and dolphin-tool (RVZ conversion)
  • Deployment: Docker container (dev and prod)

Repository Layout

.
├── app/                    # Unified Bun application source
│   ├── server.ts           # Hono server, API routes, HTMX fragments
│   ├── client.ts           # Browser entry point
│   ├── styles.css          # Tailwind CSS source
│   ├── config.ts           # Paths and tool resolution
│   ├── scanner.ts          # Directory/archive scanning via 7z
│   ├── comparison.ts       # ROM matching logic
│   ├── converter.ts        # RVZ → ISO conversion
│   ├── wit.ts              # wit (WBFS) operations
│   ├── operations.ts       # Bulk copy/convert worker
│   ├── drive.ts            # Drive type detection
│   ├── logger.ts           # In-memory operation log
│   ├── utils.ts            # Filename/region normalization
│   └── types.ts            # Shared TypeScript types
├── bin/                    # Mock tools for dev/test
│   ├── wit
│   └── dolphin-tool
├── public/                 # Static assets (built CSS, HTMX, index.html)
├── tests/                  # bun:test suite
├── fake-data/              # Example source/target drives
├── Dockerfile
├── docker-compose.yml      # Base config (shared)
├── docker-compose.dev.yml  # Dev overrides (mock tools, fake data, hot-reload)
└── docker-compose.prod.yml # Prod overrides (real drives, host wit mount)

Features

  • Read-only source directory scanning
  • Automatic archive extraction (zip, 7z, rar) via streaming 7z
  • RVZ → ISO → WBFS conversion pipeline (via dolphin-tool and wit)
  • Wii WBFS folder structure (./wbfs) and GameCube Swiss structure (./Games)
  • Fuzzy name + game ID + region matching against target drive
  • Bulk copy/convert operations with integrity checks
  • Live operation logs with [scan]/[operate] progress in container logs
  • Dark mode UI
  • Drive type auto-detection with manual override

Development

Local (no Docker)

bun install
bun run dev

Open http://localhost:3000. Needs 7z installed for archive extraction tests (brew install p7zip on macOS, apt install p7zip-full on Linux).

Docker dev

docker compose -f docker-compose.yml -f docker-compose.dev.yml up --build

This mounts fake data and mock wit/dolphin-tool scripts from bin/, and hot-reloads app/ and public/ via volume mounts.

Production

# Create .env with your drive paths:
cat > .env <<EOF
SOURCE_DIR=/mnt/source
TARGET_DIR=/mnt/target
EOF

docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d --build

The prod compose file mounts your source drive read-only and your target drive read-write. Both wit and dolphin-tool are installed inside the container — wit via apt, dolphin-tool via the npm package. No host binaries needed.

Managing the deployment

# View logs
docker compose -f docker-compose.yml -f docker-compose.prod.yml logs -f

# Restart
docker compose -f docker-compose.yml -f docker-compose.prod.yml restart

# Stop
docker compose -f docker-compose.yml -f docker-compose.prod.yml down

# Update (after pulling new code)
docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d --build

Testing

bun test
bun run typecheck

Environment Variables

Variable Default Purpose
SOURCE_DIR /data/source Read-only source directory
TARGET_DIR /data/target Destination drive root
WIT_PATH /usr/bin/wit wit binary path inside container
DOLPHIN_TOOL_PATH resolved dolphin-tool binary override
TEMP_DIR /tmp/rom-loader Conversion scratch space
LOG_LEVEL INFO Logging level
PORT 3000 HTTP server port
HOSTNAME 0.0.0.0 Bind address

Safety

  • Source directory is mounted read-only in Docker.
  • File copies are verified by size after write.
  • Target structure is created only when necessary.
  • Local files are never modified; only target drive receives writes.