Achievement ideas

Every achievement JAM could offer with the data it keeps today, what is still missing before any of them can be earned, and a first batch of one-off badges drawn as 16px pixel art, so the ideas can be judged as badges and not as words. Pick the ones worth keeping; each can come back as its own item for an icon and the build.

Decided for this sheet, overturn at review
  • Two kinds of achievement. Trees count something up through Stone to Diamond and wear a fruit (on a shield from platinum). Badges are earned once and sit on a round coin, so a badge never reads as a tier.
  • A badge's rim says its kind: red for firsts, blue for time of day, green for the calendar, purple for hidden ones.
  • A hidden badge shows one shared "?" coin until it is earned; after that it looks like any other badge.
  • Every idea is grounded in what jam-core stores today: running and cycling JAMs, joining as an RSVP only, no check-in, weather, chat or ratings. Times are read in Europe/Brussels.
  • Only the trees go next to a name. Badges live on the profile.
  • The tree thresholds stay the placeholders from Avatars and achievements.
01 · Where we are

Two trees are drawn, each with six tiers and a locked silhouette, plus the states a tree can be in. That is the whole of it: so far achievements are drawings only.

JAMs joined
Not yet earned Stone, 1 JAM Bronze, 5 JAMs Silver, 10 JAMs Gold, 25 JAMs Platinum, 50 JAMs Diamond, 100 JAMs
1 / 5 / 10 / 25 / 50 / 100, placeholders
JAMs created
Not yet earned Stone, 1 JAM created Bronze, 3 JAMs created Silver, 5 JAMs created Gold, 10 JAMs created Platinum, 25 JAMs created Diamond, 50 JAMs created
1 / 3 / 5 / 10 / 25 / 50, placeholders
Not yet earnedJoin your first JAM to earn Stone
In progress7 / 10 JAMs, 3 more to Silver
Emma Gold, JAMs joinedShown off, next to the name

Every state is drawn in full on Avatars and achievements.

Nothing in the app or the API yet. jam-core has no achievement table and no unlock logic, and jam-web shows no achievement anywhere. Everything below is the plan for what those would be.
02 · The gap

What has to exist before anyone earns the first Stone. These are the jam-core and jam-web items; none of it is in this sheet's scope.

  • A stored unlock: who, which achievement, when. jam-core
    Leaving a JAM, unstarring and removing a connection all delete rows, so an achievement worked out live from those rows would vanish again. Unlocks are kept once earned, never recomputed.
  • Unlock evaluation when a person joins or creates a JAM, connects, or joins a group, and when a JAM's start time passes (the time-of-day and calendar badges), plus a one-off backfill so existing members start with what they already earned. jam-core
  • An API to read a person's achievements: earned with the date, progress to the next tier, and the hidden ones only as a count until earned. jam-core
  • Profile UI: earned, in progress, locked and hidden, and the tree icon next to a name. jam-web
  • Sharing settings respected: an achievement says something about your sessions, history or connections, so it follows that subject's per-person sharing setting before anyone else sees it. jam-core jam-web
  • An honesty caveat: joining a JAM is only an RSVP; there is no check-in. Every "joined" count trusts the RSVP until a check-in exists. Counting a JAM only once its start time has passed with you still on it is the cheapest guard.
03 · Idea catalog

One card per idea: the badge (or a dashed placeholder), the rule, and the jam-core data it would be worked out from. Twelve badges are drawn as a first batch; the rest wait for a pick.

buildable today every field it needs exists needs a small addition one constant or a small table needs new data JAM does not record it

One set: badges next to the trees, at 64px

Stone
Gold
Platinum
Diamond
Firsts
Time of day
Calendar
Hidden
Not found

The same drawing at 16, 32 and 64px

Early bird, 16px Early bird, 32px Early bird, 64px Wolf pack, 16px Wolf pack, 32px Wolf pack, 64px Wolf pack, not yet earned Not yet earned: the flat silhouette, as the trees do it

Milestone trees

Counted up through Stone to Diamond, one fruit per tree. The two drawn trees, and candidates for more; each would need its own fruit.

JAMs joined

How many JAMs you joined, 1 to 100.

Count of attendance rows, the JAM's session.starts_at past.

Trusts the RSVP: there is no check-in.

buildable today drawn

JAMs created

How many JAMs you organised, 1 to 50.

Count of session where organiser_id is you.

buildable today drawn
not drawn yet

Connections made

How many people you are connected with.

connection with status = 'accepted', either side.

buildable today
not drawn yet

Groups joined

How many groups you are a member of.

group_member with status = 'member'.

buildable today
not drawn yet

Friends invited

How many people signed up with your invite link.

profile.invited_by_code pointing at your invite_code (owner_profile_id).

buildable today
not drawn yet

Kilometres covered

Distance of every JAM you joined, added up: 10 km to 1,000 km.

Sum of session.distance_m over joined JAMs.

distance_m is optional; a JAM without one adds nothing.

buildable today
not drawn yet

Weeks in a row

Consecutive weeks with at least one JAM: 2 to 52.

Joined JAMs grouped by week of session.starts_at, Brussels time.

buildable today
not drawn yet

Crowd puller

People who joined the JAMs you organised, added up.

attendance on session where organiser_id is you, yourself not counted.

buildable today

One-time firsts

Earned once, the first time you do something. Red rim. Most of the app's first steps are already rows with a date on them.

First connection

Your first accepted connection. Two cherries, one stem.

connection.accepted_at

