Skip to content
← Blog Blog

Four products, sixty-eight repositories

Two weeks inside GolfNext. What we actually build, what thirteen years of software looks like underneath it, the integrations we started in week two, and an honest look at the goals I set myself before I'd signed anything.

Four products, sixty-eight repositories

I started at GolfNext on Monday the 3rd of August, at 8:00. I’d pictured a quiet office and twenty minutes of standing around. Most of the team was already in and in a good mood about it. I’d brought a cheesecake, which we ate after lunch, because I’ve been in Denmark long enough to know that turning up with cake is not really optional here.

Peter, who started the company in 2012, had Claude open before I’d found my desk, working through the accounts and permissions I’d need. Small thing to notice on a first morning. It told me more than an onboarding deck would have.

The first post on this blog was a letter I wrote to myself before I’d signed anything, full of predictions about a company I’d visited once. This is where I hold it up against what’s actually here. Most of what follows isn’t really about me though. It’s the company I want to describe: what we build, what sits underneath it after thirteen years, and what we’re planning to do about that.

What GolfNext builds

If you’ve never thought about the software a golf club runs on, here’s the shape of it. A club is a small business wearing several hats at once. There’s a pro shop, a driving range, memberships, a booking system, and more and more often a simulator bay or two. The booking system handles tee times, which, since I had to learn this myself, have nothing to do with tea. A tee time is the slot a group is booked to start their round on the first hole, and the whole day at a club is arranged around that grid.

Historically each of those hats arrived as its own box, from its own vendor, with its own software attached. Buy the dispenser, get the dispenser company’s system, whether or not it suits how you run your club.

Our position is the opposite of that. Your hardware and your infrastructure stay yours, and you stay free to pick the software that fits. We want to be open to any integration, so whatever management system a club already uses to run its tee times, the aim is to work with it rather than ask them to throw it out. Freedom to choose, power to connect.

Self-service kiosks. A digital reception that runs around the clock. Green fees, rentals, pro shop purchases, all without someone standing behind a counter. As far as we know it’s the only one of its kind in golf. A club gets fewer staffed hours and keeps earning outside opening times. A player gets the same convenience they already have everywhere else in their life.

Driving range payments. Payments on the range that work with any ball dispenser brand. That compatibility is the product. The dispenser belongs to the club, or to whoever sold it to them, and being able to sit on top of all of them is the whole selling point. Cards, apps, wallets, PIN codes, with real-time analytics behind it. In a lot of places the range still runs on cash, and this is where demand is growing fastest right now. More than 500 million balls a year go through it. That’s a lot of slices.

Voucher management. Issuing, distribution and redemption, all digital, from a single ticket up to a full sponsor package.

Simulator management. Automated access control, so a simulator only runs during a paid session. No more time theft, better utilisation.

Where that adds up to today: 400+ venues, 18 countries, 350,000+ active users. Founded in Denmark in 2012 and still very Danish, which is also why I walked out of my first day having decided to get serious about my Danish.

The stack, without the polish

Sixty-eight repositories. JavaFX on the desktop side, PHP, Vue, React, React Native, Spring, Java, Kotlin. All of it on AWS.

Written out like that it looks like indecision, and it isn’t. Thirteen years, four product lines, hardware sitting in the field, and for most of that history the software was built by external partners who were good at their jobs. Every project picked what made sense on the day it started, and most of those calls were reasonable ones. What never happened is anybody going back afterwards to make the choices agree with each other.

So, the honest state, because I said in the letter I’d write these things down rather than smooth them over.

A good share of those sixty-eight repositories hadn’t been touched in years and were never archived. Forks, spikes, one-off tools that outlived their reason. I started archiving in the first week, slowly, because for most of them I didn’t yet know what I was looking at, and not knowing is a much better reason to leave something alone than to delete it.

In the code you can read the generations. Several package structures inside the same language, none of them wrong, all of them different. An AGENTS.md written for Codex and a CLAUDE.md written for Claude, sitting in the same repository, describing the same project, disagreeing about it. A README.md documenting a version of the system that doesn’t exist anymore. A runtime that went end of life a while back and is still running. And a release process that’s properly good for some of our tools and a snowflake for others, where part of it lives in a pipeline and part of it lives in somebody’s head.

