@meetreeve/gamify
v0.1.0
Published
Generic gamification layer for Reeve surfaces — types, services, data hooks
Downloads
626
Keywords
Readme
@meetreeve/gamify
Generic gamification layer for Reeve surfaces. Provides types, injectable API client, and data hooks (level, achievements, streak, XP transactions). Decoupled from any specific backend — consumer provides base URL + auth header via GamifyProvider.
Usage
import { GamifyProvider, useUserLevel, useAchievements, useStreak, useXPTransactions } from '@meetreeve/gamify';
<GamifyProvider baseUrl="https://api.example.com/api" getAuthHeader={() => `Bearer ${token}`}>
<App />
</GamifyProvider>Celebration / "game-win feel" primitives (@meetreeve/gamify/reveal)
The net-new desire/celebration primitives — LevelUpReveal, ShakingLock,
Fireworks, ConfettiBurst, RewardClaim — plus their palette helpers live in
the /reveal subpath. They are the only place that pulls in canvas-confetti
and the full-screen choreography, so they are kept off the main barrel to
keep first paint light. Code-split them with React.lazy / dynamic import:
import { lazy, Suspense, useState } from 'react';
// Off first paint — only loaded when a server-confirmed rung change occurs.
const LevelUpReveal = lazy(() =>
import('@meetreeve/gamify/reveal').then((m) => ({ default: m.LevelUpReveal })),
);
function Cockpit() {
const [reveal, setReveal] = useState(null);
// ... when the SERVER confirms a rung transition (never optimistically):
// setReveal({ rungLabel: 'Rung 2 · Scaling', capabilities: ['Paid Ads'] });
return (
<Suspense fallback={null}>
{reveal && (
<LevelUpReveal
{...reveal}
major={reveal.major} // R3/R4 → escalates to two-stage Fireworks
onClose={() => setReveal(null)}
onCTA={() => {/* route to the unlocked surface */}}
/>
)}
</Suspense>
);
}The reduced-motion gate (NON-NEGOTIABLE)
Every celebration routes through useReducedMotionGame() and ships a tasteful
static / opacity fallback (no shake, no confetti, no typing). The gate + the
lightweight useShake / useSparkle hooks are on the main barrel (no
particle code), so you can use them without loading /reveal:
import { useReducedMotionGame, useShake, useSparkle, ReducedMotionGameProvider } from '@meetreeve/gamify';ReducedMotionGameProvider value={boolean} force-overrides the OS preference
(useful for tests, Storybook, or an in-app "reduce animations" toggle).
Primitive summary
| Primitive | Subpath | What it is | Reduced-motion fallback |
|-----------|---------|------------|--------------------------|
| useReducedMotionGame() | . | SSR-safe prefers-reduced-motion gate | — (it is the gate) |
| useShake({ idle }) | . | transform-only idle "itch" + impact "rattle" | no shake |
| useSparkle() | . | 3–5 short twinkles on demand | ≤1 static sparkle |
| ConfettiBurst | /reveal | capped <canvas> confetti from lower corners | static "Unlocked" badge fade |
| Fireworks | /reveal | two-stage staged shell burst (major rungs) | static "Unlocked" badge fade |
| LevelUpReveal | /reveal | full-screen choreographed rung reveal (controlled, server-confirmed) | calm modal, static text + CTA |
| ShakingLock | /reveal | locked "desire engine" (idle itch, rattle-on-tap, click-open on unlock) | static state + tap pulse |
| RewardClaim | /reveal | fly-to-home-counters collect pattern | instant update |
CSS tokens export
package.json exports "./styles/tokens.css" pointing at src/styles/tokens.css (src/ is included in files). This is intentional — the CSS file is published from source, not from dist. If you ever remove src/styles from files, add a build step to copy tokens.css to dist/ and update the export path, or theme consumers will silently get 404s.
Restraint contract: particles are <canvas> only (capped ~80–120), animations
are transform/opacity only (no layout/gesture props that forward to the DOM),
rAF/timers auto-stop and clean up on unmount, and celebrations fire only on
explicit trigger / server-confirmed unlock — never optimistically, never idle
(the sole exception being ShakingLock's idle itch). LevelUpReveal must be
mounted by the consumer only after the server confirms the rung transition.
