npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@cardgamesplay/freecell

v0.1.0

Published

Browser-based FreeCell Solitaire game built with TypeScript and vanilla DOM. Features drag-and-drop, keyboard navigation, card animations, sound effects, a music player, hint system, and i18n support for 16 languages. Play free at https://www.cardgamespla

Readme

@cardgamesplay/freecell

A browser-based FreeCell Solitaire game built with TypeScript, Vite, and vanilla DOM — no framework required. Features drag-and-drop, keyboard navigation, card animations, synthesised sound effects, a built-in music player, hint system, and full i18n support for 16 languages.

🎮 Play the live demo at cardgamesplay.com

Features

  • Classic FreeCell rules with 4 free cells, 4 foundations, and 8 tableau columns
  • Supermove support — move ordered sequences as a unit, limited by available free cells and empty columns
  • Drag-and-drop card movement with visual drop-target highlighting and stack ghost images
  • Full keyboard navigation — arrow keys to move between piles and zones, Space to select/place, Up/Down to resize selection, Escape to cancel
  • Hint engine that evaluates all legal moves and scores them with heuristics to suggest the best play
  • Animated card dealing and foundation fly-to transitions
  • Synthesised Web Audio API sound effects (card click, card drop, foundation chime) — no audio files needed
  • Built-in music player powered by @rse/soundlp with ambient tracks, play/pause, volume slider, and mute toggle
  • Undo support — every action is reversible all the way back to the opening deal
  • Auto-move safely sends eligible cards to foundations without blocking future tableau builds
  • Pause mode that hides all card faces and freezes the timer
  • Fullscreen support
  • Responsive layout that adapts to any viewport size, including mobile and orientation changes
  • Internationalisation (i18n) with 16 locales: English, Bulgarian, Spanish, French, German, Italian, Portuguese, Russian, Chinese, Japanese, Korean, Arabic (RTL), Hindi, Vietnamese, Polish, and Turkish
  • Language selector in the header and hamburger menu, with cross-tab sync via localStorage
  • Score tracking (+10 for each card moved to a foundation)
  • Win detection with a celebratory overlay showing final score, time, and move count
  • SVG card images via cardsJS with automatic CSS/Unicode fallback
  • Published as an ES module with typed exports for game engine, UI, and i18n

Project Structure

├── src/
│   ├── index.ts              # App bootstrap — wires engine, renderer, drag-drop, keyboard, timer, UI
│   ├── game/
│   │   ├── types.ts           # Card, GameState, PileRef, Move, scoring constants
│   │   ├── deck.ts            # createDeck() and Fisher-Yates shuffle
│   │   ├── gameEngine.ts      # Core game logic — move, supermove, auto-move, undo
│   │   ├── hintEngine.ts      # Heuristic hint system — evaluates and ranks all legal moves
│   │   ├── scoring.ts         # Score delta helpers
│   │   ├── winCondition.ts    # checkWin() — all four foundations complete
│   │   ├── undoManager.ts     # Command-pattern undo stack
│   │   └── deck.test.ts       # Unit + property-based tests for deck
│   ├── ui/
│   │   ├── renderer.ts        # DOM rendering — free cells, foundations, tableau, keyboard highlights
│   │   ├── layout.ts          # Responsive layout calculator (card sizing, pile positions)
│   │   ├── dragDrop.ts        # HTML5 drag-and-drop with validity checking and stack ghosts
│   │   ├── keyboardController.ts # Full keyboard navigation across free cells, foundations, and tableau
│   │   ├── cardAnimator.ts    # Deal and foundation-fly animations
│   │   ├── audio.ts           # Synthesised sound effects (Web Audio API)
│   │   ├── musicPlayer.ts     # Ambient music player with track selection and volume control
│   │   └── langSelector.ts    # Language dropdown component
│   └── i18n/
│       ├── index.ts           # Locale registry, setLocale, applyLocale, cross-tab sync
│       ├── init.ts            # Minimal bootstrap for static pages
│       ├── en.ts              # English (canonical locale type)
│       └── {bg,es,fr,de,it,pt,ru,zh,ja,ko,ar,hi,vi,pl,tr}.ts
├── index.html                 # Standalone dev shell
├── dev-entry.ts               # Dev entry point (imports shared styles + game)
├── dev.css                    # Dev-mode style overrides
├── package.json
├── vite.config.ts             # Vite config (library build + dev server)
├── vitest.config.ts           # Vitest config (happy-dom environment)
├── tsconfig.json              # Dev/IDE TypeScript config
└── tsconfig.build.json        # Build TypeScript config (emits declarations)

Getting Started

Want to just play? Head over to cardgamesplay.com — no install needed.

Prerequisites

  • Node.js ≥ 18
  • npm (or your preferred package manager)

Install

npm install

Development

npm run dev

Opens a local Vite dev server with hot module replacement. The standalone dev shell at index.html includes a site header, language selector, and dev banner.

Build

npm run build

Compiles TypeScript declarations via tsc and bundles the library as an ES module into dist/.

Test

npm test

Runs all tests with Vitest in a happy-dom environment. The test suite includes:

  • Unit tests for deck creation, shuffle, and game engine moves
  • Property-based tests (via fast-check) covering shuffle permutation validity, card count preservation, and i18n persistence round-trips

Keyboard Shortcuts

| Key | Action | |---|---| | ← → | Move cursor within the current row (top row or tableau) | | ↑ ↓ | Navigate between top row and tableau, or resize selection | | Space | Select card(s) or confirm a move | | Escape | Cancel current selection | | F2 | New game | | Ctrl+Z / Cmd+Z | Undo |

Game Rules

  1. All 52 cards are dealt face-up into 8 tableau columns — the first 4 columns receive 7 cards, the remaining 4 receive 6 cards. There is no stock or waste pile.
  2. There are 4 free cells that can each hold a single card temporarily.
  3. There are 4 foundation piles that build up by suit from Ace to King.
  4. Tableau columns build down in rank with alternating colours (red on black, black on red).
  5. Any card may be placed in an empty tableau column (not just Kings).
  6. Only one card at a time can be moved to or from a free cell.
  7. Supermove: ordered sequences of alternating-colour descending cards can be moved between tableau columns as a unit, provided there are enough empty free cells and empty tableau columns to theoretically perform the move one card at a time. The maximum moveable stack size is (empty free cells + 1) × 2^(empty tableau columns).
  8. Cards cannot be moved back from foundations.
  9. Complete all four foundations (Ace through King) to win.

Scoring

| Action | Points | |---|---| | Any → Foundation | +10 |

Score floor is 0 (never goes negative).

Internationalisation

All UI strings are driven by locale objects in src/i18n/. The applyLocale() function walks the DOM and updates elements tagged with data-i18n, data-i18n-title, data-i18n-aria-label, and other data attributes. Arabic is supported with automatic RTL layout.

To add a new language, duplicate src/i18n/en.ts, translate the values, and register the new locale in src/i18n/index.ts.

Tech Stack

  • TypeScript (strict mode, ES2020 target)
  • Vite (dev server + library build)
  • Vitest + happy-dom (testing)
  • fast-check (property-based testing)
  • @rse/soundlp (ambient music sprite)
  • cardsJS (SVG card images)
  • Web Audio API (synthesised sound effects)
  • Vanilla DOM (no UI framework)

License

This project is licensed under the MIT License.

Links