Security sits at the top of the pile. Of the twenty-nine engineering practice items I’ve written down so far, five are marked high priority, and all five are security. That’s not a discovery about GolfNext in particular. It’s what thirteen years of shipping tends to look like anywhere nobody has recently been paid to go and look.

Since I made a prediction about all this from the outside, I owe you the result. It’s roughly where I expected it to be, and I mean that as a fair outcome rather than a complaint. This is thirteen years of continuous delivery by people shipping features that customers actually needed, on deadlines, with the priorities they were handed at the time. You’d find much the same picture at most companies this age, and I’d rather be the person who tidies it than the person who tuts at it. The one prediction that landed exactly was the dull one: I’d guessed from outside that the repos would be under-automated, and they are. That’s my opening.

The part I got wrong

I’d braced myself for the products to be the weak spot. Companies carrying a stack like ours often have shipped-anyway software on top, the kind where you can feel the deadline in the interface.

That’s not what’s here. The products are good. There’s room in all of them, obviously. But the thing I keep noticing in meetings is that everybody reasons from the customer’s side first, including people with no engineering background at all. What does the player standing at the kiosk at half five in the morning actually experience. What does a club manager have to explain to a member when something goes wrong.

That instinct is hard to retrofit into a team. Package structures can be refactored and READMEs can be rewritten, and both of those are just work. Teaching a group of people to care about the person at the other end is a different order of problem, and we don’t have it.

What we started in week two

Two integrations landed almost immediately, and they’re the same bet in different clothes. The platform is only open if it actually connects to the systems clubs already run.

teeControl is a management system a lot of clubs use, and we’re integrating it so it works through our kiosks. First impressions are good. First impressions are also cheap, and there’s a fair way to go from here. We need proper test systems. We’ll probably have to adjust some of our own flows to fit theirs. There are decisions still to settle on both sides. That’ll be a process rather than a sprint, and I’d rather say so now than write a triumphant post about it in week two.

Lightspeed is a player-facing app we want to support as a payment option. Peter had already built a first version before I arrived, and taking it over was my excuse to get my hands into real code here for the first time. Ten thousand lines, read end to end, then run and poked at until I understood what it was doing. That produced a list of bugs and a stack of follow-up stories, which is what reading anything carefully produces. The more useful outcome is that it’s in my head now as well as his.

And Verifone terminals on the desk, which is the regular reminder that a lot of our software ends in a physical object somebody has to touch.

The approach John and I settled on is to skip the big upfront specification. John is the other developer, though that undersells him, since he’s as much solution architect and project manager as engineer. Get a test instance, build against it, let reality write the documentation. Two weeks in I don’t know these systems well enough to write a good spec, and pretending otherwise would just produce a document we’d quietly stop reading by September.

One small thing worth passing on to anyone thinking about working somewhere like this. I spent my first few days being patient about access, on the assumption there was a process I was supposed to wait for. Then I said out loud that this was more or less what I’d been hired for, and could I please just have it. Half an hour later I had AWS. The waiting was entirely my own invention.

How we ship

The most interesting problem of the first two weeks wasn’t inside a repository. It was working out how changes get out to customers.

I spent a Friday on proper detective work. CloudWatch logs on one screen, a downloaded database snapshot on the other, lining transaction states up against what the code believes should have happened. Somewhere in there I found forty commits that had never been pushed anywhere. This is the unglamorous half of bringing knowledge in-house. Credentials are the easy part. Rebuilding an understanding of what the system actually does takes a lot longer.

We don’t have a gradual rollout mechanism today. What we do have is customers who are physical places, and a handful of them are a short drive from the office. So the first ring is geography. A few nearby clubs get the new version first, and if it goes wrong the recovery plan is twenty minutes in a car with a spare terminal in the boot. That took about five minutes of conversation to arrive at, because once you notice where the customers are it’s a fairly obvious move. It’s not what I’d draw on a whiteboard. It’s available this week, and it buys enough confidence to keep shipping while the proper thing gets built.

Learning the game and the words for it

On day three I played the first round of golf of my life, with colleagues. Seven or eight shots a hole. Never a ten. We didn’t lose a single ball all round, which I’m told is the more impressive statistic for a beginner. Nobody wrote down a score.

I’d recommend the general version of that to anyone joining a company whose domain they don’t know. Not golf specifically. Going and doing the thing the software is about.