buildable today drawn

First group joined

You became a member of a group. A bunch of grapes.

group_member.joined_at, status = 'member'

buildable today drawn
not drawn yet

First group created

You started a group.

group.owner_id, group.created_at

buildable today

Friend joined with your invite

Someone signed up with your invite link. A letter with a strawberry seal.

profile.invited_by_code → invite_code.owner_profile_id

buildable today drawn
not drawn yet

First starred JAM

You starred a JAM to keep an eye on it.

star.created_at

Unstarring deletes the row; the unlock has to be kept.

buildable today
not drawn yet

Second city

You joined a JAM in a city other than your first one.

Two distinct session.city_id over joined JAMs.

buildable today
not drawn yet

Both sports

You joined a running JAM and a cycling JAM.

session.sport is running and cycling over joined JAMs.

buildable today
not drawn yet

Onboarding done

You finished setting up your profile.

profile.onboarded_at

Everyone from before onboarding was backfilled to their sign-up date, so they get it too.

buildable today
not drawn yet

First group JAM

You joined a JAM posted in one of your groups.

session.group_id set, on a joined JAM.

buildable today

Time of day

When the JAM starts, in Brussels time. Blue rim. Earned once the start time has passed with you still on the JAM.

Early bird

A JAM that starts before 07:00. An orange coming up over the hill.

session.starts_at, Brussels time

buildable today drawn

Night owl

A JAM that starts at 21:00 or later. A banana moon.

session.starts_at, Brussels time

buildable today drawn
not drawn yet

Lunch break

A weekday JAM that starts between 12:00 and 13:59.

session.starts_at, Brussels time and weekday

buildable today

Calendar and seasonal

A JAM on a day that means something. Green rim. Worth a badge each because they come round once a year: miss it and it is a year's wait.

New Year's Day

A JAM on 1 January. A firework in jam colours.

session.starts_at date, Brussels time

buildable today drawn

Longest day

A JAM on 21 June. A lemon for a sun.

session.starts_at date

buildable today drawn

Halloween

A JAM on 31 October. A pumpkin, which is a fruit.

session.starts_at date

buildable today drawn

Shortest day

A JAM on 21 December. Holly, the fruit that is out then.

session.starts_at date

buildable today drawn
not drawn yet

JAMiversary

A JAM on the anniversary of the day you signed up.

profile.created_at against session.starts_at

buildable today
not drawn yet

Gentse Feesten

A Ghent JAM during the Gentse Feesten. One of a family of local ones.

session.city_id and starts_at

Needs the festival's dates for each year, as a small table.

needs a small addition
not drawn yet

Car-free Sunday

A cycling JAM in Brussels on its car-free Sunday.

session.sport, city_id, starts_at

The date moves each year: the same small table of dates.

needs a small addition
not drawn yet

Rain or shine

A JAM that went ahead in the rain.

Nothing: JAM keeps no weather.

Would need the weather at the meeting point and time.

needs new data

Hidden

Shown as the "?" coin until earned, so finding one is a surprise. Purple rim once found. The profile only says how many are still out there.

Not found yet

The one coin every hidden badge shows until it is earned.

The count of hidden badges you do not have.

drawn

Founding member

You were on the beta list, or signed up before launch. A sprout.

beta_allowlist.email, or profile.created_at before launch

Needs a launch date to compare against.

needs a small addition drawn

Full house

A JAM you organised fills to capacity. A jam jar full to the lid.

attendance count reaching session.capacity

Checked on each join: a leave afterwards does not take it back.

buildable today drawn

Wolf pack

A JAM with three or more of your connections on it. A paw print in jam.

attendance joined with your accepted connections

buildable today drawn
?

Same time next week

A JAM on the same weekday four weeks running.

session.starts_at weekday and week

buildable today
?

Race pace

You joined a JAM run at race pace.

session.effort = 'race_pace'

buildable today
?

Trailblazer

You joined a JAM on trail.

session.surface = 'trail'

buildable today
?

Marathon week

42.2 km or more of JAMs in one week.

Sum of session.distance_m ≥ 42,195 within a week

buildable today
?

Track day

You joined a JAM on a track.

session.surface = 'track'

buildable today
?

Showed up

Ten JAMs where you were actually there, not just on the list.

Nothing yet: joining is an RSVP.

Needs a check-in.

needs new data
04 · In context

A profile's achievements, mixing tree tiers, firsts, a calendar badge and a hidden one, and the same person in a list. Only the trees go next to a name: that slot belongs to them.

04.1 · Profile, achievements

Sofia Platinum, JAMs joined

Ghent · running · 58 JAMs, 12 created

Achievements7 earned · 3 hidden left
JAMs joinedPlatinum
JAMs created12 / 25
First connectionMar 2026
First groupApr 2026
Early birdMay 2026
Longest day21 Jun 2026
Wolf packFound!
HiddenKeep going
Night owlStart at 21:00
Halloween31 Oct
Invite a friendShare your link
HiddenKeep going
04.2 · Next to a name: trees only
Sofia Platinum, JAMs joinedGhent · running · 58 JAMs›
NNoah Stone, JAMs createdGhent · cycling · 1 JAM created›
Lucas Diamond, JAMs joinedAntwerp · cycling · 112 JAMs›

A badge says what happened once; a tier says how far you have come, which is what someone glancing at a list wants to know. A coin next to a name would also be a second, competing icon there.

Locked badges show their silhouette with how to earn them; hidden ones show only the "?" coin and never say how.