Stagent Wrapped: a year of shows, airports, and cities in one page
Spotify Wrapped shows you how much music you listened to. Stagent Wrapped shows you how much music you made. Here's how we built it, and why the data was already waiting.
Every December, Spotify Wrapped turns a year of listening into a scrollable story you can't help but share. Your top songs, your top artists, the minutes you spent inside your headphones. It's one of the smartest pieces of product marketing any software company has ever shipped, and it works because Spotify already has all the data. They don't build Wrapped. They render it.
Last week we shipped the same idea for the people on the other side of that listening. Stagent Wrapped is a year-in-review for touring artists and booking agencies. It shows you how many shows you played, how many cities you landed in, which airport saw you most often, how many hours you spent in the air, what your busiest month was, and a dozen other numbers that add up to what a year on the road actually looked like. The artist version reads like Spotify's. The agency version is the same story from the other seat, with bookings across the roster, travel coordination stats, and growth versus the year before.
I want to write about it because the interesting part isn't the feature. It's what the feature revealed about the product we'd been building without quite noticing.
The data was already there
The first draft of Wrapped was built in a single day. Not because we're fast, but because there was almost nothing to build. Every stat Wrapped shows is a query against data Stagent was already storing, because Stagent is a booking platform, and every booking is a little data point about a real event that happened in the real world.
A booking has a venue, a date, a duration, a country, a city, a promoter, a fee, a status. It points at a flight, an accommodation, a ground transport. It belongs to a tour, to an artist, to an agency. Every time an artist plays a show through Stagent, we accumulate enough metadata to describe the show more thoroughly than most of the people who attended it. Nobody had been looking at that data as a story before Wrapped. It was just the substrate the operational features ran on.
When we started writing the WrappedStatsCalculator, most of the methods were one-liners. 'Total shows' is $confirmedBookings->count(). 'Countries visited' is a distinct-count of the country column on the venues table. 'Total performance time' is the sum of the duration field. 'Busiest month' is a group-by on the booking start date with a sort. The only reason writing this felt like building anything at all was because we had to decide which numbers mattered, not compute them.
That's the tell. When a product accumulates interesting data as a side effect of being used, a year-in-review isn't really a feature. It's a reframing.
What the artist sees
The artist version of Wrapped is designed to feel personal, because the underlying numbers are personal in a way that music streaming can only approximate. Spotify knows what you listened to. Stagent knows what you lived.

A touring artist's Wrapped opens with the raw count of shows performed and the success rate of their pipeline, how many of their inquiries turned into confirmed gigs. The number of unique venues they played. The busiest month of the year. What percentage of their shows fell on weekends. Their total performance minutes, formatted into a shape the brain can hold. A small joke at the bottom where we divide performance minutes by four and tell the artist how many tracks they played, which isn't real but is the kind of approximation you laugh at and then share.
The geography section is where it gets emotional for most users. How many countries. How many continents. How many cities. The country they played most often. The city they returned to. The airport that saw them most. The total hours they spent in the air across the year.
The travel section carries the same weight. Total flights, total flight minutes, the longest single flight, the total nights spent in accommodations. This is the data that makes an artist's partner understand why they were tired in November. It's also the data most artists have never actually seen laid out, because the only place it existed was inside an operational tool nobody was reading as a narrative.
At the bottom there's a set of fun facts we generate procedurally from the raw numbers. Each one is a small pattern-match. If a metric hits a threshold, a line gets added. None of them are impressive on their own. Together, they're the part of the page people screenshot and send to their group chat.

What the agency sees
The agency version is a different story from the same data, and the reason it matters to us more than the artist version is that agencies are the customer. An agency running Stagent pays to manage a roster, and at the end of the year, they get a Wrapped that reads their own operation back to them.

The roster card is the headline. Total bookings across the whole agency, how many artists were active, how many hours of performance the agency's artists put on stages, the success rate of the pipeline, the busiest month, and the top venue. This is the first page an agency owner scrolls to, because it turns twelve months of quietly grinding through emails and contracts into a single number with their name on it.

