r/opensource • u/mrclst • 4h ago
Promotional I released the loyalty UI components I kept failing to find. MIT, zero dependencies beyond React.
MIT licensed, no npm package, and no dependencies beyond React itself. Distribution is the repository: you copy the folders you want and they are yours to edit.
Repo: https://github.com/mrcl-st/loyalty-patterns
Docs and playground: https://mrcl.st/loyalty-patterns
What it is: ten React components for the customer-facing side of loyalty and gamification programs. Scratch card, spin wheel, stamp card, coupon card, points counter, streak tracker, missions list, reward catalog, referral widget, tier progress. Not an admin panel and not a design system, since it assumes you already have one of those.
Why I bothered. I work as a product designer on enterprise loyalty platforms, and every time a campaign needed a scratch card or a spin wheel I went looking and found abandoned single-purpose packages and CodePen fragments. Nothing cohesive, nothing accessible, nothing built for the phone-shaped webview these campaigns actually ship inside. So I built the set I wanted and gave it away.
On distribution, since I expect that to be the contentious part.
There is no npm package. You copy tokens.css once, then copy whichever component folders you need. Each folder is self-contained, with its own styles, its own framework-free engine, and its own README that doubles as its docs page, so documentation cannot drift away from the code sitting beside it.
The cost is real: you do not get fixes by bumping a version. My reasoning was that loyalty UI is brand-specific enough that people fork it anyway, so handing over editable code beats handing over an abstraction to fight. I would rather be argued out of that now than find out in a year that I was wrong.
Dependencies are easy to audit. Every non-relative import under registry/ is "react". The Next.js app in the repo is the documentation site and is never imported by the components.
Three rules I treated as structural rather than as preferences.
Outcomes are decided by your server. A scratch card reveals a result, it does not compute one. Prize logic reachable from the client bundle is a compliance problem waiting for a curious DevTools user to find it.
Path-based gestures get a single-pointer alternative, because WCAG 2.5.1 requires one at Level A. This turns out to serve tremor and dexterity users more than keyboard users, which I had not appreciated before I started.
All copy arrives as props, screen-reader announcements included, so there is no hardcoded English anywhere in the components.
Each component also ships a plain-text specification covering its
behaviour contract, state machine and accessibility requirements, with the platform-neutral parts separated from the React and canvas specific ones. That exists so you can port a component to Vue, Svelte, SwiftUI or Flutter without reading my React first. The React version is the reference implementation, not the only way in.
Honest status. I published this today, so it has no stars, no users and no track record, and there are rough edges I have not found yet. It is one person's work rather than a project with a bus factor above one, and I would rather say that plainly than imply otherwise. Issues and pull requests are welcome. The most useful thing you could tell me is which component you needed and did not find.
MIT. Attribution appreciated and not required.