https://github.com/kasperstorgaard/skub
A tiny puzzle game where you push pieces against walls and each other to reach the target
https://github.com/kasperstorgaard/skub
deno fresh game-development open-props puzzle puzzle-game tailwindcss typescript
Last synced: 3 months ago
JSON representation
A tiny puzzle game where you push pieces against walls and each other to reach the target
- Host: GitHub
- URL: https://github.com/kasperstorgaard/skub
- Owner: kasperstorgaard
- License: other
- Created: 2024-06-26T13:20:53.000Z (about 2 years ago)
- Default Branch: main
- Last Pushed: 2026-03-28T12:27:53.000Z (3 months ago)
- Last Synced: 2026-03-28T15:54:15.821Z (3 months ago)
- Topics: deno, fresh, game-development, open-props, puzzle, puzzle-game, tailwindcss, typescript
- Language: TypeScript
- Homepage: https://skub.app
- Size: 1.28 MB
- Stars: 0
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Skub
A sliding-piece puzzle game inspired by
[Ricochet Robots](https://en.wikipedia.org/wiki/Ricochet_Robots).
Guide the puck to its destination - but pieces continue until they hit
something.
**[Play it now](https://ricochet.kasperstorgaard.deno.net/)**
## Demo
https://github.com/user-attachments/assets/aeda00d9-e2a5-4814-830c-f34db20361cc
## Features
- **Progressive enhancement** — full server-side state management and, works
without JavaScript
- **Touch & keyboard** — swipe on mobile, arrow-keys or `u`/`r`/`h` shortcuts on
desktop
- **CSS-only replays** — animated solution playback, no JS animation libraries
- **Smart solver** — BFS-based solver finds optimal solutions and powers the
hint system
- **Dark/light theme** — follows system preference
- **Puzzle editor** — create, generate, and share your own puzzles with a
live-solving minimum moves badge
- **Leaderboards** — compare your solution against others
## Editor
https://github.com/user-attachments/assets/c1c1c2fd-defb-48a7-9622-1df74779787e
The built-in editor lets you create puzzles from scratch or generate random
solvable boards with configurable minimum moves. A debounced solver runs on every
edit, showing the optimal solution length in real time. Use **Download** to
export a puzzle as a `.md` file and **Import** to load one back in.
## Tech Stack
| Layer | Tech |
| --------- | ------------------------------------------------------------------------------------ |
| Runtime | [Deno](https://deno.land) |
| Framework | [Fresh 2](https://fresh.deno.dev) |
| UI | [Preact](https://preactjs.com) + [Signals](https://preactjs.com/guide/v10/signals/) |
| Styling | [Tailwind CSS v4](https://tailwindcss.com) + [Open Props](https://open-props.style/) |
| Storage | [Deno KV](https://deno.com/kv) |
| Touch | [ZingTouch](https://zingchart.github.io/zingtouch/) |
| Build | [Vite](https://vite.dev) |
## Getting Started
Requires [Deno](https://deno.land/manual/getting_started/installation).
```bash
# Start dev server with file watching
deno task dev
# Build for production
deno task build
# Preview production build
deno task preview
```
## Project Structure
```
routes/ File-system routes (pages + API)
islands/ Interactive Preact components (hydrated client-side)
components/ Static server-rendered components
game/ Core game logic (board, solver, parser, types, cookies)
client/ Browser-only code (touch, keyboard, routing)
lib/ Portable utilities (env, analytics, replay, build tools)
db/ Deno KV database layer
static/puzzles/ Puzzle definitions in Markdown + ASCII
```
## Puzzle Format
Puzzles are Markdown files with YAML frontmatter and an ASCII board:
```markdown
---
name: My Puzzle
slug: my-puzzle
createdAt: 2025-06-15T00:00:00.000Z
---
+ A B C D E F G H +
1 # # |
2 X |
3 | |
4 |
5 |
6 @ |
7 |
8 # |
+-----------------+
```
Symbols: `@` = puck (player piece), `X` = destination, `#` = blocker,
`|` = vertical wall, `_` = horizontal wall.
The easiest way to create a puzzle is via the in-app editor at `/puzzles/new`.
Design your board, then click **Download** to save the `.md` file. Use
**Import** to load it back into the editor later. Place it in
`static/puzzles/` and run `deno task update-puzzles` to register it.
## Privacy
This site uses [PostHog](https://posthog.com) for product analytics.
Tracking is **opt-in** — no data is collected until you accept via the cookie banner.
Data is processed by posthog in the eu, and not shared with other third parties.
## License
MIT