Hacker News new | past | comments | ask | show | jobs | submit login
Ask HN: Who should handle UI logic?
3 points by zero_kool 25 days ago | hide | past | favorite | 5 comments
Hey everyone, I’m working through an architectural decision and need some advice from the community. The issue I’m about to describe is just one example, but the same problem manifests in multiple places in different ways. The core issue is always the same: who handles UI logic and should we make it dynamic make it responsibility of backend?

Example: We’re designing a tab component with four different statuses: applied, current, upcoming, and archived. The current design requirement is to group “current” and “upcoming” into a single tab while displaying the rest separately.

This leads to a debate:

Frontend Team’s Position: They want the backend to handle the grouping logic and send the data already grouped, like this:

``` [ { "title": "Applied & Current", "count": 7 }, { "title": "Past", "count": 3 }, { "title": "Archived", "count": 2 } ] ```

The goal is to reduce frontend redeployments, especially for minor UI changes. This is because 2/3rds of our frontend will be mobile apps (both Android and iOS), and we've had trouble getting app updates approved by the app stores in a timely manner.

Additionally, we're white-labeling the apps with small modifications (color themes, logos, etc.), and we plan to scale to 150-200 tenants over the next 2 years. With so many tenants, reducing redeployments would save us from having to push updates to multiple app origins.

Backend Team's Position: They believe grouping logic and UI decisions should be handled on the frontend, with the backend providing raw data, such as:

``` [ { "status": "applied", "count": 4 }, { "status": "current", "count": 3 }, { "status": "past", "count": 3 }, { "status": "archived", "count": 2 } ]

```

Their argument is that adding UI-specific logic to the backend increases complexity and violates separation of concerns. Backend should remain data-centric, delivering raw data, and avoid being tied to UI presentation decisions.

They also pointed out that server-driven UI could create unnecessary technical debt, especially as frontend needs evolve over time. For example, changing UI elements like tabs to something else (e.g., a scrolling view) would require backend changes, adding overhead.

Another concern is the risk of backend decisions limiting frontend flexibility, especially if other UI teams or platforms need to consume the same data differently. Changes for one frontend could affect others unnecessarily, making the system harder to maintain.

Additional Context: - Server-Driven UI: Server-driven UI has been gaining popularity as a way to solve some of these challenges. Companies like Airbnb, PhonePe, and Swiggy have implemented server-driven UIs to make large sections of their apps dynamically configurable. However, the current approach we’re discussing isn't a fully generic server-driven UI—it’s more like implementing dynamic UI behavior for some parts while leaving the rest static. - Startup Constraints: As a startup, speed and resource efficiency are critical for us. We're trying to balance agility and scalability while minimizing technical debt.

The Dilemma: Should the backend take on the responsibility of managing grouping logic and sending the frontend grouped data, or should the frontend handle all UI logic and just receive raw data from the backend?

Given the additional complexity we have with mobile apps, app store approvals, white-labeling, and scaling, I’d really appreciate your thoughts as frontend architects. How would you approach this to balance flexibility, scalability, and maintainability? Are there alternative solutions (like a Backend-for-Frontend (BFF) layer) that might work better in this situation?

Thanks in advance for any insights you can provide!




This is what gives rise to backend-for-frontend services. You have good reasons to keep the frontend as it is and the backend team as well. So there is a requirement for a middleman to provide additional services.

As to who should handle it? The argument isn't about the "backend" is it? It's the API. The API should be kept clean. The frontend doesn't have to use the public API though.


I worked on a mobile app dev team that tried to Ui logic with the backend. With many of the justifications you mentioned being justifications for doing it that way. White labelling, A/B testing, avoiding redeploying, etc.

The result was a mess, with many of the possible concerns and drawbacks you’ve cited ending up manifesting themselves. It was an unmaintainable mess that tried to re-invent the web browser wheel badly, except using json instead of HTML. Maintaining the abstraction framework became a full-time job for people already just trying to barely deliver features on time.

And with the backend people already being busy and tied up with other stuff, the mobile app developers ended up having to become impromptu full stack developers, have to code PHP on backend to complete features in addition to the code they had to write in Objective-C/Java for their native app level portion of the feature.

The backend approach was so resented and hated by the mobile app devs that the business eventually got rid of it.


Let the backend send what's convenient to them. In the frontend, create Models that transform to what's convenient to the FE. Sometimes, the FE needs two models for the same data. For example, a Table View and a Nested Card View of the same collection.

Model Example:

  const UF = { // User Fields
    id: 'user_id',
    name: 'name',
    balance: 'remaining_dollars',
    balanceFormatted: 'balanceFormatted' // @ClientSideOnly
  }

  function UserModel(data) {
    const model = Object.create(null)
    Object.assign(model, data)
    model[UF.id] ??= ''
    model[UF.id] = String(model[UF.id]) 
    model[UF.name] ??= ''
    model[UF.balance] ?? = 0
    model[UF.balanceFormatted] = toDollars(model[UF.balance])
    return model
  }
In that example:

1. You are protecting from prototype pollution. `model` doesn't have a `__proto__`

2. Initialized the fields with sane defaults. So if the backend missed that field, it doesn't crash the UI. By the same token, they are handy for prototyping while the backend is written.

3. Your views a free of formatting, and in some cases of many conditionals.

4. You don't have to worry about int ids. Not because they are often changed to GUIDs, but because when you use the ID, let's say in a checkbox, `this.value` is a string regardless. So you saved 30 minutes of debugging a silly bug.

5. Backend wants to rename a field. You just have to rename the UF, without having to look all over the app.

6. The model is easy and fast to unit test, while the testing the UI is…

7. You saved 3 meetings.

--

My personal project is data-driven and even there I pass the backend data through model constructors. One example is that in the frontend I use a Linked-List for convenience, while the backend sends and receives an Array.


Why not make the front-end configurable? So neither front-end or back-end code has to change, but the UI can re-group and place data different based on changes to config files?

It adds complexity to your stack to go this way, and often results in a complex implementation/configuration process for new customers, so I truly do not recommend it as a standard practice... but when I have worked on multi-tenant products where each tenant has unique data display requirements, it definitely reduces the churn of re-deployment to meet some one-off need.

Of course, you'd still need to decide where those config files live, but it now is a content change, not a code change, to alter the UX.


As a frontend dev with some full stack experience, I don't think this should really be a matter of "we want vs they want", but of your underlying resource constraints and UX needs (UI performance, database indexing or write performance, caching layers, app store limitations, etc.). It's not a game of hot potato, but how it impacts the overall data flow, both ingestion (from data sources) and serving (to the end user). Ideally you'd choose what's best for the project and company overall, not any particular team's microscopic preferences.

But in this particular case it doesn't seem like there's much to debate. It's like a single line of code for the frontend to map or reduce that simple JSON into whatever they want. It shouldn't require a rebuild (or how do you do any sort of dynamic data?).

If this is a common problem though, then yeah a BFF can help with the political side of things, if both groups can co-maintain it. It's really just a codified API layer. Backend sends data to it, frontend can choose how they want to present it through simple transformations.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: