Progression

Convex component that tracks cumulative XP, threshold-based levels, and activity streaks with host-controlled rules and no embedded domain logic.

Installation

npm install @vllnt/convex-progression

About Progression

@vllnt/convex-progression stores cumulative points, threshold-based levels, and activity streaks. Your application supplies the subject, progress key, award amounts, thresholds, and periods, so the same component can support several kinds of progress.

Use cases
- Learning apps: award points for lessons and track consecutive practice periods.
- Mobile habit trackers: display activity streaks using your own definition of a completed day.
- SaaS onboarding: translate completed setup steps into points and milestone levels.
- Communities: recognize repeated participation across independent contribution tracks.
- Games: track experience and levels for players or teams without embedding game-specific rules.

How it works
Mount the component and create a Progression client. accrue adds points and calculates a level. recordActivity uses periodKey and expectedPrevious to continue a streak or start again after a gap. get reads progress and can recompute the level from a revised threshold ladder. reset and bounded eraseSubject support lifecycle management.

Integration
Your backend authorizes reads and awards, deduplicates events, calculates periods, and handles late activity. Mounts isolate data and scopes provide namespaces. Rewards, streak freezes, leaderboard ranking, and UI remain host features; React is not required.

Maintained by [bntvllnt](https://bntvllnt.com) at [VLLNT](https://vllnt.com). Find the author on [GitHub](https://github.com/bntvllnt) and [X](https://x.com/bntvllnt).

Benefits

Use cases

how to track XP and levels in Convex

Install @vllnt/convex-progression and call xp.accrue(ctx, subjectRef, key, delta, thresholds) from any Convex mutation. The component stores cumulative XP and computes the current level by counting how many thresholds that XP has crossed. Thresholds are passed by the host on every write, so the ladder can change without a migration.

how to track activity streaks in Convex

Use xp.recordActivity(ctx, subjectRef, key, periodKey, thresholds, { expectedPrevious }) from @vllnt/convex-progression. Pass the current period key and the expected previous period key; the component continues the streak if they are consecutive or resets it if there is a gap. The host defines what a period means, such as a date string for daily streaks.

Convex component for onboarding progress and milestones

@vllnt/convex-progression supports SaaS onboarding by translating completed setup steps into points via accrue and defining milestone levels through threshold arrays. Each onboarding track can use a separate key or scope, and xp.get returns the current XP, level, streak, and maxStreak without coupling the component to any domain logic.

how to run multiple independent progress tracks in one Convex app

Mount @vllnt/convex-progression multiple times using app.use(progression, { name: 'gameProgress' }) and app.use(progression, { name: 'learningProgress' }) in convex.config.ts. Each mount has isolated tables and its own scheduled work. Construct a separate Progression client for each component reference to keep data fully separated.

Frequently asked questions

Does @vllnt/convex-progression include any UI or React utilities?

@vllnt/convex-progression is a backend-only component with no React entry point. It exposes mutations and a query that your own backend functions call. UI display, streak freeze logic, leaderboard ranking, and reward delivery remain host responsibilities.

How does @vllnt/convex-progression handle changing XP thresholds?

Thresholds are passed by the host on every call rather than stored in the component. When you call xp.get(ctx, subjectRef, key, scope, thresholds) with a revised threshold array, the component recomputes the level from the stored XP against the new ladder. This avoids backfill migrations when your level design changes.

How does @vllnt/convex-progression authenticate users?

@vllnt/convex-progression is auth-agnostic. The host resolves identity through its own auth mechanism and passes an opaque subjectRef string to each method. The component never receives end-user tokens or raw deltas; your backend authorizes every read and write before calling the component.

Can @vllnt/convex-progression delete data for a user who is removed?

Yes. xp.eraseSubject(ctx, subjectRef, scope?, batch?) deletes all records for a subject in bounded batches and reschedules itself until the data is fully removed. This supports GDPR-style deletion without blocking a single mutation for an unbounded amount of time.

What version of Convex does @vllnt/convex-progression require?

@vllnt/convex-progression requires convex@^1.45.0 as a peer dependency and Node.js 20 or later for the development toolchain. It is currently at version 0.1.0 and is described as an unreleased candidate, so check the repository for current publication status before adding it to a production project.

Links