Skip to content

stacksjs/image-optimization

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

13 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

image-optimization — native-style image optimization, built on stx + Bun

GitHub Actions License Made with stx

image-optimization

A native-style image-optimization app modelled on ImageOptim, built with stx + Bun and our pure-TypeScript image libraries.

No runtime dependencies beyond Bun and the ts-* libs — every codec is in-process TypeScript:

Format Library
PNG @stacksjs/ts-png
JPEG ts-jpeg
WebP @stacksjs/ts-webp
BMP @stacksjs/ts-bmp
GIF ts-gif
AVIF @stacksjs/ts-avif
SVG text minify (CDATA-aware)
┌──────────────────────────────────────────────────────────┐
│ ●●●            ImageOptimization                         │
├──────────────────────────────────────────────────────────┤
│  cover.jpg     84.2 KB   21.0 KB   −75.0%  ⬇  ✕         │
│  hero.png       1.2 MB    872 KB   −28.4%  ⬇  ✕         │
│  banner.gif      62 KB    21 KB    −64.9%  ⬇  ✕         │
│                                                ┌────┐    │
│                                                │ ↓  │    │
│                                                └────┘    │
├──────────────────────────────────────────────────────────┤
│  +  3 files · saved 1.4 MB (66.2%)            ⋯  ↻ Again │
└──────────────────────────────────────────────────────────┘

Install

Download the latest .dmg from Releases, drag the .app into /Applications, done.

Run from source

bun run setup        # provision system + JS deps (pantry install + bun install)
bun run dev          # browser
bun run dev:native   # native Craft window (macOS)

Bun is the only system requirement — declared in deps.yaml and provisioned by pantry when you run pantry install (or bun run setup). Everything else is a regular package.json dependency.

The --native flag relies on:

  • @stacksjs/desktop being built in the local stx repo
  • the craft binary on your $PATH (or at ~/.bun/bin/craft / CRAFT_BINARY_PATH=…)

If --native can't find a craft binary, it transparently falls back to opening the system browser at the dev URL.

Distribution

.dmg builds

Pushing a v* tag triggers .github/workflows/release.yml which:

  1. Spins up a macOS runner
  2. Uses pantry to provision bun + craft-native.org (the native shell binary) — declared in deps.yaml
  3. Builds the stx site with bun run build
  4. Calls packageApp() from @craft-native/craft to produce a signed-or-unsigned .app and a .dmg (via hdiutil)
  5. Uploads the .dmg to the GitHub Release via stacksjs/action-releaser

The packaging logic lives in scripts/package.ts. To package locally:

bun run build:dmg
# → dist/ImageOptimization-<version>.dmg

Optional code-signing / notarization: provide APPLE_SIGN_IDENTITY, APPLE_ID, and APPLE_APP_PASSWORD as repo secrets and the workflow forwards them to packageApp.

Pantry registry

bun run release:patch   # 0.0.1 → 0.0.2 → tag → workflow runs → DMG on Releases
bun run release:minor   # 0.0.x → 0.1.0 → tag → workflow runs → DMG on Releases

Continuous-release tarballs are also published to the pantry registry at registry.pantry.dev on every push to main (see ci.yml). Auth: PANTRY_REGISTRY_TOKEN repo secret.

Architecture

┌──────────────────────────────────────┐
│  Craft native window (WKWebView)     │  ← UI
│   (or system browser w/o --native)   │
└────────────────┬─────────────────────┘
                 │ fetch /optimize
                 ▼
┌──────────────────────────────────────┐
│  stx dev server (Bun.serve)          │  ← server
│   ├ /         → src/pages/index.stx  │
│   └ /optimize → apiRoutes (config)   │
└────────────────┬─────────────────────┘
                 │ dispatch by magic bytes
                 ▼
┌──────────────────────────────────────────────────────────┐
│  ts-png · ts-jpeg · ts-webp · ts-bmp · ts-gif · ts-avif  │  ← image libs
│   (pure TS, zero runtime deps)                            │
└──────────────────────────────────────────────────────────┘

Format coverage

Format Strategy
PNG decode → re-deflate at level 9 across 4 strategies, keep smallest
JPEG decode → re-encode at q=85 (note: drops EXIF / orientation)
WebP decode → re-encode lossless
BMP decode → re-encode (drops alpha when fully opaque)
SVG text minify, CDATA-aware
GIF palette tightening per-frame + global-palette consolidation (lossless)
AVIF ISOBMFF re-mux: strip Exif/XMP/mime items, thumbnails, redundant brands
TIFF · ICO · HEIC detected and reported, no optimizer yet (passthrough w/ note)

Output is only kept when smaller than the input — already-optimized files come back unchanged with passthrough: true in x-stx-result.

UX

  • Drag and drop any number of images onto the window
  • Click + to pick files via the system dialog
  • Per-row download to save the optimized bytes
  • Per-row remove to drop a file from the list
  • Toolbar summary shows total bytes saved across all rows in real time
  • Again re-runs the optimizer on every file (useful after a settings change)
  • After the first drop, the drop zone shrinks into the corner but stays interactive
  • Errors surface in the toolbar in red so failures aren't silent

Layout

image-optimization/
├── src/
│   ├── pages/
│   │   └── index.stx       — the ImageOptim UI (drop zone, list, toolbar)
│   ├── components/
│   │   ├── DropZone.stx    — full-window drop target
│   │   ├── Toolbar.stx     — bottom action bar
│   │   └── FileRow.stx     — per-file row template
│   └── optimize.ts         — magic-byte format detection → per-format pipeline
├── scripts/
│   └── package.ts          — builds .app + .dmg via @craft-native/craft
├── .config/
│   ├── stx.ts              — registers /optimize via apiRoutes
│   └── crosswind.ts        — content paths for utility-class generation
├── deps.yaml               — pantry-provisioned system deps (bun, craft)
└── package.json

Notes on dependencies

The image libs are imported by relative path from ~/Code/Libraries/ts-*, and stx itself is invoked via the local repo at ~/Code/Tools/stx/stx. This mirrors how the example in the stx monorepo is wired up — the libs remain editable in place rather than being copied into node_modules.

License

MIT — see LICENSE

About

No description or website provided.

Topics

Resources

Code of conduct

Contributing

Stars

Watchers

Forks

Releases

No releases published

Contributors