Global reach is the next one that lands. Twenty-two countries, a hundred and fifty-five cities, a ranked list of the markets where the agency's artists played the most. Most booking agencies have a rough sense of where their business lives, but very few of them have ever seen it laid out like this. The top-markets bar chart turned into the most-shared section of the entire Wrapped, because an agency that thought of itself as 'mostly Germany' suddenly had receipts for exactly how German their year was, or how it wasn't.

The travel coordination card is the one I care about most, because it's the logistics story that nobody in this industry ever tells about themselves. Three hundred and eighty-two flights coordinated. Six hundred and sixty-eight thousand kilometres booked. Ninety-five hotels across fourteen countries. The top airline the agency flew on. The split between car rides, trains, and the occasional ground transport anomaly the system doesn't know how to name. A booking agency is not just a dealmaking operation. It's a logistics operation that happens to also close deals. Showing an agency the scale of what they moved across a year turns the operational grind into a visible asset. The flights coordinated. The transports arranged. The accommodations booked. The distance covered by their people. This is work you already did, and here's what it looks like when you stack it up.
Every agency that got their Wrapped sent it to their team the day it arrived. That was the signal we cared about.
The part behind the page
The technical shape of Wrapped is simple until the share cards arrive. A Wrapped page is a scrollable blade view with Alpine.js animations running on precomputed stats, so page load is fast and nothing hits the database while a user is scrolling. The share cards are where it gets fun. When a user opens their Wrapped, we queue a background job that renders a set of themed OG images, one per section, using Browsershot against a headless Chromium. Those images get uploaded, URLs get signed, and the share sheet becomes a screenshot-ready set of visuals an artist can drop straight into their Instagram story.
We had to refactor the route scheme twice in the same week because the public shareable URLs needed signed tokens, and the OG image endpoints needed to be discoverable without authentication. The final shape uses Laravel signed routes and a per-team hashid in the path, so a shared link works for anyone who has it and expires on our terms. Not elegant in v1, very clean by the end of the week.
Email was the other piece that mattered more than we expected. We built an artisan command that bulk-queues the Wrapped notification emails with a key-highlights summary, so agencies could choose to send Wrapped to every artist on their roster in one sweep. The email opens with the top three or four numbers and a link to the full scrollable page. That pattern is almost certainly lifted from Spotify's own email, and we didn't pretend otherwise.
The accumulated-data observation
The reason I wanted to write about Wrapped is that it's the purest example I've seen of a principle I keep coming back to. A vertical product accumulates interesting data as a side effect of operating. You don't build the data as a feature. You generate it by being the place where the work happens. After a year of an artist using Stagent seriously, we have a year of their tour stored in structured form, ready to be read as a story, because managing bookings is already the work of structuring it.
The value of that accumulated data is invisible until you reframe it. Operationally, the booking table is a bunch of rows you query for itineraries and invoices. As a story, it's the year an artist had. Same rows, completely different product. The only thing we added for Wrapped was the rendering layer.
This is a thing I'd tell anyone building vertical software to watch for. The data you're storing to run the product is almost always a more interesting data set than you think. Every once in a while, stop and ask what the accumulated truth inside your database would look like if you rendered it as a narrative for the user. Sometimes the answer is 'nothing interesting'. Sometimes the answer is Wrapped.
Stagent Wrapped took a day to build and is the most talked-about thing we've shipped in a year. The part that took the longest was deciding which numbers to show, which is the correct shape for this kind of problem. The data had been waiting. We just finally looked at it the way our users would.

Hi, I'm Mischa. I've been Shipping products and building ventures for over a decade. First exit at 25, second at 30. Now Partner & CPO at Ryde Ventures, an AI venture studio in Amsterdam. Currently shipping Stagent and Onoma. Based in Hong Kong. I write about what I learn along the way.
Keep reading: The painkiller test: how I decide what to build next.