- TypeScript 81%
- JavaScript 8.2%
- CSS 5%
- HTML 2.9%
- Go 2.1%
- Other 0.8%
| .build | ||
| .github | ||
| .vscode | ||
| build | ||
| public | ||
| scripts | ||
| src | ||
| tests/e2e | ||
| .dockerignore | ||
| .envrc | ||
| .gitignore | ||
| .nvmrc | ||
| assets_test.go | ||
| Dockerfile | ||
| go.mod | ||
| go.sum | ||
| index.html | ||
| justfile | ||
| main.go | ||
| nginx.conf | ||
| package-lock.json | ||
| package.json | ||
| playwright.config.ts | ||
| README.md | ||
| REPORT.md | ||
| tsconfig.json | ||
| vite.config.ts | ||
| wails.json | ||
Pixel Ruler
A lightweight, installable PWA for inspecting the exact pixel coordinates of
an image. Upload a picture, hover the crosshair "ruler", and read off the precise
(x, y) pixel under your cursor - with 0,0 at the top-left of the image.
Everything runs 100% client-side. Images are never uploaded, and the app makes no third-party runtime requests. Like any PWA, it still uses normal same-origin requests for its own assets and service-worker update checks.
Features
Core
- Load images via file picker, drag-and-drop, or clipboard paste
- Supports PNG, JPEG, and WebP
- Decoded images are limited to 8,192 px per side and 16,777,216 total pixels
- Crosshair ruler with full-extent guide lines tracking the cursor
- Live integer pixel readout
(x, y)in the image's native resolution
Quality-of-life
- Zoom (mouse wheel toward cursor) and pan (drag), plus
Fit/1:1controls - Loupe / magnifier inset for sub-pixel precision
- Temporary preview panel - hover or use the keyboard to inspect RGB, alpha, HEX, and a transparency-aware swatch without changing selected samples
- Persistent selected-color panels - click/tap or press
Enter/Spaceto pin one or two sample cards and copy the inspected coordinate - Pair measurement - two selected samples show
dx,dy, and Euclidean distance; a third selection starts a new pair, whileClearremoves selected samples and markers - Keyboard nudge - arrow keys move the temporary inspection 1px (Shift = 10px)
- Toggleable grid overlay and crosshair guides
- Dark / light theme (follows system preference, remembers your choice)
- Installable & offline via service worker
The preview panel follows hover or keyboard inspection temporarily. The first
selection pins one color panel, the second pins another and completes the
measurement pair, and the third replaces that pair with the first sample of a
new measurement. Clear removes every pinned panel and its canvas marker.
Keyboard shortcuts
| Key | Action |
|---|---|
O |
Open image |
F |
Fit to screen |
1 |
Actual size (100%) |
+ / - |
Zoom in / out |
Arrows |
Move temporary inspection 1px (Shift = 10px) |
Enter / Space |
Pin inspected pixel and copy coordinates (canvas focused) |
G |
Toggle grid |
H |
Toggle guides |
L |
Toggle loupe |
C |
Clear selected samples and markers |
T |
Toggle theme |
Viewing locally
The source index.html is a Vite entry point, not a standalone HTML file. It
loads /src/main.ts, which imports TypeScript, CSS, and other modules that a
file:// preview does not transform or serve. "Client-side" means the running
app has no application backend; the source still needs a local development
server.
After the one-time npm ci --include=dev setup, open Run and Debug in VS
Code, select Pixel Ruler: Open in VS Code, and press F5. The launch
configuration starts Vite on http://127.0.0.1:5173/ and opens the site in VS
Code's integrated browser.
To run it from a terminal instead:
npm run dev
Open the localhost URL printed by Vite. In VS Code, use Browser: Open Integrated Browser and enter that URL, or open it in a normal browser.
To inspect the production build locally:
npm run build
npm run preview
Use localhost or HTTPS when checking install and offline behavior. Opening the
source or built index.html directly does not provide the HTTP origin required
for normal module and service-worker behavior.
Desktop builds
Desktop packaging requires Just, Node.js/npm, Go, and
the native build tools required by Wails. The recipes use the pinned Wails
v2.13.0 CLI through go run, so no global Wails installation is needed.
just setup installs the npm and Go dependencies, including the pinned
project-local TypeScript compiler; just doctor verifies TypeScript and the
host's native prerequisites.
just setup # install npm and Go dependencies
just doctor # check native build prerequisites
just test # run frontend and platform-independent Go validation
just build # build both the PWA and this host's desktop application
just build writes the PWA to dist/, service-worker-free desktop assets to
.build/desktop-dist/, and the packaged application to build/bin/. Use
just web or just desktop to build only one target. npm run build remains
the canonical standalone PWA build. just test (also just validate) first
regenerates the desktop assets, then runs frontend tests/typechecking, Go tests,
and go vet without requiring host-native GUI libraries.
Desktop applications are platform-native: run the desktop build on each target
operating system rather than expecting one host to produce every platform's
package. On Linux, the recipe selects Wails' webkit2_41 build tag and requires
a C compiler, pkg-config, GTK 3 development files, and WebKitGTK 4.1
development files (for example, build-essential pkg-config libgtk-3-dev libwebkit2gtk-4.1-dev on Debian/Ubuntu). Windows builds embed the WebView2
bootstrapper. just doctor checks the Linux modules Wails actually builds
against: gtk+-3.0, webkit2gtk-4.1, libsoup-3.0, and gio-unix-2.0.
Development
Use Node 24.18.0, pinned by .nvmrc and package.json.
NVM for Windows requires the explicit version argument below; .nvmrc remains
the repository's version pin.
nvm install 24.18.0 # first setup with nvm
nvm use 24.18.0
npm ci --include=dev # install the lockfile and pinned local TypeScript
npm run dev # start the Vite dev server
npm run typecheck # run strict TypeScript checks
npm run test # run unit tests (Vitest)
npm run test:browser:install # install Chromium for browser tests
npm run test:browser # run browser tests (Playwright)
npm run playwright:mcp:install # install Firefox for the configured MCP
npm run build # typecheck + production build (PWA) into dist/
npm audit # check all dependencies for known vulnerabilities
npm run preview # serve the production build locally
npm ci --include=dev provides a deterministic setup with the pinned
project-local TypeScript compiler. On Windows, run just setup or
npm ci --include=dev before typechecking or building. npm run typecheck
uses the local tsc; no global TypeScript installation is needed.
For a manual screen-reader smoke test, use NVDA with Firefox or VoiceOver with Safari. Verify the toolbar names and toggle states, canvas instructions and image dimensions, temporary inspection coordinates, selected-sample count and pair state, Enter/Space pin action, and copy/loading status messages.
Deployment and offline use
The production build uses relative asset, manifest, start, and service-worker
paths, so the contents of dist/ can be hosted at either a domain root or a
nested static path. Root and nested-path installs and offline reloads have been
verified.
Docker
Build and run the production image:
docker build -t pixel-ruler .
docker run --rm -p 8080:8080 pixel-ruler
Open http://localhost:8080/. The image builds the PWA in a Node stage and
serves only the generated static files with unprivileged nginx. Use HTTPS in
production so the service worker and install flow are available.
Serve the files over HTTPS in production (or localhost while testing), since
service workers require a secure context. Visit the deployed app online once so
its assets can be cached before expecting an offline reload. npm run preview
is useful for local production-build checks, but it is not a production server;
verify the final hosting path and cache behavior on the actual static host.
Tech
Vite + vanilla TypeScript (no UI framework) with vite-plugin-pwa. Rendering uses
a <canvas> for crisp guides at any zoom; an offscreen canvas at native resolution
provides accurate pixel color sampling. The screen↔image coordinate math lives in a
small, unit-tested Viewport module (src/viewport.ts).