Akademisk Boldklub (a Danish football club currently playing in the country's Betinia Liga division) was founded in 1889 by students at Copenhagen's prestigious technical institute. They had translated the English football association's rulebook into Danish after deciding that cricket just wasn't enough.
For a while, players could only put on AB's owl-mascot jersey if they passed the entrance exam to the university or the Polytechnic Institute (now Technical University of Denmark and one of the foremost in Europe). Happily, Niels Bohr didn't have trouble passing the exam and kept goal for AB in 1905 alongside his brother Harald, who became a famous footballer as well as a mathematician. Club lore says Niels Bohr once let a long ball roll toward his goal untouched because he was leaning against the post working on a math problem.
Datum joined AB as a kit partner for the 2025/26 season along with a collection of tech friends like Myriad360 and Plane. In addition to aiming for promotion, the club was actively growing its global audience while tapping into their technical roots. This spring, the bet paid off: a 5-0 win on the final day, the championship, and promotion to the Betinia Liga for the first time in ten years.
Ready, set, grow!
What I inherited
Zac, our fearless CEO and AB investor, moonlighted as AB's web guru for the past year. But with the team's promotion and a brand refresh ready to launch, he needed more firepower to get things over the line. That's where I came in! First, I took stock of the situation. Like most startups, AB was juggling multiple websites and apps - and none of them were quite right.
The live one: a WordPress site with a decade of accumulated plugins, page builders, and content in the way old WordPress sites do. It worked, in that it rendered.
The half-built one: a new WordPress theme on SportsPress, a month or two of redesign work already sunk into it. SportsPress wants you to maintain your own database of players, fixtures, results, and stats inside WordPress. Sounds reasonable, but hold that thought.
The Frankenstein one: Working evenings with Claude, Zac had pulled the important pieces out of WordPress in search of better and more scalable services. But along with clear improvements came a good dose of complexity. Here's what Zac had in place:
- The shop moved to Shopify at shop.ab.dk
- Auth and user profiles (a super important element) moved to Descope
- A fresh Strapi instance with all the blog content and categories ported over
- Mailgun for email, Wasabi for media and some 3rd party scraped sports data APIs
- The Vercel integration set up so a push to main just deploys
- Plus a Next.js app to sit in front of all of it!
It was clear that WordPress didn't need to be in the equation, so my job was to make it go away, launch the site, and get everything ready for the new season.
The spreadsheet that killed two codebases
AB's promotion came with something really valuable: league data. The club now gets a set of embeddable widgets from the DBU (Danish soccer league) and Sports Innovation that cover player pages, match lineups, schedules, live scores, realtime stats, heat maps, and highlights. To figure out what we'd need to rebuild, I put all of them in a spreadsheet and handed the task to Claude.
Happily, the answer was none of them. All ~80 widgets were iframe embeds from dash.si-ab.com. The league maintains the data and the league renders the data. Our job was simply to put the right embed in the right place with the right styling, which would allow us to collapse the architecture substantially.
Without the need to render sports data, we didn't need SportsPress or WordPress. And if the site's main job is content, brand, and embed management, we didn't need a big React framework either. Two birds killed with one embedded stone.
Astro, meet Claude
Astro already powers Datum's various websites, which are mostly static, content driven, with a handful of interactive islands. It made sense to lean into the same pattern for AB.
In addition to Astro 7 we chose Vercel for server side rendering (SSR), Strapi Cloud to back the content, and a small SiWidget component to handle all of the league embeds. The component builds the embed URL, strips the padding, and handles cookie consent in both Danish and English. Then it lazy loads the iframe.
I started vibe coding on the last day of June, arming Claude Code with an AGENTS.md brief that codified the folder layout, brand guardrails, i18n rules, and the migration order. My job was to review, steer, and delete what didn't belong while gathering content and feedback from the AB team. It took us three weeks to go from an empty branch to launch.
In the spirit of AB's nerd lineage, two fun shout outs:
- The repo's onboarding doc is addressed to AI assistants first and humans second.
- The dev server runs on port 1889, AB's birth year. Everyone loves a good Easter egg!
Localization, brand as code, social cards, and redirects
Preparing for a new website launch means sweating the details. First up was localization.
While there is a growing international fan and sponsor base, AB's primary audience is Danish and the website needs to help Google (and humans) understand that. This meant keeping Danish at the root (/kampe, /nyheder, /hold) with English content sitting under an /en/ url structure. Astro's built-in i18n handles the routing, a middleware resolves locale and guards the Descope session, and UI strings come from a hand-crafted dictionary. A content workflow that leverages both DeepL in Strapi and a human review helps keep new content on target.
To support AB's brand refresh and help with maintenance over time, we decided to codify everything possible into code. The club's new brand guidelines are really solid, but the fastest way to ruin good guidelines is to let every page interpret them independently. The tokens live in one file (src/styles/tokens.css) and everything reads from there: AB green #006A52, the Pantone gold, and a neon #00FF1F that is strictly for screens.
In speaking with the AB team, it’s clear that their marketing is centered around social media, especially around games. The old site had terrible social card support, and it was always the same generic crest on a green rectangle. To spice things up, the new site has four dynamic opengraph image endpoints under /api/og/, for matches, players, articles, and partners. All 1200x630, generated on the fly.

Finally, a decade of WordPress meant a decade of backlinks, bookmarks, and search results. To support the launch, we mapped every legacy URL to its new home in a vercel.json, evaluated at the edge before any Astro function runs, with exact matches first and a wildcard catch-all that sweeps every old news slug into /nyheder/:slug.
What we actually learned
The best decision in this project was subtraction.
We didn't build a sports data platform, because the league already runs one. And we retired WordPress despite a decade of accumulated content and habit pulling the other way. The site that shipped is smaller than any of the three sites it replaced, and that's the point: AB's staff publish in Strapi, the league's widgets update themselves, and the deploy pipeline is a push to main.
Zac spent a year moving the hard pieces out of the monolith: commerce, auth, content, media, delivery. That's a big reason why the new Astro frontend only took three weeks. Thanks, boss!
First home match at Gladsaxe Stadium, July 31st. Kom så, AB.