Back to homeBack to the desktop
Sports technology

Cardy

A sports network in Iraq for individual visits and monthly memberships at partner venues.

Visit the Cardy website
downloads
20K

downloads

sports venues
200

sports venues

subscribers
2,000

subscribers

I joined Cardy a few days after launch as a consultant to give technical advice. Over the following year, my role grew into business, product and engineering work. I built the technical team first and rebuilt the dashboard. We introduced a new business model in the existing app before I led the Flutter rewrite, keeping the same features in the new interface. The backend came last, moving from PHP and MySQL to Bun and PostgreSQL. Along the way, I rebuilt the website and introduced new features. What interests me about Cardy is connecting sports and technology through good apps.

The app

12 screens

Landing pages

4 screens

The dashboard

6 screens

Choose a venue, arrive and scan its Cardy QR code.

Members choose a partner gym, pool, padel court or another sports venue in the app. When they arrive, they find the special Cardy QR code and scan it to check in. They can pay for individual visits with prepaid points or subscribe to a monthly membership at one venue.

The app is available in Arabic, English and Kurdish.

The dashboard brings bookings, visits and payments into one place.

Venue owners use the dashboard to manage their venue information, pricing, memberships and bookings. They can follow visits and member activity, review payments and use settlement reports. The dashboard is in Arabic, matching the language they use in their daily work.

The product was live. It was not ready.

I joined as a consultant a few days after launch. People were already using Cardy, so I had to understand what was getting in their way. The work soon grew beyond simple technical advice.

  • A DNS/CDN problem made the app unreachable on Iraqi networks. People were being told to install a VPN to use it.
  • The Laravel and MySQL backend was full of spaghetti code, making even small changes impossible.
  • There was no CI/CD and no caching. Deployments were painful, so they rarely happened.
  • Payments were cash only. Someone had to collect money from every venue.
  • The dashboard was in English, while the people using it every day spoke Arabic.
  • The business model was the biggest problem. Entry passes limited the sports, venues and pricing Cardy could support.

I built the technical team first. Over the following year, that gave us the people to rebuild the dashboard and app, introduce new features and eventually replace the backend. I still work in the code, but leading the team also means giving people enough context to own their part of the product.

Across this work, I introduced CI/CD and separate development, testing and production environments on Dokploy. Changes go through testing and review before release. Translation and configuration checks are automated, so the same issues do not depend on someone remembering to look for them every time. Monitoring and backups are part of the setup too.

I keep product requirements, technical overviews and release instructions with the work. Larger features get a review that challenges the assumptions before we ship them.

An English template was the wrong starting point for a team working in Arabic.

After building the team, I rebuilt the dashboard. The first version used a purchased React admin template. It was English only, and the home screen showed three visitor counters. Venue owners and the operations team worked in Arabic every day, so I rebuilt it from the ground up with React 19, TypeScript, TanStack, shadcn/ui and Tailwind, using a right to left layout from the start.

I added search, filters, exports and settlement reports around the work the team actually does. We use the Arabic labels in our requirements too, so the engineers and operators can discuss the same task in the same words.

Signing in
Activity overview
Managing venues
Editing a venue

Pricing and challenges in the rebuilt dashboard

2 screens

Entry passes had limited the sports, venues and prices Cardy could support, so we decided to change the business model to prepaid points and monthly memberships. Members would be able to pay for individual visits across partner venues or choose a monthly plan for one venue.

Members already knew their way around the old interface, even with its problems. From previous experience, I knew that changing the business model and the interface at the same time would ask them to learn too much at once. I brought that experience to Cardy, and we introduced the new model and its features in the familiar interface first.

Payments needed attention too. Before I joined, they were cash only. I brought the gateways behind one payment layer so the app uses the same flow regardless of the provider. The backend checks payment confirmation and repeated requests before crediting points, because a retry must not add the same points twice.

Alongside the product changes, I stabilised the inherited system and moved Cardy to hosting that worked on Iraqi networks, resolving the DNS/CDN problem that had led people to be told to install a VPN.

After introducing the new business model, I led the Flutter app rewrite. We changed the UI while keeping exactly the same features, so members could use the product they already knew in a new interface.

Only after that did we introduce new features in the rebuilt app, such as member challenges. The sequence mattered to me. Changing the model, rebuilding the UI and adding features were separate steps, each giving people one change to understand at a time.

The public site needed to catch up with the product.

The old website was a WordPress and Elementor homepage in English. I rebuilt it as a static Astro site with Arabic in Iraqi dialect as the main language, alongside English and Kurdish Sorani. It explains the visit and membership options, shows real venues on the map and sends each visitor to the right app store.

I also introduced a Cardy for Partners page to explain how Cardy works for venue owners. It covers the venue setup, dashboard and cost, with a form to join Cardy.

I organised the translations by language and added checks for missing text. The site also includes the privacy, terms and account deletion pages the app needs. A static build suited this work, and it follows the same testing and release process as the rest of Cardy.

Introducing Cardy
Explaining the visit options
Cardy Care

Cardy for Partners

1 screen

I had to migrate an awful backend and database structure.

The backend rebuild came last, after the team, dashboard and app. I moved it from PHP and MySQL to Bun and PostgreSQL, but wanted more than a change of language. Before writing the replacement, I documented the data model, migration steps, risks and a way back if the change did not go as planned. The existing app was still in use, so I rebuilt one area at a time.

I captured sanitised examples from the Laravel API and built a tool that sent the same request to both backends. It compared the response status, structure, types and side effects. That gave me a concrete way to decide whether each area was ready, including the awkward cases a rewrite can easily miss.

The data migration had its own checks. Row totals, points and balances had to reconcile before a run counted as complete. I rehearsed the migration and wrote down the release and rollback steps, so moving to the new backend was something we could review and repeat.

  1. 01

    Test the behaviour that matters

    Alongside unit tests, I used integration tests with PostgreSQL and Redis for scans, bookings and credits. Concurrent requests and repeated actions were part of those checks.

  2. 02

    Measure before tuning

    Load tests found a bottleneck in the venue detail route, which I addressed with response caching. I also accounted for members sharing a carrier IP on local mobile networks.

  3. 03

    Leave a backend people can understand

    The API, worker and scheduler share one codebase, with OpenAPI documentation generated from the code. That helps the team follow the system as it changes.

Cardy has reached 20K downloads, 200 sports venues and 2,000 subscribers. I'm proud of the work I've contributed with the team over the year, from building the team itself to rebuilding the dashboard, app and backend, and changing the model those systems support.

The work connected business, product and engineering. The entry pass model, the language of the dashboard and the way we released changes all needed attention. Previous experience helped me decide how to introduce those changes, including keeping the business model change separate from the new app UI. Connecting sports and technology through good apps meant working through all of those decisions. The backend rewrite was one part of a much larger change.

My role
Founding Engineer and Technical Lead
Period
September 2025 to present
Built with
Flutter for the mobile appAstro for the websiteReact 19 for the dashboardBunExpress 5TypeScriptPrismaPostgreSQL and PostGISRedis for caching and background workS3 and imgproxyDokploy and NixpacksInfisicalOpenObserveGitHub Actions for the appLaravel and MySQL (deprecated)
Ask about Cardy