Case study
Rebuilding an affiliate platform
I was hired to maintain a slow legacy AngularJS app. I rebuilt it from scratch in React instead, and over time it became the main way the affiliate team works.
- Role
- Frontend Developer at ComeOn! Group, team of about 14
- Period
- Apr 2022 - present
- Stack
- Links
- Private
Context
ComeOn! Group runs an affiliate tracking platform used by a few thousand people. It is data-heavy: most of the product is tables, filters and reports. When I joined, it was a legacy AngularJS application that was slow and hard to change, and my job was to keep it running.
Deciding to rebuild
Patching the old app was making every change expensive. I decided to start a new React application from scratch and move functionality over piece by piece, so the team never had to stop using the platform. The new app gradually took over, and today it is the main way users work with the platform.
The app is internal, so this write-up uses diagrams and simplified code instead of screenshots.
The table problem
The biggest mess was the tables. I inherited a pattern where every table had its own set of ten or more files, context providers were scattered through the tree, and the same sorting, filtering and pagination logic was copied again and again. There was no shared idea of how a table should behave, so the UX was inconsistent too.
Before: per table
After: per table
I built a single configuration-driven GenericTable component with the reusable filtering logic inside it. Then I migrated the existing tables one by one, about 30 of them, each in its own pull request. A typical migration PR added around 60 lines and removed around 600.
// Simplified illustration of the idea, not production code.
export const payoutsTable = defineTable({
source: api.payouts.list,
columns: [
column.date("createdAt", "Date"),
column.text("affiliate", "Affiliate"),
column.money("amount", "Amount"),
],
filters: [filter.dateRange("createdAt"), filter.search("affiliate")],
});
A new table is now a configuration file, and a fix to sorting or filtering lands in every table at once.
Working with the people who use it
I work directly with the affiliate managers. The loop is simple: ask what slows them down, design a solution, build it, get their feedback and iterate. Owning that loop end to end, from conversation to shipped feature, is a big part of why the rewrite was adopted instead of tolerated.
Engineering basics
New features ship with unit tests, and every change goes through a CI pipeline that builds and deploys automatically. Alongside the frontend work I make small backend changes when a feature needs them.
Result
- The React rewrite replaced the legacy app as the main interface.
- About 30 tables moved onto one component, each shrinking from roughly 600 lines to 60.
- New tables and filters are configuration, not new code.