michaelongaro/Squeak
michaelongaro/Squeak has 48 GitHub stars and 5 forks. GitHot measured 0 stars in 24 hours. Last checked 2026-11-15 04:52 UTC. Last push 2026-11-11.
Measured star growth
- in 24h
- 0
- in 7 days
- Collecting history
- in 15 days
- Collecting history
- in 1 month
- Collecting history
Net star changes over overlapping periods, not daily totals. Missing measurements are left blank. Stars measure attention, not software quality.
About
A fun, fast-paced multiplayer rendition of solitaire. Games can be played with 2-5 players, lasting around 20 minutes.
Web & AppsREADME.md
OriginalSqueak 🐁
https://github.com/user-attachments/assets/ca54aaa0-4d2e-4f10-a7a4-01644fa0544b
Visit the site and play for free: Squeak.
Description
Squeak is a recreation of the card game popularly known as "Nerts" made with the T3 Stack. This project relies heavily on Socket.io to handle all transmission of realtime game and friend logic. Authentication is handled by Clerk. The Postgres database and server are both hosted on Railway.
Games can be played with 2-5 players and last roughly 20-40 minutes, depending on how many rounds there are. Sometime in the future I plan on creating native iOS and Android apps utilizing React Native with Expo.
Development checks
npm testruns regression tests for card moves, round timers, voting, room membership, scoring, and API guards. Database calls are mocked; tests do not use the project database.npm run typecheckgenerates Next.js route types and checks TypeScript.npm run lintruns ESLint directly (Next.js 16 removednext lint).npm run buildgenerates the Prisma client and creates a production build with type checking enabled.
Socket handlers and helpers live under src/server/socket; only HTTP endpoints belong under src/pages/api. The room-cleanup job accepts a POST to /api/cron with { "secret": "<CRON_JOB_SECRET>" } in its JSON body.
Analytics
The Analytics table stores one row per UTC day, with atomic counters:
| Counter | Recorded when |
|---|---|
pageViews |
An initial page loads or navigation to a different path completes. Query-string, hash, shallow-route changes, and duplicate route notifications are ignored. Refreshes count again. |
roomsCreated |
A new room is successfully saved. |
gamesStarted |
The first round of a new match starts. |
gamesPlayed |
A match finishes with a player reaching the winning score. Abandoned matches are not included. |
roundsStarted |
Any round starts, including the first. |
roundsPlayed |
A round completes, including rounds ended by a vote. |
Each match/round counts once for the room, regardless of the number of human players or bots. Events are attributed to the UTC day on which they occur. Counters begin when this version is deployed; historical activity is not backfilled. Tracking is best effort: network or database failures can cause missed events, but never block gameplay. These are total page views, not unique visitors.
Before deploying to another environment, run npm run db:analytics against its configured DATABASE_URL. This rerunnable script only creates the analytics table; the existing npm run db:push workflow also includes the new model. Use Prisma Studio (npm run db:studio) to inspect daily counts. No user identifiers, IP addresses, cookies, or page URLs are stored, and game counters are recorded only by the server.
For all-time totals:
SELECT
COALESCE(SUM("pageViews"), 0) AS "pageViews",
COALESCE(SUM("roomsCreated"), 0) AS "roomsCreated",
COALESCE(SUM("gamesStarted"), 0) AS "gamesStarted",
COALESCE(SUM("gamesPlayed"), 0) AS "gamesPlayed",
COALESCE(SUM("roundsStarted"), 0) AS "roundsStarted",
COALESCE(SUM("roundsPlayed"), 0) AS "roundsPlayed"
FROM "Analytics";