The week after, John and I sat down for what turned into the most useful two hours of week two: agreeing what we call things, before three systems each invent their own word for the same concept. Nine holes is a loop. Stroke index ranks the holes by difficulty. There’s rating category. None of this is exotic if you play golf, and all of it is invisible to an engineer who has never stood on a tee box, which two weeks ago was me.

Getting the vocabulary right early costs almost nothing. Getting it wrong costs you three services, three names for one thing, and a translation layer nobody set out to build. I did run one check I’d suggest to anyone doing this: I had Claude verify “loop” on its own, because it smelled to me like a word engineers invent and then talk themselves into believing is domain language. It came back as real golf. Using the model to check our own vocabulary, rather than to write code, is one of the better uses I’ve found for it so far.

Twenty-nine items, and where this is going

The improvement list lives in ClickUp now, mostly so I can stop carrying it around in my head. Twenty-nine items, all still in the backlog, grouped roughly into repository standards and conventions, security and secrets, CI/CD and testing and dependencies, infrastructure and data, architecture direction, and AI and agents.

The first thing we’ve actually rolled out is the least exciting item on the whole list. mise, which pins and installs the right language versions per project, so you clone a repo and the correct Java turns up on its own. With that many technologies spread across that many repositories, the tax you pay all day long is switching between them, and that particular tax is avoidable.

The goal hasn’t changed since the letter. Build a landscape where context is cheap to pick up. If a new engineer, or a fresh AI session, can understand a service quickly, work can start immediately, by whoever picks it up. If they can’t, every task starts with archaeology. Everything on that list of twenty-nine sits downstream of that one sentence.

The scorecard

Which brings me back to the letter, and the promise to mark my own homework in public.

Stay on the keys. Held. Two terminal fixes shipped, pull requests reviewed, and I’ve taken ownership of one of the apps. I’m still building, which was the condition I set before I accepted the job.

Rebuild the understanding, not just the access. Mostly. The CloudWatch afternoon, the database snapshot, the Lightspeed handover: that’s the right shape of work. What I can’t claim yet is being able to release anything in the stack without asking somebody.

Candor in the open. Held, and easier than I expected, mostly because the room here makes it easy.

Now the other half.

Goal one slipped. “Make the work visible” was first on the list and this blog was supposed to be how. Every post before this one was written before I’d signed the contract, which turns out to be the easiest possible time to write about a company. Then I actually started, and for two weeks there were things in front of me that mattered more than a blog post. I’m not going to call that a crisis. I did write that if it went quiet I should treat it as a warning sign, so: noted.

The cold start is nowhere near five minutes. I set myself five minutes from clone to running code and told future me to go and time it. I haven’t timed it properly, which is its own small failure. I’ve cloned enough of these repositories by now to give a fair estimate though. Somewhere between two and six hours depending which one you pick, call it four on average. Getting the iOS build running took most of a day of Xcode, pods and emulators. mise is the first real step at closing that, and a step isn’t a number.

The shared AI kit is item twenty-nine of twenty-nine, and that part is on purpose. In the letter I called it the thing that turns “AI-first” from a slogan into shared tooling. Two weeks in I can see why it can’t come first. A shared kit built on top of sixty-eight inconsistent repositories would mostly just encode the inconsistency. Foundation first, kit second, and I’d defend that order. What I won’t pretend is that the order is free. Until we get there, I’m getting a lot of leverage out of a setup I’ve spent a year tuning that nobody else here has yet.

And the days ate the space to think. I wrote that the creative, playful time isn’t a reward you earn once the serious work is done, that it is the serious work. Two weeks in, it’s the first thing the calendar takes. One thing helps here, and it’s specific to this industry: golf is seasonal. Clubs are busy now, so we’re busy now. The platform goes quiet over the winter, and that’s when the toolset for the 2027 season gets built. Having a shape to the year is more useful than I expected it to be.

The thing I got most wrong is also the one I’m happiest about. I turned up braced for friction. I expected to have to earn access, argue for scope, make a case for every change. Almost none of that was there, and what resistance I did meet in the first fortnight I’d brought with me.

Two weeks isn’t long enough to conclude much. Ask me again in the winter, when the clubs go quiet and we find out what we actually do with the time.