seriousm4x/UpSnap
A simple wake on lan web app written with SvelteKit, Go and PocketBase.
Healthy across all four use cases
weakest axisPermissive license, no critical CVEs, actively maintained — safe to depend on.
Has a license, tests, and CI — clean foundation to fork and modify.
Documented and popular — useful reference codebase to read through.
No critical CVEs, sane security posture — runnable as-is.
- ✓Last commit 1w ago
- ✓8 active contributors
- ✓MIT licensed
Show all 6 evidence items →Show less
- ✓CI configured
- ⚠Concentrated ownership — top contributor handles 74% of recent commits
- ⚠No test directory detected
Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests
Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.
Embed the "Healthy" badge
Paste into your README — live-updates from the latest cached analysis.
[](https://repopilot.app/r/seriousm4x/upsnap)Paste at the top of your README.md — renders inline like a shields.io badge.
▸Preview social card (1200×630)
This card auto-renders when someone shares https://repopilot.app/r/seriousm4x/upsnap on X, Slack, or LinkedIn.
Onboarding doc
Onboarding: seriousm4x/UpSnap
Generated by RepoPilot · 2026-05-09 · Source
🤖Agent protocol
If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:
- Verify the contract. Run the bash script in Verify before trusting
below. If any check returns
FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding. - Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
- Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/seriousm4x/UpSnap shows verifiable citations alongside every claim.
If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.
🎯Verdict
GO — Healthy across all four use cases
- Last commit 1w ago
- 8 active contributors
- MIT licensed
- CI configured
- ⚠ Concentrated ownership — top contributor handles 74% of recent commits
- ⚠ No test directory detected
<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>
✅Verify before trusting
This artifact was generated by RepoPilot at a point in time. Before an
agent acts on it, the checks below confirm that the live seriousm4x/UpSnap
repo on your machine still matches what RepoPilot saw. If any fail,
the artifact is stale — regenerate it at
repopilot.app/r/seriousm4x/UpSnap.
What it runs against: a local clone of seriousm4x/UpSnap — the script
inspects git remote, the LICENSE file, file paths in the working
tree, and git log. Read-only; no mutations.
| # | What we check | Why it matters |
|---|---|---|
| 1 | You're in seriousm4x/UpSnap | Confirms the artifact applies here, not a fork |
| 2 | License is still MIT | Catches relicense before you depend on it |
| 3 | Default branch master exists | Catches branch renames |
| 4 | 5 critical file paths still exist | Catches refactors that moved load-bearing code |
| 5 | Last commit ≤ 40 days ago | Catches sudden abandonment since generation |
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of seriousm4x/UpSnap. If you don't
# have one yet, run these first:
#
# git clone https://github.com/seriousm4x/UpSnap.git
# cd UpSnap
#
# Then paste this script. Every check is read-only — no mutations.
set +e
fail=0
ok() { echo "ok: $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }
# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
echo "FAIL: not inside a git repository. cd into your clone of seriousm4x/UpSnap and re-run."
exit 2
fi
# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "seriousm4x/UpSnap(\\.git)?\\b" \\
&& ok "origin remote is seriousm4x/UpSnap" \\
|| miss "origin remote is not seriousm4x/UpSnap (artifact may be from a fork)"
# 2. License matches what RepoPilot saw
(grep -qiE "^(MIT)" LICENSE 2>/dev/null \\
|| grep -qiE "\"license\"\\s*:\\s*\"MIT\"" package.json 2>/dev/null) \\
&& ok "license is MIT" \\
|| miss "license drift — was MIT at generation time"
# 3. Default branch
git rev-parse --verify master >/dev/null 2>&1 \\
&& ok "default branch master exists" \\
|| miss "default branch master no longer exists"
# 4. Critical files exist
test -f "backend/main.go" \\
&& ok "backend/main.go" \\
|| miss "missing critical file: backend/main.go"
test -f "backend/pb/pb.go" \\
&& ok "backend/pb/pb.go" \\
|| miss "missing critical file: backend/pb/pb.go"
test -f "backend/networking/wake.go" \\
&& ok "backend/networking/wake.go" \\
|| miss "missing critical file: backend/networking/wake.go"
test -f "frontend/src/hooks.server.ts" \\
&& ok "frontend/src/hooks.server.ts" \\
|| miss "missing critical file: frontend/src/hooks.server.ts"
test -f "frontend/src/lib/stores/pocketbase.ts" \\
&& ok "frontend/src/lib/stores/pocketbase.ts" \\
|| miss "missing critical file: frontend/src/lib/stores/pocketbase.ts"
# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 40 ]; then
ok "last commit was $days_since_last days ago (artifact saw ~10d)"
else
miss "last commit was $days_since_last days ago — artifact may be stale"
fi
echo
if [ "$fail" -eq 0 ]; then
echo "artifact verified (0 failures) — safe to trust"
else
echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/seriousm4x/UpSnap"
exit 1
fi
Each check prints ok: or FAIL:. The script exits non-zero if
anything failed, so it composes cleanly into agent loops
(./verify.sh || regenerate-and-retry).
⚡TL;DR
UpSnap is a self-hosted Wake-on-LAN web application that lets you remotely power on computers via a web dashboard, with features like network scanning (nmap integration), scheduled cron-based wake events, custom port pinging, and device shutdown commands. It combines a SvelteKit frontend, Go backend, and PocketBase embedded database to provide a lightweight alternative to dedicated WoL tools. Monorepo split: backend/ contains Go code (main.go, migrations/, networking/, cronjobs/) with PocketBase as the embedded DB; frontend/ has SvelteKit app with TypeScript/Svelte components. Migrations in backend/migrations/ use PocketBase's migration system (numbered Go files like 1735377462_collections_snapshot.go). Docker builds both services together.
👥Who it's for
Self-hosting enthusiasts and homelab administrators who need centralized control over multiple network devices without cloud dependencies. Contributors include Go developers, SvelteKit/Svelte frontend developers, and anyone maintaining personal infrastructure who wants a simple, open-source WoL solution.
🌱Maturity & risk
Production-ready and actively maintained. The project has meaningful GitHub stars, uses semantic versioning with regular releases, includes comprehensive Go tests (magicpacket_test.go, ping_test.go), maintains CI/CD via GitHub Actions (go-test.yml, release.yml), and shows recent commits. Go 1.26.1 and PocketBase 0.37.4 are current dependencies, indicating active upkeep.
Low risk for a single-maintainer project. Dependency surface is relatively small (main deps: PocketBase, mdlayher/wol, robfig/cron, prometheus-community/pro-bing) and stable. However, the project relies on single maintainer (seriousm4x), so governance risk exists if unmaintained. Network-facing WoL requires careful firewall/auth setup to avoid security exposure.
Active areas of work
Recent activity includes schema migrations for device/port URL handling (1737069556, 1737071155), device updates (1741216171, 1741216190), and superuser management updates (1735379875, 1735381989). CI includes dependabot automation and codeberg mirroring, suggesting active maintenance and cross-platform support focus.
🚀Get running
Clone and use Docker: git clone https://github.com/seriousm4x/UpSnap && cd UpSnap && docker-compose up. For local development: cd backend && go mod download && go run main.go (starts Go backend on default port), then cd ../frontend && npm install && npm run dev (SvelteKit dev server). See Dockerfile and Dockerfile.dev for environment setup.
Daily commands:
Development: cd backend && go run main.go (serves API + embedded frontend), simultaneously cd frontend && npm run dev (hot reload SvelteKit). Production: docker run -it ghcr.io/seriousm4x/upsnap:latest or Docker Hub image. Requires network access for WoL (UDP 9/broadcast) and ping (ICMP). Environment: PocketBase stores data in ./pb_data/ by default.
🗺️Map of the codebase
backend/main.go— Application entry point that initializes PocketBase, sets up migrations, routes, and cronjobs—essential for understanding the backend lifecyclebackend/pb/pb.go— Core PocketBase initialization and handler registration; defines the primary backend API surfacebackend/networking/wake.go— Magic packet (WoL) implementation—the central business logic that makes device wake-up workfrontend/src/hooks.server.ts— SvelteKit server hooks managing PocketBase authentication and session; controls auth flow for the entire appfrontend/src/lib/stores/pocketbase.ts— Frontend PocketBase client initialization and reactive store—single source of truth for backend communicationdocker-compose.yml— Production-ready deployment configuration; shows how all services (backend, frontend, PocketBase) integratebackend/go.mod— Go module dependencies; documents critical libraries like mdlayher/wol, pocketbase, and cron scheduler
🛠️How to make changes
Add a new WoL device endpoint
- Create a new migration in
backend/migrations/to add columns to thedevicescollection if needed (backend/migrations/1741216190_updated_devices.go) - Register a new HTTP handler in
backend/pb/handlers.goto handle the POST/GET request (backend/pb/handlers.go) - Implement the business logic by calling
backend/networking/wake.gofunctions (backend/networking/wake.go) - Update the frontend form component in
frontend/src/lib/components/DeviceForm.svelteto include new fields (frontend/src/lib/components/DeviceForm.svelte) - Update the device type definition in
frontend/src/lib/types/device.tsto match the new schema (frontend/src/lib/types/device.ts)
Add a new scheduled cron task
- Define the cron schedule and callback function in
backend/cronjobs/cronjobs.go(backend/cronjobs/cronjobs.go) - Register the cron job in
backend/main.goduring startup (backend/main.go) - Implement the task logic using existing networking utilities like ping from
backend/networking/ping.go(backend/networking/ping.go)
Add a new frontend page/route
- Create a new
.sveltefile infrontend/src/routes/following SvelteKit conventions (frontend/src/app.html) - Use the PocketBase store from
frontend/src/lib/stores/pocketbase.tsto fetch data (frontend/src/lib/stores/pocketbase.ts) - Import and compose reusable components from
frontend/src/lib/components/(e.g.,Navbar.svelte,DeviceCard.svelte) (frontend/src/lib/components/Navbar.svelte) - Ensure authentication is enforced via the server hook in
frontend/src/hooks.server.ts(frontend/src/hooks.server.ts)
Add platform-specific network functionality
- Create OS-specific implementation in
backend/networking/functionname_linux.goandbackend/networking/functionname_other.go(backend/networking/pingdevice_linux.go) - Use build tags to conditionally compile the correct implementation (
backend/networking/shutdown_windows.go) - Export a common interface function that dispatches to the platform-specific implementation (
backend/networking/wake.go)
🔧Why these technologies
- SvelteKit — Lightweight, reactive frontend framework with server-side rendering and authentication hooks—ideal for a focused web app without heavy dependencies
- PocketBase — Self-hosted backend-as-a-service with built-in auth, database, and file storage—eliminates need for separate DB and auth services
- Go — Fast, compiled, cross-platform language with excellent networking libraries (mdlayher/wol)—perfect for low-latency WoL packets and system calls
- Docker Compose — Simple orchestration of frontend, backend, and PocketBase in a single deployable unit—enables one-click setup
- mdlayher/wol — Specialized Go library for precise magic packet construction and transmission—avoids reinventing complex network protocol logic
⚖️Trade-offs already made
-
Single monolithic Go backend instead of microservices
- Why: Simpler deployment, easier debugging, lower operational overhead for a single-purpose WoL app
- Consequence: Limited horizontal scaling; all features (API, WoL, cron jobs) in one binary
-
PocketBase for auth instead of OAuth/external IdP
- Why: Self-contained, no external dependencies, data stays on your infrastructure
- Consequence: User must manage credentials; no SSO integration (though possible via custom handlers)
-
Platform-specific networking code (Linux, Windows, macOS) with build tags
- Why: Optimizes for each OS (e.g., iptables on Linux, WMI on Windows) rather than lowest-common-denominator
- Consequence: Must test/build on each platform; platform-specific bugs require platform-specific fixes
-
Cron jobs run in the same process as HTTP handlers
- Why: Simpler, no external job queue needed for a small app with infrequent background tasks
- Consequence: Heavy cron jobs could block HTTP requests; not suitable for high-traffic scenarios
🚫Non-goals (don't propose these)
- Does not support remote access without reverse proxy/VPN setup (app assumes LAN or proxied access)
- Does not handle SNMP or other vendor-specific device protocols—WoL and SSH/RDP only
- Does not provide real-time device state synchronization (pull-based polling, not push/WebSocket)
- Does not include multi-tenant isolation or RBAC
🪤Traps & gotchas
PocketBase must be initialized before first run (creates pb_data/ directory); network WoL requires raw socket access (may need root/CAP_NET_RAW on Linux—see kernel.org/pub/linux/libs/security/libcap/cap dependency). Frontend i18n strings must match keys in backend API responses. Migrations are irreversible; test schema changes in dev first. nmap must be installed separately for network scan feature. Docker containers bind to 0.0.0.0:8090 by default—port conflicts will block startup.
🏗️Architecture
💡Concepts to learn
- Magic Packet (WoL) — Core WoL mechanism UpSnap uses—a specially crafted Ethernet frame containing target MAC address repeated 16 times, broadcast on UDP port 9. Understanding this is essential to debug WoL failures or add BIOS-level WoL features.
- ICMP Ping / Network Reachability — UpSnap uses prometheus-community/pro-bing to check device status (port-specific pinging). Understanding ICMP vs TCP pinging helps explain why some devices don't report alive/dead correctly.
- Cron Scheduling (cron expressions) — UpSnap's robfig/cron/v3 integration allows users to define scheduled WoL events. You need to understand cron syntax and timing edge cases to debug or extend the scheduler.
- Raw Socket Programming (CAP_NET_RAW) — UpSnap's mdlayher/wol requires raw socket access on Linux to craft and broadcast WoL packets. The kernel.org/pub/linux/libs/security/libcap/cap dependency enforces Linux capability constraints—critical for container security.
- PocketBase Migrations — Schema changes use PocketBase's Go-based migration system (backend/migrations/). Understanding the migration file format and ordering prevents data loss and ensures consistency across deployments.
- SvelteKit Form Actions — Frontend handles WoL button clicks and device CRUD via SvelteKit +page.server.ts form actions, which tie to PocketBase API calls. This is the primary integration point between UI and backend.
- Broadcast Networking (UDP/Ethernet) — WoL packets are sent to broadcast addresses (255.255.255.255:9); understanding broadcast domains and network interfaces explains why WoL fails across VLAN boundaries or misconfigured routers.
🔗Related repos
gnmmarechal/etherwake— Lightweight C-based WoL tool; UpSnap modernizes this with web UI and schedulingachantech/wolweb— Another web-based WoL dashboard; UpSnap differentiates with PocketBase auth and built-in ping/nmap scanningpocketbase/pocketbase— Embedded database/auth backend used by UpSnap; contribute or file issues here if DB features are neededsveltejs/kit— Framework for UpSnap frontend; check for bleeding-edge SvelteKit patterns and breaking changesmdlayher/wol— Go WoL library underlying UpSnap's magic packet implementation; low-level dependency to understand for networking issues
🪄PR ideas
To work on one of these in Claude Code or Cursor, paste:
Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.
Add frontend unit tests for SvelteKit components and utilities
The repo has comprehensive backend tests (backend/networking/*_test.go files exist) but no visible frontend test suite. SvelteKit projects typically benefit from Vitest/Jest tests. This would improve code reliability for the UI layer, especially for critical components like device management, authentication, and the wake-on-LAN triggering logic.
- [ ] Create frontend/src/tests directory structure
- [ ] Add Vitest configuration to frontend (vitest.config.ts)
- [ ] Write unit tests for core utilities in frontend/src/lib (if they exist beyond what's shown)
- [ ] Add tests for authentication flows and device management operations
- [ ] Integrate frontend test step into .github/workflows/go-test.yml (rename to test.yml or create frontend-test.yml)
Add GitHub Actions workflow for building and pushing multi-platform Docker images
The repo has Dockerfile and docker-compose.yml files and publishes to both ghcr.io and Docker Hub, but the release.yml workflow only mentions Go release. A dedicated workflow for building/pushing multi-arch Docker images (linux/amd64, linux/arm64) on releases would streamline deployment and improve accessibility for ARM-based devices (common in home labs where WoL is used).
- [ ] Create .github/workflows/docker-build.yml or extend release.yml
- [ ] Configure docker/setup-buildx-action and docker/login-action for both registries
- [ ] Add build matrix for multiple platforms (amd64, arm64, potentially arm/v7)
- [ ] Tag images with version from git tags and 'latest'
- [ ] Push to both ghcr.io/seriousm4x/upsnap and docker.io/seriousm4x/upsnap
Add integration tests for PocketBase backend handlers (backend/pb/handlers.go)
The backend has unit tests for networking (magicpacket_test.go, ping_test.go) but no visible tests for the main PocketBase handlers and API endpoints. The handlers.go file contains critical business logic for device management, user authentication, and WoL operations that should be tested against actual PocketBase collections and migrations.
- [ ] Create backend/tests or backend/pb/handlers_test.go
- [ ] Set up test database fixtures using backend/migrations (1735377462_collections_snapshot.go and others)
- [ ] Write tests for device CRUD operations, wake/sleep/shutdown endpoints
- [ ] Add tests for authentication middleware (backend/pb/middlewares.go)
- [ ] Test device scanning functionality (backend/pb/handlerscan_linux.go, backend/pb/handlerscan_other.go with platform-specific tests)
- [ ] Integrate into .github/workflows/go-test.yml with test coverage reporting
🌿Good first issues
- Add integration tests for backend/networking/ping.go (currently only unit tests exist; needs E2E tests against real network interfaces)
- Expand Svelte component test coverage—no .test.ts files visible in frontend/src/lib/components/; start with a single high-use component like device list
- Document the PocketBase migration pattern in CONTRIBUTING.md with a worked example (repo has 6+ migrations but no contributor guide on schema changes)
⭐Top contributors
Click to expand
Top contributors
- @dependabot[bot] — 74 commits
- @seriousm4x — 14 commits
- @invario — 7 commits
- @mabbas007 — 1 commits
- @phuonganh2601 — 1 commits
📝Recent commits
Click to expand
Recent commits
6df1205— update deps (seriousm4x)cc605ac— Added shutdown group (#1732) (mabbas007)24e218b— gh-action: bump pnpm/action-setup from 5 to 6 (dependabot[bot])aabd8c1— gh-action: bump dependabot/fetch-metadata from 2 to 3 (dependabot[bot])b297f3a— Format pending countdown as MM:SS (#1727) (phuonganh2601)af655d3— build(deps-dev): bump vite from 7.3.1 to 7.3.2 in /frontend (dependabot[bot])65d6e9f— update deps (seriousm4x)6d53e9e— fix(cron/wake): fix closure bugs, add reload hooks, and improve command robustness (#1723) (monstercjz)6caddf2— Update README.md - reorganized parts and linked to Wiki instead (#1719) (invario)f7dc0b2— Update docker-compose.yml (#1721) (invario)
🔒Security observations
- High · Outdated Go Version —
backend/go.mod. The project uses Go 1.26.1, which is significantly ahead of the current stable release cycle. This may indicate version mismatch issues or potential forward compatibility problems. More critically, several dependencies have not been updated in coordination with this version. Fix: Verify Go version compatibility with all dependencies. Use a stable, well-tested Go version (currently 1.23.x LTS range) and audit dependency versions accordingly. - High · Outdated Security-Critical Dependencies —
backend/go.mod. Multiple dependencies have known security advisories and are significantly outdated: golang.org/x/crypto v0.50.0 (released Oct 2024), golang.org/x/net v0.53.0 (released Mar 2024), and golang.org/x/sys v0.43.0 (released Feb 2024). These are core security libraries used by PocketBase for JWT, TLS, and network operations. Fix: Immediately update to latest versions: golang.org/x/crypto, golang.org/x/net, and golang.org/x/sys. Run 'go get -u' and audit for breaking changes. - High · Privileged Container Capabilities Not Minimized —
docker-compose.yml, Dockerfile. While the docker-compose.yml properly uses 'cap_drop: ALL' and 'cap_add: NET_RAW', the base Dockerfile uses 'setcap cap_net_raw=+p' on the binary which is good practice. However, the container runs with 'network_mode: host', which exposes the container to all host network interfaces and bypasses network isolation. Fix: Consider whether host network mode is absolutely necessary. If WOL requires it, implement network namespace isolation where possible and document the security implications. Add explicit resource limits (memory, CPU) to constrain impact. - High · Untrusted External Binary Download in Dockerfile —
Dockerfile (line: wget from GitHub releases). The Dockerfile downloads pre-compiled binaries from GitHub releases without verifying cryptographic signatures or checksums. An attacker could perform MITM attacks or compromise the GitHub account to inject malicious code. Fix: Implement checksum verification using SHA256 hashes. Generate and publish cryptographic signatures (GPG or cosign) for all releases. Verify signatures in the Dockerfile before executing the binary. - Medium · Exposed Environment Variable in Docker Image —
Dockerfile. The Dockerfile includes ARG VERSION which becomes part of the build context. While not a secret, it could reveal deployment information. The default HTTP listen address binds to 0.0.0.0:8090 which is publicly accessible. Fix: Document that UPSNAP_HTTP_LISTEN should be set to 127.0.0.1:8090 or a private network address in production. Add a warning in comments about exposing on 0.0.0.0. Consider binding to localhost by default. - Medium · Missing Security Headers Configuration —
frontend/src/hooks.server.ts, frontend/src/hooks.ts. No evidence of security headers (Content-Security-Policy, X-Frame-Options, X-Content-Type-Options, etc.) in the frontend hooks or SvelteKit configuration. This could expose the web interface to XSS and clickjacking attacks. Fix: Implement security headers in SvelteKit hooks. Add CSP, X-Frame-Options: DENY, X-Content-Type-Options: nosniff, Strict-Transport-Security headers. - Medium · No HTTPS Enforcement Configuration Visible —
docker-compose.yml, Dockerfile, backend/main.go (not provided). The docker-compose configuration and Dockerfile do not show HTTPS configuration. The app appears to serve HTTP only on port 8090, creating risks for credential interception. Fix: Configure TLS/HTTPS in the backend. Use environment variables for certificate paths. Document reverse proxy setup (nginx/Caddy) with Let's Encrypt for production deployments. - Medium · Weak Dependency Version Pinning —
undefined. The go.mod file uses indirect dependency version ranges that allow automatic updates. PocketBase v0.37.4 may have its own security vulnerabilities that are not addressed. Fix: undefined
LLM-derived; treat as a starting point, not a security audit.
👉Where to read next
- Open issues — current backlog
- Recent PRs — what's actively shipping
- Source on GitHub
Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.