rack layout designer https://count.racku.la
  • TypeScript 76.7%
  • Svelte 19.7%
  • Shell 2.3%
  • CSS 0.8%
  • JavaScript 0.3%
  • Other 0.1%
Find a file
Gareth Evans 023b630f20
chore: remove the app light theme (#2468) (#2618)
* chore: remove the app light theme (#2468)

Make dark the single app chrome theme. The light (Alucard) theme was
opt-in, default off, and already dropped from the mobile View options, so
keeping it was a per-token maintenance tax for a rarely-used mode.

Removed:
- the [data-theme="light"] token block plus the color-scheme and
  theme-color light hints in index.html
- the Settings "Dark theme" toggle, the ui-store theme state/actions, and
  src/lib/utils/theme.ts
- the vestigial theme props passed to MobileViewSheet
- the unused sun/moon icons
- the Alucard contrast utilities and their tests

Also fixes the layout-preview thumbnails to render a dark rack (a
mini-canvas) instead of light grey. The transparent preview background
fell through to the export renderer's light branch; the preview now uses
a dark background. The export "Light background" option (independent, for
white paper) is unchanged.

Visual-regression baselines were mostly captured in light theme, so the
spec now renders dark and the baselines are regenerated separately.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01C2VoE74ScZpfBtvs1MCeKW
Signed-off-by: ggfevans <hi@gvns.ca>

* test: regenerate visual baselines for dark-only theme (#2468)

The visual-regression suite captured most states in light theme. With the
light theme removed the spec now renders dark, so the Linux baselines were
regenerated via the Update Visual Snapshots workflow.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01C2VoE74ScZpfBtvs1MCeKW
Signed-off-by: ggfevans <hi@gvns.ca>

---------

Signed-off-by: ggfevans <hi@gvns.ca>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-25 19:40:34 -07:00
.claude chore: format the entire repo with prettier + repo-wide format CI gate (#2424) (#2429) 2026-06-17 23:02:02 -07:00
.github feat: storage server opt-in (restore dev server mode + browser-to-server switch) (#2604) 2026-06-23 20:42:54 -07:00
.husky fix: make husky pre-commit hook POSIX sh compatible (#2288) (#2293) 2026-06-15 00:43:19 -07:00
api chore(deps): bump hono from 4.12.23 to 4.12.27 in /api (#2607) 2026-06-23 18:54:51 +00:00
assets chore: format the entire repo with prettier + repo-wide format CI gate (#2424) (#2429) 2026-06-17 23:02:02 -07:00
assets-source/device-images chore: normalize vendor asset directories and split the generic library (#2572) 2026-06-22 04:08:37 -07:00
deploy fix: revalidate the SPA entry document so deploys propagate (#2599) 2026-06-22 23:18:49 -07:00
docs feat: storage server opt-in (restore dev server mode + browser-to-server switch) (#2604) 2026-06-23 20:42:54 -07:00
e2e chore: remove the app light theme (#2468) (#2618) 2026-06-25 19:40:34 -07:00
scripts chore: normalize vendor asset directories and split the generic library (#2572) 2026-06-22 04:08:37 -07:00
src chore: remove the app light theme (#2468) (#2618) 2026-06-25 19:40:34 -07:00
static chore: format the entire repo with prettier + repo-wide format CI gate (#2424) (#2429) 2026-06-17 23:02:02 -07:00
.coderabbit.yaml fix: gate security-triage Claude call on net-new alerts and load secure-coding skill (#2425) (#2427) 2026-06-17 22:31:32 -07:00
.dockerignore Fix frontend Docker build and persist env wiring 2026-02-10 01:01:36 -08:00
.env.example feat: runtime storage mode config injection (#2036) (#2051) 2026-06-10 08:34:08 -07:00
.gitignore test: visual regression tripwire for key UI states (#2098) (#2250) 2026-06-14 05:41:28 -07:00
.markdownlint-cli2.jsonc fix: gate security-triage Claude call on net-new alerts and load secure-coding skill (#2425) (#2427) 2026-06-17 22:31:32 -07:00
.mcp.json chore: add svelte mcp 2026-01-09 20:35:35 -08:00
.octocov.yml chore: switch to delta-based coverage metrics (#697) 2026-01-16 05:36:57 +00:00
.prettierignore chore: mobile viewport and gesture foundation (#2466) (#2475) 2026-06-18 17:35:40 -07:00
ACKNOWLEDGEMENTS.md chore: format the entire repo with prettier + repo-wide format CI gate (#2424) (#2429) 2026-06-17 23:02:02 -07:00
AGENTS.md chore: add AGENTS.md 2026-02-13 18:49:34 -08:00
CHANGELOG.md chore: rename milestones to three-digit padding (M01 → M001) 2026-06-19 20:19:21 -07:00
CLAUDE.md fix: revalidate the SPA entry document so deploys propagate (#2599) 2026-06-22 23:18:49 -07:00
CODE_OF_CONDUCT.md chore: format the entire repo with prettier + repo-wide format CI gate (#2424) (#2429) 2026-06-17 23:02:02 -07:00
CONTRIBUTING.md docs: tidy CONTRIBUTING and add DCO section (#2559) 2026-06-21 23:02:45 -07:00
docker-compose.yml chore: format the entire repo with prettier + repo-wide format CI gate (#2424) (#2429) 2026-06-17 23:02:02 -07:00
eslint.config.js chore: block CSS class selectors in E2E tests (#1423) (#2251) 2026-06-14 06:00:33 -07:00
index.html chore: remove the app light theme (#2468) (#2618) 2026-06-25 19:40:34 -07:00
LICENSE Update copyright year and owner in LICENSE file (#1166) 2026-02-10 01:17:16 -08:00
login.html chore: mobile viewport and gesture foundation (#2466) (#2475) 2026-06-18 17:35:40 -07:00
package-lock.json chore(deps): bump @types/node in the typescript group (#2617) 2026-06-25 18:53:58 +00:00
package.json chore(deps): bump @types/node in the typescript group (#2617) 2026-06-25 18:53:58 +00:00
performance-budget.json ci: bundle-size performance budget and baseline for the M14 shell (#2185) (#2271) 2026-06-14 08:46:26 -07:00
prettier.config.js docs: draft Unreleased changelog and set prettier proseWrap to never (#2384) 2026-06-17 02:55:35 -07:00
README.md chore: format the entire repo with prettier + repo-wide format CI gate (#2424) (#2429) 2026-06-17 23:02:02 -07:00
SECURITY.md docs: update SECURITY.md supported version to 26.6.3 (#2613) 2026-06-23 20:54:53 -07:00
svelte.config.js chore: format the entire repo with prettier + repo-wide format CI gate (#2424) (#2429) 2026-06-17 23:02:02 -07:00
tsconfig.json chore(ts): fix svelte-check errors and drop deprecated baseUrl (#2105, #2104) (#2143) 2026-06-11 21:00:00 -07:00
vite.config.ts feat: unified panel chrome - collapse chevrons, 320px panels, 44px controls (#2397) (#2402) 2026-06-17 17:45:11 -07:00
vitest.config.ts chore(ts): fix svelte-check errors and drop deprecated baseUrl (#2105, #2104) (#2143) 2026-06-11 21:00:00 -07:00

Rackula

Drag-and-drop rack layout designer
Plan your rack, move some pixels, save your shoulders.

License: MIT GitHub Release Docker CalVer CI

Rackula demo

Rackula showing a rack with server and network devices


Features

  • Drag and drop devices into your rack from a real hardware library
  • Real device images from the NetBox devicetype-library, not grey boxes
  • Export layouts to PNG, PDF, or SVG for documentation and change requests
  • Share layouts via URL or QR code, no file attachments needed
  • Mobile-friendly interface for field use
  • Bayed rack grouping for AV installs and multi-cabinet deployments
  • Optional persistent storage with API-backed layout sync
  • Self-hostable via Docker, Proxmox LXC, or bare metal
  • Optional auth with local accounts or OIDC for shared deployments

Who It's For

Audience Use Case
Homelabbers Plan your server rack before you rack it. Move pixels, not 4U servers.
AV Technicians Bayed rack support for audio installs, map out amp racks, patch bays, and processor chains.
Network Engineers Document and plan switch/router topologies. Export for runbooks and change requests.
Data Centre Teams Layout planning for colo cages and enterprise cabinets. Share via URL with your team.
Educators & Students Teach networking and infrastructure concepts with a visual, hands-on tool. No licence keys, no gatekeeping.

Why Though?

You might ask, why should I make an imaginary rack like some sort of IT cosplay? And to that I would say, "fine then! don't! SCRAM!" but also, consider:

  • Plan your layouts before you build them. It's a lot easier to move your mouse than that 4U server full of hard drives. Your shoulder will thank you.
  • Document existing layouts so you know what is where.
  • Because you can

How Racks Work

Racks are measured in rack units, written U. One U is 1.75 inches of vertical space, and a common full-height rack is 42U. Rackula models racks in whole U: a device occupies a whole number of units and mounts at a whole-U boundary, the same way real rails register equipment under the EIA-310 standard. If something sits at U5, it is really at U5, not floating part of a unit above it.

Gear smaller than 1U, like half-height brackets or side-by-side half-width pairs, does not bolt to the rails on its own. It rides inside a 1U carrier (a bracket, tray, or shelf) that takes up one whole U and holds the smaller devices. The carrier registers to the rails, and the small devices register to the carrier.

Get Started

Use it right now

count.racku.la no account, no install, just racks.

Self-host with Docker

This is a quick run of the client-side only frontend (no persistence across browser sessions):

docker run -d -p 8080:8080 ghcr.io/rackulalives/rackula:latest

Or with Docker Compose:

curl -fsSL https://raw.githubusercontent.com/RackulaLives/Rackula/main/deploy/docker-compose.persist.yml -o docker-compose.yml
mkdir -p data && sudo chown 1001:1001 data
docker compose up -d

Open http://localhost:8080 and get after it.

Build from Source

git clone https://github.com/RackulaLives/Rackula.git
cd Rackula && npm install && npm run build

Serve the dist/ folder however you like. It's just files.

Deploy on Proxmox (LXC)

Note: LXC is currently in pre-release. See the Self-Hosting Guide for details and manual install instructions.

Security & Auth

For production deployments, configure API security and authentication:

# Generate secrets
openssl rand -hex 32  # API write token
openssl rand -hex 32  # Session secret (if using auth)

Set CORS_ORIGIN, RACKULA_API_WRITE_TOKEN, and optionally RACKULA_AUTH_MODE (none, local, or oidc) in your .env file.

See the Self-Hosting Guide for full configuration details including auth modes, env vars, and TLS setup.

Built With Claude

This project was built using AI-assisted development with Claude. I told it what to build and then said "no, not like that" a lot. The AI did a lot of typing. Commits with substantial AI contributions are marked with Co-authored-by tags because we're not going to pretend otherwise.

Documentation

Acknowledgements

Built for the r/homelab and r/selfhosted communities. Colours from Dracula Theme. Device data from NetBox devicetype-library. See ACKNOWLEDGEMENTS.md for full credits.

Star History

Star History Chart

Licence

MIT Copyright © 2025-2026 Gareth Evans