[HN Gopher] Don't build a general purpose API to power your own ...
       ___________________________________________________________________
        
       Don't build a general purpose API to power your own front end
       (2021)
        
       Author : aabbcc1241
       Score  : 208 points
       Date   : 2023-08-20 08:39 UTC (14 hours ago)
        
 (HTM) web link (max.engineer)
 (TXT) w3m dump (max.engineer)
        
       | anymouse123456 wrote:
       | I've built both models (and more too) over decades.
       | 
       | There are lots of questions one might ask before deciding between
       | these two (or other) approaches:
       | 
       | * Where does this team want the boundary between client and
       | server in terms of user experience, server load and substantial
       | UX interaction latency?
       | 
       | * Can this frontend team independently plumb a changes all the
       | way through the database?
       | 
       | * Are backend teams always available for (or interested in) every
       | minor update?
       | 
       | * Are both halves of the application deployed on the same
       | schedule?
       | 
       | These are a handful of the first questions I'd ask before trying
       | to push either solution at this point in time, the answers would
       | likely lead to more questions.
        
       | FrustratedMonky wrote:
       | Think this is describing other frameworks that do this. Isn't
       | this how ELM works? Or ELM architecture in general?
       | 
       | This is kind of how some 'functional' web api's work.
        
       | Y-bar wrote:
       | > Imagine if you could just send it the whole "page" worth of
       | JSON. Make an endpoint for /page/a and render the whole JSON for
       | /page/a there. Do this for every page. Don't force your front-end
       | developers to send a bunch of individual requests to render a
       | complex page. Stop annoying them with contrived limitations.
       | Align yourselves.
       | 
       | Why not just send HTML as a single response at this stage?
       | Sometimes it feels like we are doing web development more complex
       | than it needs to be.
        
         | shaftoe444 wrote:
         | > Imagine if you could just send it the whole "page"
         | 
         | Could have stopped here
        
           | aatd86 wrote:
           | Maybe for separation of concerns between data and UI? The
           | browser is not going to be the only client?
        
             | philderbeast wrote:
             | you can have seperation of data and UI and still send the
             | whole page.
             | 
             | The vast majority of the time, the browswer is infact going
             | to be the only client.
             | 
             | once you reach the point where its not, then build the api
             | to suit the new client rather then trying to build one that
             | does both.
        
               | aatd86 wrote:
               | True, you could insert something in the middle, that
               | generates a page depending on the user-agent. But then it
               | requires extra SSR logic.
               | 
               | But on the other hand, you can have a iOS or Android
               | based app that depends on the same data. So the browser
               | is not the only client in general, especially nowadays, I
               | think?
        
               | regularfry wrote:
               | That's the crux of the question. The BFF approach says
               | that you _remove_ logic from the client and put it in a
               | server-side component. Not that you add extra logic. Then
               | you _might_ find that you need to copy that server-side
               | component sideways for a new client, if the view layer in
               | that client is sufficiently different to what you already
               | have. The browser can be the only client of its BFF API;
               | the mobile apps can either speak to the same API or have
               | their own.
               | 
               | Dramatically more important than any theoretical,
               | abstract consideration in deciding whether this can work
               | is what your teams look like. The client team should
               | almost certainly own the BFF API, which has implications
               | for skillsets and maturity.
        
               | aatd86 wrote:
               | That's only for a react type of application if I'm not
               | mistaken?
               | 
               | If so, that doesn't handle the general case (native apps
               | for instance)
        
             | nonethewiser wrote:
             | Well now you're building a general purpose API
        
               | aatd86 wrote:
               | I think there is a middle-ground concern here: avoiding
               | request waterfalls.
        
             | CharlieDigital wrote:
             | That's what the database is, isn't it? The separation layer
             | between the raw data and how it's projected into some
             | interface (user or otherwise).
        
               | aatd86 wrote:
               | Yes in a way. There are a bit more layers in-between.
               | 
               | In fact, you can see it as 2 decoupled kinds of database:
               | 
               | - the storage database
               | 
               | - the working in-memory UI database that holds the data
               | represented (e.g. on your screen (GUI)).
               | 
               | The goal in general is to modify the data contained in
               | this UI database and then to push the changes to storage.
        
         | [deleted]
        
         | croes wrote:
         | I think it's about API as such and not about how to serve the
         | webpage.
         | 
         | No matter of JSON or HTML don't built a general purpose API if
         | it's only your frontend.
        
         | JaggerJo wrote:
         | This breaks once you need to update parts of the page without
         | reloading everything.
        
           | marginalia_nu wrote:
           | In that case you can just parse the DOM clientside and insert
           | it into the page.
        
           | loloquwowndueo wrote:
           | You can still return html partials from your endpoints and
           | use htmx to swap content without a full reload :)
        
             | JaggerJo wrote:
             | yes, but then it's not one request per page
        
               | loloquwowndueo wrote:
               | Only if there's an update - htmx will encourage you to
               | render full html pages but still gives you the ability to
               | do in-place updates which is what most folks think a JS
               | front end with a json Api backend and client side
               | rendering is needed for.
        
               | halfcat wrote:
               | HTMX can swap multiple DOM elements from a single HTTP
               | response
               | 
               | https://htmx.org/extensions/multi-swap/
        
           | Y-bar wrote:
           | JS can update the DOM dynamically.
           | 
           | Nothing prevents the main response from being served as
           | regular HTML and subsequent XHR request for some parts of a
           | page being JSON or some such data format. In fact I bet that
           | sending server-side rendered HTML is faster than sending a
           | full structured page as JSON which has to be decoded, parsed,
           | and then converted to HTML.
        
             | timeon wrote:
             | Reminds me early AYAX days.
        
             | holoduke wrote:
             | I run a popular app (native ios and android) and a web
             | version. I find having A single json serving api much
             | easier to maintain. The frontends are isolated projects.
             | The backend is just a simple layer with static data served
             | as json. If you would have static html it means you need to
             | update all static files whenever a ui change is needed.
             | Makes it overly complicated. Caching becomes also a
             | challenge and the so does the performance. Currently just
             | running a few Hetzner instances to serve 50k requests per
             | second. That would be really hard with a server side
             | rendered html.
        
               | halfcat wrote:
               | Do you build each interface with different tools (e.g.
               | Swift, Java, and React), or one of the unifying tools
               | (Flutter, React Native, etc)?
        
               | Y-bar wrote:
               | > If you would have static html it means you need to
               | update all static files whenever a ui change is needed.
               | Makes it overly complicated
               | 
               | We do use a templating engine and separate CSS files, so
               | no, not at all, all static files does not need updating
               | on every change.
               | 
               | > Caching becomes also a challenge and the so does the
               | performance
               | 
               | Not at all, not even on black fridays.
               | 
               | > That would be really hard with a server side rendered
               | html.
               | 
               | Why do you pose that hypothetical when our real-world
               | experience is easy?
        
             | robertoandred wrote:
             | Then you're stuck with two kinds of templating.
        
           | runeks wrote:
           | The is exactly what HTMX does and it works: allow returning a
           | HTML response and statically annotating a part of the DOM to
           | be replaced with that.
           | 
           | Granted, this requires JavaScript on the front end, but it's
           | a framework that can be shared between different websites, so
           | you're not writing any custom JavaScript for your site.
        
           | vidarh wrote:
           | Around 2005 was the first time I "accelerated" a website by
           | requesting the whole page in the background and swapping out
           | what had changed.
           | 
           | We eventually trimmed what was returned a bit, but just
           | getting rid of the page transition was 90% of the work.
        
           | strictfp wrote:
           | That's true. But that's only really a concert if you're
           | building an SPA. If you're not, having multiple pages is
           | generally faster than running some js framework to reload
           | parts of the page. Plus that you get the benefit of every
           | state combination having it's own URL. You don't need to
           | write any custom state reconstruction code.
           | 
           | This was the original design of REST as applied to the web.
           | It was explicitly designed in such a way that it was
           | forbidden to reload parts of the page. This makes it so that
           | every state has it's own URL and you therefore can link to
           | every state. Deep linking if you wish, for all of the web.
        
         | madsbuch wrote:
         | This is exactly how next.js works. But even more importantly:
         | Why not use GraphQl in this situation? This is exactly what it
         | excels at:
         | 
         | 1. The backend can be entity centric, like it does best 2. The
         | frontend can request a page worth of data from diverse entities
         | in a single go.
        
         | SoftTalker wrote:
         | Yeah, this goes back a couple of decades where "page a" was
         | just "page-a.asp" or "page-a.php" and you did everything to do
         | with that page in that file. Simple, and you could mostly make
         | changes to page a without worrying that you'd break other
         | pages.
         | 
         | Need page b? Copy page-a.asp to page-b.asp, gut the page-a
         | logic, and put in the page-b logic.
         | 
         | Before you get too nostalgic for these simple days, do we
         | rememember why we stopped developing web pages that way?
        
           | Muromec wrote:
           | Because you can't have a lot of itneractivity with a nice
           | responsive UI like this if your network has high latency and
           | low bandwidth. So we pushed a lot of logic to the browser.
           | Now it turns out it doesn't scale well, so maybe we should go
           | back to copying page a to page b and calling it a day, same
           | way we came back to static linking once disk space stopped
           | being limiting factor.
        
           | slotrans wrote:
           | > ...do we rememember why we stopped developing web pages
           | that way?
           | 
           | Because we needed an API for our mobile apps, and once we had
           | that, SPAs seemed convenient.
           | 
           | It was definitely, absolutely NOT because the page-centric
           | way of building sites didn't work (it does), or because SPAs
           | are better (they aren't).
        
             | oceanplexian wrote:
             | I'm a systems engineer and SPA's are a superior
             | architecture to deal with from a delivery POV. It is very
             | difficult to cache a dynamic web app with a CDN. There are
             | ways, like SSI, managing variants, Purging, and so on, but
             | a huge pain. And if you don't have a sophisticated CDN and
             | are using something like Cloudfront, forget about all those
             | fancy features.
             | 
             | SPA? I can serve the whole thing with static files and
             | remove 90% of the traffic from my web server. The API can
             | be served from a different path from the static files. API
             | requests are super tiny and more tolerant to fluctuating
             | network conditions, and you can hide a lot of that with
             | Javascript.
        
               | TheCleric wrote:
               | Exactly. Even non-SPA frameworks (such as NextJS with
               | static builds) mean you can compile all of your frontend
               | code to S3 (where it's a negligible cost) and only pay
               | for the API instances.
        
               | ThatPlayer wrote:
               | I have a hobby project that's very static: a website for
               | viewing webscraped snippets of writing from another site.
               | I hosted it on Github Pages. I didn't want to use a
               | static site generator which would've generated easily
               | 10,000 files and with all the duplicated code would have
               | put me above GitHub's 1GB limit for Github Pages.
               | Similarly Cloudflare Pages has a 20,000 file limit.
               | 
               | So instead I combined it into various JSON files. Now I
               | have a SPA downloading the JSON as necessary, and don't
               | need any API/backend/database. I'm considering moving to
               | sqlite now there are official WASM builds.
        
         | fastboy wrote:
         | [dead]
        
         | wiseowise wrote:
         | Got to pump CV with frameworks you know? Promotions don't write
         | themselves. Bonus point: job security. And when you leave who
         | cares what poor shmuck will have to support it?
        
         | renegade-otter wrote:
         | How did we get to the point where simple and effective server-
         | side pages are either unknown as a way of doing things or are
         | considered to be a technical heresy?
         | 
         | Younger developers scoff at us fossils and the olden ways, but
         | this is exactly how this ignorance of classic, tried-and-true,
         | performant patterns results in atrocious complexity and
         | performance, only because "this is how things are done".
         | 
         | It HAS to be a BFF, it HAS to be 15 different microservices and
         | 20 different AWS toys, right? There is no other way? Are you
         | sure?
         | 
         | It seems like we are talking about the whole industry, but it's
         | largely he Node ecosystem in my experience (which is
         | effectively - the industry). It's not like there is not Rails
         | development being done out there, with nothing but a trusty
         | Postgres database.
         | 
         | Ironically, our existing architecture patterns are beginning to
         | resemble J2EE - a bulky, slow, expensive, boiler-plate-laden
         | process where a simple site costs one million dollars and
         | performs like shit.
        
           | rewmie wrote:
           | > How did we get to the point where simple and effective
           | server-side pages are either unknown as a way of doing things
           | or are considered to be a technical heresy?
           | 
           | We are not at that point nor we were ever at that point, or
           | close to it.
           | 
           | Server-side rendering has been a hot topic in JavaScript
           | framework circles for over a decade, and React famously
           | solved that problem so well that it is now a standard, basic
           | technique.
           | 
           | Also, just because you throw the same buzzword around that
           | does not mean the problem stayed the same. Reassembling a
           | javascript-generated DOM with a coherent state is not the
           | same as sending a HTML document down the wire. And you know
           | why people started assembling DOMs with JavaScript? Because
           | sending HTML documents down the wire was too slow and did not
           | allowed for any control over aspects that dictate perceived
           | performance.
        
           | LapsangGuzzler wrote:
           | Because JavaScript rules web dev and the JS community has
           | pushed so many mainstream ideas that have turned out to be
           | duds. It's a major echo chamber due to its size relative to
           | other web dev communities.
           | 
           | I also partly blame the careerist obsession around always
           | learning new technology, because it's becoming obvious that a
           | lot of the "new stuff" over the last decade created more
           | problems than solutions. Don't get me wrong, learning is an
           | important part of the job, but we've created a culture of
           | constantly pushing new technology to pad resumes and feed our
           | insecurities around irrelevance instead of solving problems.
        
             | jwells89 wrote:
             | Hype, which the web/JS community seems particularly
             | vulnerable to, also plays a big part. Yes proven tech is
             | safe and reliable, but choosing it is so much less fun than
             | getting swept away by the tide of whatever the newest
             | "revolution" is. Don't you want to be part of the wave?
        
             | bheadmaster wrote:
             | It seems to me that the more people use <thing>, the less
             | evidence of quality of <thing> is required by the people
             | using <thing> - everyone just assumes everyone else knows
             | what they're doing.
             | 
             | It becomes something akin to a religion - after all, 2
             | billion Christians can't be wrong, can they?
        
               | nonethewiser wrote:
               | Can you pick a less antagonistic example?
        
               | brightlancer wrote:
               | The adage I learned decades ago was "a billion Chinese
               | can't be wrong".
               | 
               | If PP had used that, would it have been antagonistic?
               | Racist?
        
               | bheadmaster wrote:
               | Would you prefer I used Judaism instead? Or Islam?
               | 
               | Or do you consider my point about network effect in tech
               | stacks being similar to religious beliefs to be
               | antagonistic by itself?
        
               | toyg wrote:
               | Eat shit - billions of flies cannot be wrong. (cit.)
               | 
               | More seriously: once a bit of tech becomes mainstream, it
               | becomes politically easier to use it. Your manager has
               | not heard of <cool tech>, but he did read about React in
               | some business magazine. So when the choice is between
               | React and bheadmaster's Funky Funkness Framework, he'll
               | go with React.
        
               | ricardobayes wrote:
               | No one ever got fired for choosing React
        
               | ncallaway wrote:
               | > everyone just assumes everyone else knows what they're
               | doing.
               | 
               | It's not just that. There are practical reasons to choose
               | the bandwagon, even if you know it's not the technically
               | optimal approach.
               | 
               | If you're planning on hiring junior and mid level
               | engineers, for example, it's a great help if they already
               | know the technologies involved. Your hiring pool for
               | React is a lot bigger than for a more obscure tool.
               | Additionally, the popular tools also tend to be stable
               | and long lasting, with good support.
               | 
               | So, there are compelling business reasons to choose
               | what's popular, even if you aren't making assumptions
               | about the technical quality just because its popular.
        
           | ecf wrote:
           | It's because you fossils keep thinking server-side rendering
           | is the right call for everything and won't consider other
           | possibilities.
        
           | oefrha wrote:
           | If you want to build a moderately complex interactive
           | experience that doesn't suffer from roundtrip latency on
           | every single interaction, you need to recreate the
           | interactive parts of DOM in JavaScript anyway (ignore wasm),
           | else you need to do imperative updates which quickly become a
           | nightmare. jQuery-oriented development is a classic for sure,
           | doesn't mean people want to go back to it.
        
           | evantbyrne wrote:
           | The current SPA paradigm was adopted to solve a number issues
           | that engineering teams were facing. Your sentiment is one I'm
           | seeing a lot more as of recently, which leads me to believe
           | we're approaching the end of the current web development
           | paradigm. There's too much time wasted writing _glue_ when
           | developing SPAs: database queries, back-end controllers, data
           | serialization, network requests, front-end state, shadow dom,
           | etc. Lots of frameworks coming out that essentially remove
           | the need to write glue code. I expect this trend to continue
           | until we reach the point where you are mostly just coding a
           | few things: schema, non-generalizable business logic, and
           | presentation.
        
             | martinald wrote:
             | Blazor Server, while definitely not the right thing for all
             | applications, is the best solution I've found to this.
             | 
             | You write all the code in one language (C#), and it streams
             | the changes to the clientside as needed automatically. It
             | means you can call the database in your 'frontend' HTML
             | layouts directly and gets rid of all the glue code. You
             | have no serialization problems because you are using the
             | same classes everywhere, and the component structure keeps
             | things very clean.
             | 
             | I would say I am about 5x more productive in Blazor Server
             | than any other frontend technology. You don't need to write
             | APIs at all. It's just like writing static server side
             | rendered pages but you can do dynamic stuff. It is honestly
             | like magic.
             | 
             | It does come with some huge downsides though, in that it
             | needs to keep a websocket open to stream all the DOM
             | changes from the server, and this also has
             | memory/performance issues on the server (needs to keep
             | state on the server all the time). Which basically rules it
             | out of anything that needs to work over intermittent
             | connections (mobile), and very high scale stuff (probably
             | could be done with enough server RAM, but it's not the
             | right tool for that).
             | 
             | However, it's perfect for boring line of business
             | applications that will only be accessed on solid internet
             | connection, which is many of them.
             | 
             | There is also Blazor Webassembly which removes the
             | websocket part, and lets you code frontend and backend in
             | C# still, sharing a lot of classes, though you do need some
             | glue code to connect the database. I've heard people are
             | having good results with gRPC for that; but haven't looked
             | into it much (blazor server works fine for most apps IMO).
        
               | troupe wrote:
               | Is this kind of what Vaadin does?
        
               | martinald wrote:
               | Hadn't actually heard of that. Might be similarish but
               | Blazor uses standard html/css/JS and just sends DOM diffs
               | down the wire. Don't think at first look Vaadin works in
               | the same way.
        
               | troupe wrote:
               | Ah ok. So the server keeps track of what the client
               | should look like and just keeps it up to date?
               | 
               | If so that sounds like a very nice model that would make
               | it a lot easier to get back to just using simple HTML and
               | delegate the complexity to the framework or server
               | process. Are there other projects beside Blazor that use
               | this type of approach?
        
               | evantbyrne wrote:
               | Not super famliar with blazor, but something like this
               | sounds like what I would consider the halfway point to
               | the next paradigm. I think you have to go further in
               | simplification of the back-end as well.
        
           | hot_gril wrote:
           | Not sure what a BFF is, but having separate frontend and
           | backend development doesn't mean you have 20 microservices.
        
             | yu3zhou4 wrote:
             | I think BFF might stand for Backend For Frontend in this
             | context
        
               | hot_gril wrote:
               | "A BFF layer consists of multiple backends developed to
               | address the needs of respective frontend frameworks, like
               | desktop, browser, and native-mobile apps."
               | 
               | Ok. Yeah that's only for huge scale things.
        
               | Hel5inki wrote:
               | I don't find that to be an accurate representation of
               | BFF. I've used BFF with a browser FE to simply weave
               | several microservice endpoints into a tailor-made api for
               | the frontend. This reduces the burden on the
               | microservices by removing the need to make many endpoints
               | for clients and helps reduce network calls on the FE
        
               | sarchertech wrote:
               | Most of the time time BFF just means that instead of
               | having the frontend call endpoints A, B, and C. It calls
               | a single endpoint D, which calls A, B, and C and handles
               | aggregating and transforming the data into the specific
               | form the frontend needs.
        
               | tcoff91 wrote:
               | A BFF is just an API gateway that is tailored to a single
               | frontend. It's especially helpful if the frontend is a
               | native application as opposed to a web application, hence
               | why it was a pattern championed by Netflix. If you have
               | some native client out there and you can't guarantee that
               | the user will update it, it's helpful for it to only talk
               | to a single service so in case you want to evolve your
               | backend architecture, you can update the BFF
               | implementation and the existing native app won't be
               | broken by your backend changes.
               | 
               | Having a native app out there in the wild on customer
               | computers that is coupled to a bunch of different
               | microservices is hell for when you want to change your
               | backend without breaking your customers' experience and
               | forcing them to update.
        
           | TeMPOraL wrote:
           | I think it's the difference between generations of people for
           | whom JS was an extra thing to enrich HTML documents, vs.
           | younger generations that see HTML as merely a rendering
           | target for JS.
        
           | thrashh wrote:
           | It's because if you want to continue getting a job, you want
           | to use what other people are using.
           | 
           | Using most static page frameworks is like using ColdFusion
           | for your career advancement.
        
             | godzillabrennus wrote:
             | We have a boot strapped and profitable app with thousands
             | of customers written in Django that has been operating fine
             | since 2009 with new entrants raising and spending millions
             | to build fancy BFF/Micro Service solutions, hiring sales
             | people, losing money for years, only to publicly state they
             | have finally gotten to 300 customers.
             | 
             | Job security is relative.
        
           | kmstout wrote:
           | I'm torn. On the one hand, there are many websites I hate
           | interacting with because they are unnecessarily structured as
           | JS clients exchanging data with a remote server via a network
           | link. On the other hand, it's easier for me to develop
           | libraries and CLI clients of my own, these days getting quite
           | far with Firefox dev tools' network view and "copy as curl,"
           | and only occasionally having to actually read the code in
           | those JS clients. In the old days, I would have to resort to
           | some ugly and comparatively brittle page scraping.
           | 
           | This new world sucks for the interactive user in a browser
           | (which is me often enough), but it's great for the guy who
           | wants to treat a website as just a remote provider of some
           | kind of data or service (also me often enough).
        
           | nonethewiser wrote:
           | > How did we get to the point where simple and effective
           | server-side pages are either unknown as a way of doing things
           | or are considered to be a technical heresy?
           | 
           | Demand for interactivity. A real demand - that's why desktop
           | apps are now web apps.
           | 
           | It can be over applied, sure, but there are great reasons not
           | to serve html templates. The trend is not some massive
           | incompetence.
        
             | sarchertech wrote:
             | Incompetence is the wrong word, but in an industry that
             | grows so fast that 3 years of experience is considered
             | senior, many people aren't even aware that the old ways are
             | an option.
             | 
             | In my experience, the percentage of large react sites where
             | someone sat down and seriously considered using old
             | fashioned server side rendering, but decided on React
             | because the site actually required a huge amount of
             | interactivity is close to zero.
             | 
             | Every React site I've ever been involved with in in the
             | last say 7 years was using React because "that's the way
             | it's done", and anything else was just a post hoc
             | justification.
        
               | ethbr1 wrote:
               | There's also an interactivity _requirement_ (as in, this
               | is impossible without interactivity) and an interactivity
               | _desire_ (as in, UX folks want an interactive feature).
               | 
               | So many websites now pretend they're in the former
               | category, but would work just fine if they implemented a
               | less-interactive form. That's how it was done in the old
               | days! "No, you can't have that. Here's the best we can
               | do." "Oh, that's fine."
               | 
               | But I expect more of what's driving complicated
               | backend/frontend split design these days is shipping the
               | org chart (in companies large enough to have frontend and
               | backend teams) and technology-by-consultant (where the
               | right technology is whatever you can get a consultant
               | in).
        
         | barrkel wrote:
         | Because you want to paginate. Update the page piecemeal based
         | on an event from another user. Because you want to use the same
         | data on multiple pages, and want to write the authorization and
         | filtering logic once.
        
         | Muromec wrote:
         | >Why not just send HTML as a single response at this stage?
         | 
         | Is it time to discover memcache again? I think it's about time.
        
         | tylercrompton wrote:
         | Something about injecting HTML from an API, even from a
         | controlled server, feels wrong.
        
           | prmph wrote:
           | But that's the point: its not an API, it's just an app web
           | server.
           | 
           | There's nothing wrong with a web server serving HTML; that's
           | their whole purpose.
        
         | littlecranky67 wrote:
         | Feels like the author misses the point of an SPA. If you have
         | website where every "view" is a /page/a etc., SPA might not be
         | the best choice. But in an SPA i can be dynamic, and trigger
         | data retrieval/sending without route changes.
         | 
         | A very basic example is if I have a checkbox that allows the
         | user to subscribe to push notifications. On click I sent a xhr
         | request to the backend POST `/subscribe/1234` which registers
         | the subscription. Next time I'll check `/subscriptions` or
         | similar to see if the checbbox is in "checked" state (i.e. we
         | are subscribed). This is basic functionality which requires a
         | concise REST/JSON API, and has nothing todo with your
         | page/route layout a la /page/a, /page/b etc.
        
           | Falmarri wrote:
           | Having form elements automatically update the back end is
           | extremely annoying UI imo. There's usually no indication that
           | it's actually doing that, and if there is I generally don't
           | trust it.
        
           | hakunin wrote:
           | Author here.
           | 
           | We do this for SPA. The POST can be supported just like you
           | explained. Then you can either reload the "page" to see that
           | the checkbox is checked, because backend will include that as
           | part of the page, or (as an optimization) reload just that
           | checkbox if you created a specialized resource for it. The
           | entire page is still there for you to fetch upon transitions.
           | 
           | Among pages, you will still need a few individualized
           | resources sprinkled around for
           | optimizations/reloads/fragment-paginations. The difference
           | between that and a complete API is that they will be entirely
           | design driven. If a table needs paginating, and is built with
           | data from multiple resources, you will not provide 2
           | resources, and expect front-end to paginate and glue them
           | together. Instead, you provide a complete paginated resource
           | for this table, where data is ready to be displayed as-is.
        
             | littlecranky67 wrote:
             | That us exactly how stuff worked around 2005. And no, you
             | should not do a full form post just to toggle a checkbox.
        
               | yakshaving_jgt wrote:
               | Why not?
        
               | valenterry wrote:
               | As a user, I can think if a couple of reason immediately:
               | 
               | - I don't like page (re)loads. They are usually slower
               | and more likely to fail, compared to a lightweight
               | request. Especially in scenarios with a bad connection
               | 
               | - If they fail, it's harder to retry, I see a connection
               | timeout page. With a SPA I see an error message,
               | potentially with a retry button. Or even better: the SPA
               | retries for me a few times.
               | 
               | - I can continue to see all the rest of the page while
               | the action is running
               | 
               | - I can potentially start other actions in parallel
               | 
               | - I prefer to not lose any progress of things on the
               | side, e.g. text-boxes where I already entered/changed
               | some text
               | 
               | - It's easier to inspect what goes wrong by looking at
               | the network tab. Okay, most users don't do that, but for
               | me it's still a pro
               | 
               | There are also advantages, but I think nowadays the cons
               | outweight those for me.
        
               | yakshaving_jgt wrote:
               | I'm convinced this is HN-themed satire.
        
       | jaza wrote:
       | Gotta say I disagree with this idea. RESTful APIs have become the
       | norm for a reason, and in my opinion it's dangerous and damaging
       | to suggest abandoning them for a whole swathe of back-ends.
       | 
       | Re: YAGNI. I worked on a product where, about 10 years ago, they
       | decided to build proper APIs (for the first time), mainly to
       | power their own front-end, but they also told the paying clients
       | that they were welcome to use them. Didn't take some clients long
       | to start using and loving those APIs. (Granted, they were
       | enterprise clients, with their own significant dev resources,
       | that's not the case for all software.)
       | 
       | Re: front-end doesn't really have freedom. Yes it does! If one
       | day page A needs a list of X, and there's already a nice generic
       | API endpoint to list X, then only a front-end code change is
       | needed.
        
         | sdflhasjd wrote:
         | > RESTful APIs have become the norm for a reason
         | 
         | What would you say those reasons are though? I think they
         | mostly boil down to cost.
         | 
         | I agree with the article, but mostly for a reason the article
         | didn't press on: performance and responsiveness. Making loads
         | of small requests sucks, and on a mobile, it sucks times ten.
         | HTTP/2 and whatnot have improved things but when you have even
         | a small dependency tree of data, you can't avoid the network
         | latency and it can quickly add up to a second or more of
         | unresponsiveness.
         | 
         | Obviously this doesn't apply (or matter) in some circumstances,
         | but in many applications I think it's worth the extra cost.
        
           | timeon wrote:
           | > and on a mobile, it sucks times ten
           | 
           | People often like to design for mobile devices but not for
           | mobile connections.
        
         | Attummm wrote:
         | The other added benefit is sharing the data with other teams,
         | and of companies.
         | 
         | Everything has the same flow. And if a custom api call is
         | needed for a particular frontend page, it can always be made.
         | But won't be the norm.
        
         | weego wrote:
         | No, what we have is everything trending towards a monoculture
         | where every solution is a minor iteration or flavour change to
         | systems that solved problems for companies at scale such as
         | meta/google.
         | 
         | We regularly see developers talking about optimising js loops,
         | dom updates etc in products that are little more than blogs
         | with a few interactive elements.
         | 
         | Most of us work on things that will get ripped out and redone
         | within a couple of years, yet dev culture tells us we should be
         | focusing on developing for every possible future with reuse and
         | scale in mind, and that's unfortunately false.
        
           | marginalia_nu wrote:
           | > [pointless changes] in products that are little more than
           | blogs with a few interactive elements.
           | 
           | I wonder if a lot of this isn't busy work to justify having
           | engineers on staff.
           | 
           | You need engineers on staff to make changes when that is
           | necessary, but you don't typically need to constantly be make
           | such changes. At the same time the engineers can't be seen
           | doing nothing, so this type of work is invented.
        
             | zelphirkalt wrote:
             | You are saying engineers should build software, that
             | doesn't frequently require changes to fit some new use
             | case? Outrageous. Then we would have to do proper
             | engineering and make things flexible, anticipating
             | potential use-cases. We would have to heed advice written
             | in books such as PAIP (or more recently "Software Design
             | for Flexibility"). Can we be expected to know literature of
             | our own field?
        
           | davidmurdoch wrote:
           | I agree with everything but
           | 
           | > We regularly see developers talking about optimising js
           | loops, dom updates etc in products that are little more than
           | blogs with a few interactive elements.
           | 
           | In which I see the opposite. Developers don't optimize
           | because "DevEx" is a feature of a codebase, but performance
           | is treated as an afterthought.
        
           | szundi wrote:
           | At my company most code we did in 20 years ago is there and
           | working. Providing b2b service for 5k customers.
           | 
           | Thanks god it's Java.
           | 
           | Our competitors are lost trying to tinker with the old PHP or
           | redoing everything with cutting edge node/js dead end techs.
        
             | whynotminot wrote:
             | You think node js is dead end tech?
        
               | halfcat wrote:
               | I interpreted the statement as, "dead end tech, which
               | happens to use node/js".
        
         | tootie wrote:
         | There's a well-established answer to this that I've done for
         | years that satisfies both and it's the BFF pattern. The crux of
         | which is an orchestration tier. A simple pass-through API
         | gateway which can interface with all your thoughtfully-
         | designed, single-purpose APIs, extract and transform one or
         | more payloads and serve up a single payload that maps one-to-
         | one with a frontend. I've deployed this architecture for years
         | on some large-scale sites. It works very nicely. Bonus is that
         | you can manipulate and even swap out entire backend pieces
         | without worrying about your frontend.
        
           | NovaX wrote:
           | qlio [1] was a really elegant implementation of this pattern
           | before it was named and popularized. That provided a nice
           | decoupling of the FE/BE teams by allowing very quick
           | iterations, with an early means to compose apis to simplify
           | the marshalling.
           | 
           | [1]: https://tech.ebayinc.com/engineering/announcing-ql-io
        
         | gorjusborg wrote:
         | I also disagree.
         | 
         | I agree that pretending you have multiple clients sets up a
         | more difficult bar to meet. I agree that bar might be overkill
         | for some projects.
         | 
         | The idea that it is overkill for all projects is a leap I can't
         | follow. Optimizing for greenfield development speed is
         | something inexperienced devs often do, and that's what this
         | feels like.
        
       | [deleted]
        
       | jgilias wrote:
       | The problem is not building a general purpose API, the problem is
       | over thinking it. There's a sweet spot where you build the API
       | just slightly more flexible than your FE needs at the time, yet
       | without wasting time on making it fit 'all possible future use
       | cases'.
       | 
       | Then you can later on whip up a mobile app if needed, let the
       | clients use it, whatever. And evolve it accordingly.
        
         | runeks wrote:
         | I disagree. Trying to generalize a single implementation into
         | an interface is always problematic. And that's exactly what
         | inserting an API between the FE and BE is if your only UI is a
         | web page.
         | 
         | If, later on, you want a mobile app, then an API can easily be
         | deduced from your current, working UI, instead of trying to
         | imagine what the UIs of your web FE and mobile app have in
         | common.
        
       | Spiwux wrote:
       | Don't think I could disagree any harder. Requirements change.
       | Business needs change. You want your FE to be able to evolve
       | independently without having to wait for the BE to implement the
       | precise logic you need.
        
         | another-dave wrote:
         | As well as your FE team forced to wait on BE changes for new
         | features, you've also created busywork for the BE team anytime
         | there's a FE refactor/restructure to boot.
        
           | bramblerose wrote:
           | An organisation that separates frontend and backend teams
           | will naturally converge to an architecture where the
           | collaboration between frontend and backend is minimized
           | (i.e., a generic REST API) -- Conway's law.
           | 
           | This doesn't mean that an actual cross-functional team that
           | contains both frontend and backend developers can't use the
           | proposed single-purpose API to run circles around the split
           | team.
        
             | another-dave wrote:
             | Regardless of cross-functional teams, I think having to
             | make changes at an API level at the backend for UI changes
             | will negate a lot of the benefit.
             | 
             | For clarity, I don't think you need to treat your own
             | front-end like an external consumer & think it's fine to
             | have bespoke endpoints as needed.
             | 
             | What I'm skeptical of is the author's suggestion that a
             | backend endpoint brings back presentational info like
             | "leftBoxTitle".
        
       | hakunin wrote:
       | One extra thing I have confirmed after writing this article: it's
       | usually a bad idea to reuse back-end data in multiple places on
       | the front-end.
       | 
       | If you think about functions or object constructors in general,
       | it kind of makes sense. One of the most important architectural
       | practices I've ever discovered is: don't pass in the parameters
       | that you have, pass in the parameters that the function needs. So
       | if you have companyName, and you are constructing a page that has
       | a title, you shouldn't pass it companyName: companyName, you
       | should pass it pageTitle: companyName (parameter name: parameter
       | value). It's crucial that the parameter is named after what is
       | needed, not what you have. This is kind of the essence of what
       | the article is suggesting.
       | 
       | If your front-end is reusing a lot of fields from back-end, it's
       | likely that you're passing it what you have in your
       | database/resources, and not what it needs -- fields for
       | constructing the UI, configuring the views. Moreover, I rarely
       | see front-end going through the exercise of defining exactly what
       | they need. The article encourages more of that.
       | 
       | Once the front-end starts reusing the generic back-end fields
       | everywhere, you lose track of your use-cases. Everything you ship
       | from the back-end becomes potentially important for mysterious
       | reasons that not even front-end can easily understand anymore.
       | Front-end already built complex dependency trees based on these
       | generic fields. If you actually untangle these trees, it might
       | turn out that your front-end can only exist in 5 different
       | "modes", but you can no longer see that in the tangled mess. You
       | can no longer streamline and optimize these 5 configurations.
       | 
       | So to summarize: pass what is needed, not what you have is a good
       | general architectural rule that's also applicable between back-
       | end and front-end.
        
         | kdazzle wrote:
         | I don't know about this. I do think people tend to prematurely
         | optimize by over-generalizing their APIs instead of building
         | what they need. But this seems like it swings too far the other
         | way.
        
         | appplication wrote:
         | This is really timely for me, thank you. I'm ignorant when it
         | comes to web dev best practices (data engineering background
         | mostly) but find myself suddenly having created a couple small
         | backends for some of our internal (non-customer facing)
         | tooling, and running into basically all of your questions.
         | 
         | One of these I struggled with right away was "how do I ensure
         | the front end and back end have consistent data sourcing and
         | validation", e.g. for various forms, dropdown selectors, etc. I
         | have found surprisingly few resources for general patterns
         | here. So I did your anti-pattern of having an endpoint for each
         | little thing (e.g. /api/v1/country-codes or something like
         | that).
         | 
         | This has felt... ok at best. One challenge, perhaps entirely
         | imagined, is coherent namespacing. Part of the backend is also
         | a public (internally) API. We auto-generate all our docs with
         | swagger, and I was finding that the few meaningful endpoints I
         | had were diluted by the mess of individual endpoints for the
         | frontend. So I threw these under /api/v1/config. Feels like a
         | junk drawer but at least it cleaned things up.
         | 
         | I like the idea you're proposing here for having one API per
         | page, I think it makes a lot of sense. It also eliminates the
         | "I guess I'll add another endpoint" and changed it to "let me
         | add another field". Feels more granular and scoped. I will be
         | giving this a try!
        
           | nonethewiser wrote:
           | I don't think what he's suggesting is common whatsoever. Take
           | that however you want.
        
             | appplication wrote:
             | Because I'm otherwise uninformed to pros/cons here and
             | don't have the benefit of experience to fall back on, what
             | are the alternative suggestions for best practices for
             | these types of problems? For context, my app is a single
             | backend dev (me), separate frontend team that tasks on as
             | needed. Backend dev resources are unlikely to expand beyond
             | me for the 2-year horizon.
             | 
             | I also have all context on vision for direction of the web
             | app, and field all user feedback and requests. Front end
             | team has no context on user needs, and does not keep any
             | roadmap for the app. So it seems like the above recommended
             | pattern could make sense in that I could drive more front
             | end work from the backseat, so to speak.
        
               | theptip wrote:
               | I think the standard evolution of an API is:
               | 
               | 1) basic CRUD API for your objects (eg DRF generated
               | model-API in Django). Really easy to build. Client is
               | assumed to have some magic knowledge (eg which country
               | code style you use). Ideally as much of the smarts as
               | possible is server-side, but early on you can compromise
               | on this.
               | 
               | 2a) for reads, notice you need nesting / joins, add
               | nested fields. Maybe notice these joins are slow and make
               | them optional; build some expanded=true or
               | with_subobject=true type query params.
               | 
               | 2b) for writes, notice that CRUD is getting hard to
               | maintain as frontend can create n^2 possible states for n
               | fields, and backend validation needs to consider all
               | other fields for each update. Move complex state
               | transitions to mutation/action/verb endpoints instead of
               | PUT(any fields). Add your first "status" fields.
               | 
               | This gets you quite far, likely to be fine for 2 years
               | and beyond. After this there are lots of options
               | depending on needs, and overhead associated with more
               | layers/abstraction;
               | 
               | 3) use something structured like GraphQL, or just
               | refactor the API to do away with directly updating
               | objects. Maybe lean into Finite State Machines if you
               | have a small number of objects with complex transitions,
               | endpoints trigger those parameterized transitions.
               | 
               | Another option to consider is a server-side rendered
               | framework with client-side hooks like Django+HTMX, Rails
               | Hotwire, Elixir Livewire, where the frontend devs are
               | working on styling, design, templates, and most/all the
               | actual app logic is backend code. This gets you
               | surprisingly far these days. If you are the one defining
               | all the features, you'll iterate quicker in this mode.
        
               | appplication wrote:
               | Thanks for the thorough comment, I appreciate your
               | insights. I was thinking about something like htmx since
               | it seems to be getting a lot of positive buzz lately. The
               | only thing keeping me from going that way is that I can
               | offload most of the frontend work to folks who understand
               | it better.
               | 
               | For 2b, could you elaborate a bit? Is this like having
               | dedicated handling for specific functionality? If I
               | understand you, for example instead of PUT-ing some
               | status on /myobject/{id}/, I could have something like
               | /myobject/{id}/update_status/. And the benefit here is
               | assuming that setting status is not a straightforward
               | transition (maybe requires other transformations, etc),
               | that this lets you better compartmentalize this complex
               | logic instead of having one giga-endpoint for all PUTs?
        
               | 8bithero wrote:
               | Given that you're the sole backend developer with a
               | focused vision for the app, the Server-Informed UI
               | approach described in the article could work well for
               | you. It simplifies the backend architecture and makes it
               | easier to coordinate with your frontend team.
               | 
               | However, for long-term scalability, you might run into
               | issues with this approach. If so, take a look at "Bounded
               | Contexts," a technique in Domain-Driven Design that helps
               | break down your application into manageable, scalable
               | units.
        
         | ericmcer wrote:
         | I... don't like this.
         | 
         | You are basically saying we should take a name that conveys
         | info about its content (companyName) and change it to something
         | that contains none (pageTitle).
         | 
         | I can tell if a field is being used for a page title by looking
         | at the html, I can't tell what it contains unless it is named
         | well. Additionally if I ever want to hop into the backend my
         | time on the frontend will have given me 0 context if you are
         | renaming all the fields.
         | 
         | Also if you want to use Typescript this would prevent a bunch
         | of automated type generation you could do.
        
           | jackblemming wrote:
           | Like most things, it depends. If you have a generic math
           | module, you of course want generic parameter names. It would
           | be weird to have a differential math library with a bunch of
           | random terminology from another domain mixed in.
           | 
           | If the page only makes sense if a company name is used as a
           | title, then of course use companyName as the variable.
        
           | rvnx wrote:
           | It's a very curious way of doing things.
           | 
           | The result with this strategy is that you may need the
           | companyName and end-up at some point with code that does
           | back:
           | 
           | companyName = pageTitle
           | 
           | or worse:
           | 
           | companyName = pageTitle.split(' - ')[0]
           | 
           | Because there is a moment when you will need to get the
           | companyName again for some comparison or some whatever logic
           | (e.g. is selected account profile current company ?)
           | 
           | This feels very confusing.
           | 
           | Instead pass companyName and keep it that way until the very
           | last moment that you display it on the page (e.g. when
           | rendering the view/template)
        
             | hakunin wrote:
             | The whole point is that when you need companyName for
             | another thing, you should create a parameter `anotherThing`
             | and backend will set companyName into it as well. It's
             | designed to make it very weird to _not_ do that, so that
             | you don't do that.
        
               | [deleted]
        
           | EGreg wrote:
           | You guys are each partially right. What you need is
           | MIDDLEWARE.
           | 
           | On the one hand, you have some data coming in format X.
           | 
           | On the other hand, you need the data in format Y.
           | 
           | What you need is to define how to map X to Y. And then when
           | you request Y, a way to indicate what parts of X you really
           | need, so the code getting X can optimize, if it needs.
           | 
           | In my experience, the real issue is how to _cache_ the X -
           | should we be caching all of it depending on the Y, or should
           | we be caching parts and understanding how they fit together.
           | I have had problems with updating caches, and I am looking
           | for solutions!
           | 
           | https://news.ycombinator.com/item?id=36146520
        
             | valenterry wrote:
             | I think what you are looking for a is "(pure) functional
             | reactive programming".
             | 
             | The problem with caching is that it is very often highly
             | individual and it usually comes with drawbacks, i.e. you
             | win performance here but lose it there or you win
             | performance but you lose consistency. (related: CAP
             | theorem)
             | 
             | So I doubt there is any "generic" solution that will or
             | even _could_ make you happy. But if you find one, let me
             | know. :-)
        
               | EGreg wrote:
               | Well, in a single-threadsd environment you almost can
               | have consistency, and you can cache the latest results.
               | What I am saying is that if a result consists of X1, X2,
               | X3 but you don't need all of them for a certain request,
               | then you wind up caching X1, X2 one time, and requesting
               | X1, X3 another time, what to do with the cache of (X1,
               | X2)? Currently I just update the caches which are subsets
               | (X1) of a cached response, and do it with manual
               | individual code. I hoped that I could have some sort of
               | dependency graph. Maybe reactive programming, yeah. But
               | that would essentially be some sort of declarative
               | language, to run pure functions which still have custom
               | code. Hmm
        
           | Philip-J-Fry wrote:
           | They're suggesting using the pageTitle parameter for the
           | title, and being explicit about how things are used. If you
           | pass a companyName parameter, it is quite generic. You just
           | happen to use the companyName for the title, but you also use
           | it elsewhere. Someone might want to add some additional info
           | to the title. Their solution will likely be a new parameter
           | and then concatenate these values together. But if you just
           | thought about being explicit to begin with, then you'd
           | already have the functionality to do that.
           | 
           | The idea is to write things as standalone components. Which
           | is a pretty universal programming strategy.
        
         | nonethewiser wrote:
         | Seems like you couldnt have front end engineers with this
         | philosophy. Or you could but it would be very unproductive.
         | Because theyd need backend changes for every API call.
        
           | jmilloy wrote:
           | Yeah. This is suggesting to me that the "model" live in the
           | back-end obviously and the "view" is separated across the
           | front-end and back-end. I think that does sound more
           | straightforward for many cases. So working on the "view"
           | requires being not exactly a "full-stack" engineer but at
           | least being able to make changes both on your front-end part
           | of the view that makes API calls and back-end part of the
           | view that serves them. I think that makes sense. You can
           | still have fully "back-end" developers that handle the
           | database and actual server, and fully "front-end" developers
           | that handle ui design and content.
        
           | nucleardog wrote:
           | Yep, in my experience this is what it led to.
           | 
           | Every API call was so form fit to the UI that nearly every UI
           | tweak needed frontend and backend changes.
           | 
           | It didn't need to be this way (there was a lack of
           | engineering skill and leadership), but even past the surface
           | level much of the backend code beyond the API interface also
           | became form fit to the specific use case meaning many times
           | seemingly simple changes required near total reimplementation
           | of all of the business logic and other underlying code.
           | 
           | End of the day, showing the same data or exposing the same
           | flows elsewhere in the application required nearly a total
           | reimplementation on the backend. This created an explosion in
           | size of the codebase and complexity.
           | 
           | This whole idea seems to basically be going back to RPC-based
           | APIs and all the drawbacks that led to everyone kind of
           | collectively agreeing REST was better (even if most people
           | only sort of half implement it).
           | 
           | Our approach, staring down a roadmap of projects that
           | basically involved exposing the same functionality over and
           | over with different pictures in front of it was to steer
           | _hard_ the other direction.
           | 
           | We sat down and put together an API specification that laid
           | out the general shape of an API. Not the specific resources,
           | but for any given collection/resource how it should be
           | exposed. We found common "tough" use cases and figured out up
           | front how to expose those RESTfully and documented the
           | patterns to maintain consistency. We put down a framework in
           | code to make compliance with the spec the "easy" path for
           | most cases.
           | 
           | Then we approached the rest of the design from an API
           | perspective, not a frontend or backend perspective. For any
           | given flow/operation/etc, what would a good interface look
           | like for this. (This is very similar to figuring out what the
           | interface for a module/class/etc should look like, given its
           | responsibility, before writing it.) Then we built it.
           | 
           | The end result has been that more and more frequently
           | requests and even entirely new projects require _no_ backend
           | involvement. Often the FE team doesn't even need to ask any
           | questions--given any endpoint that exposes a collection of
           | resources, they know _exactly_ how to work with it because
           | they're all the same.
           | 
           | When new business rules or requirements come in, we no longer
           | need to apply them in 5 or more different places across two
           | codebases. And we've still maintained a good separation of
           | frontend and backend duties to the point our FE team is busy
           | but kind of bored--they're only really concerned with the
           | view/display logic at this point.
           | 
           | Company history is largely lost to the mists of time, but the
           | API routes were all prefixed `/v5/`. I can only imagine how
           | much further along the company would be if they'd spent the
           | last decade building on top of a foundation instead of
           | rebuilding the foundation every two years as they have been
           | with the RPC model.
        
             | hakunin wrote:
             | > showing the same data or exposing the same flows
             | elsewhere in the application required nearly a total
             | reimplementation on the backend. This created an explosion
             | in size of the codebase and complexity.
             | 
             | I'm trying to understand how this is possible. Couldn't the
             | backend logic that contributes this response fragment in
             | one endpoint be extracted and reused to contribute the same
             | response fragment in another endpoint?
             | 
             | Was backend not modularized and reused?
             | 
             | The way I understand your approach, you ended up building
             | and maintaining CRUD resources similarly to how they would
             | exist in a naive public API, but the difference is that you
             | spent extra time to build more meaningful, rich, business-
             | level resources than serving nearly raw database records.
             | 
             | This is probably a good compromise that isn't disagreeing
             | with the article as much as you seem to be implying. The
             | difference between your approach and the article's approach
             | is a small side-step. You either let the front-end fetch
             | your rich business-level resources separately, or you
             | package them into pages and serve them in a nice single
             | package. Or you can build pages as per the article, and
             | extract these rich resources that you display in those
             | pages into separate endpoints for some additional
             | flexibility. Either way, you end up with rich use-case
             | driven resources, packaged differently.
        
             | underwater wrote:
             | > Every API call was so form fit to the UI that nearly
             | every UI tweak needed frontend and backend changes.
             | 
             | Having to change backend code is not necessarily a bad
             | thing. Just don't structure your code as two seperate
             | codebases built by two different teams.
        
           | paulddraper wrote:
           | This philosophy encourages full stack engineers.
           | 
           | So every feature/change only needs one engineer.
        
             | hakunin wrote:
             | While this may be true to some extent, I think front end
             | has plenty to deal with even if you do ship them the exact
             | data they need.
             | 
             | Primarily, this philosophy encourages you to maintain a
             | strict connection between needed use cases, and the code
             | that enables them. Once that connection is severed, your
             | code expands beyond the required use cases, and you end
             | having to maintain support for phantom/theoretical use
             | cases.
        
               | 8bithero wrote:
               | This approach would also be a nightmare if you ever
               | decided to refactor the frontend. You'd be forced to do
               | double the work since failing to update your backend
               | would probably result in nonsensical legacy naming... I'd
               | also dread to think what would happen if you also used
               | the backend to serve a mobile app. You'd end up spending
               | 40% of your time trying to figure out what to name fields
               | before eventually going full circle and reverting back to
               | logical generic names :|
        
               | rvnx wrote:
               | And the moment your SaaS is growing, and your customers
               | request access to your API:
               | 
               | Instead of just implementing ACLs/permissions on existing
               | APIs you have to develop _and_ maintain two APIs, one for
               | the customers (that will get outdated with lot of missing
               | features and be less battle-tested) and one "real API".
        
               | paulddraper wrote:
               | Releasing a public API is.....an enormous commitment.
               | Anything you do has to be maintained for years.
        
               | BytesAndGears wrote:
               | Agreed, and my company has done exactly that.
               | 
               | Our public API is fit for the use-cases of our big
               | customers that want deep integrations, and our frontend's
               | API is able to handle our specific workflows.
               | 
               | We have a bunch of shared backend code, but the endpoints
               | that our API customers use are very specific. Sometimes
               | we build custom endpoints for a single customer which
               | would be useless for our frontend/services. Keeping them
               | separate allows them to gain needed functionality without
               | trying to bolt it on to existing internal APIs, and
               | cluttering it all into one messy blob.
               | 
               | Of course our internal API is a mess in a bunch of other
               | ways but at least we don't have to deal with the public
               | parts making it even messier
        
             | nucleardog wrote:
             | Ignoring my general thoughts on full stack engineering for
             | the sake of brevity--this works okay if your FE and BE have
             | enough overlap in necessary skill set (e.g., same language)
             | but in my experience when you need to hire a senior
             | Rails+Vue3 developer or something you're going to be
             | tearing your hair out.
        
         | jmilloy wrote:
         | This and the article strike me initially as completely wrong,
         | which makes it very interesting. I still want a clear
         | separation between the "model" and the "view", and I guess I
         | tend to assume that this corresponds to the front-end and back-
         | end. Maybe that's a poor assumption.
         | 
         | What I see here is that the "view" is split across the front-
         | end and the back-end. Or in other words, the back-end contains
         | both the model and the JSON API as a view. I think this is what
         | is meant by "I suggest you stop treating your frontend as some
         | generic API client, and start treating it as a half of your
         | app."
         | 
         | I still want a clean separation between the model, e.g.
         | companyName, and the view, e.g. pageTitle. Somewhere, there
         | needs to be the explicit logic (in the back-end part of the
         | view) that says that the the pageTitle for page A is the
         | companyName. It's okay for many different views to "reuse"
         | fields from the model, but each view should have its own front-
         | end and back-end components. That the view is split across a
         | front-end/back-end divide through the nature of the web-stack
         | doesn't change the fact that each view should remain distinct
         | from the other views.
         | 
         | So I can agree in the sense that the alternative where you
         | create a general-purpose JSON API as a model _and_ view in the
         | back-end, and then essentially code up an _additional_ model
         | and view for each front-end page /element with logic to convert
         | the API data into the necessary content is a waste of time.
        
           | slim wrote:
           | it's called Controller and it's for this exact reason that
           | it's separate from the Model and the View.
        
             | jmilloy wrote:
             | I disagree, the controller is something else. The point is
             | that MVC is orthogonal to backend/frontend.
        
           | hakunin wrote:
           | Arguably, the opposite is true. The view is more washed out
           | across the stack if back-end supplies generic fields, and
           | front-end decides how to use them. Now you no longer know who
           | is responsible for which decisions, and have to look for them
           | everywhere in the stack.
           | 
           | If back-end provides the entirety of data to build the page,
           | then you limit front-end decisions to UX based on the
           | specific data, and no longer allow them to pull in new
           | functionality or foundational business logic over to their
           | side.
        
             | Terretta wrote:
             | > _arguably... view is washed out across the stack_
             | 
             | Perhaps to argue this requires munging "view" with "front
             | end"?
             | 
             | MVC needn't mean database schema, front end, and logic. It
             | could, but then what is a "view" in the database?
             | 
             | Perhaps you're reinventing MVVM?
             | 
             | https://en.wikipedia.org/wiki/Model-view-viewmodel
        
               | jmilloy wrote:
               | MVVM definitely came to mind as I was writing my comment.
               | The model is clearly in the back end, the view clearly in
               | the front, and the view model contains the explicit link
               | between companyName and pageTitle and can live in either.
               | Here the suggestion is to put it in the backend and serve
               | it as JSON.
        
               | Terretta wrote:
               | Normally I'd say "kids these days" but all 3 of our
               | accounts joined in 2010.
        
             | jmilloy wrote:
             | I think if the back end provides generic fields and the
             | front end acts as an independent consumer of the API, then
             | you essentially have two apps each with their own entire
             | MVC (or whatever paradigm you are using), one on the front
             | end and one on the back end. So I wouldn't quite say that
             | "the view is more washed out across the stack" but that you
             | have two views (and two models).
        
               | hakunin wrote:
               | Agree with this. Of course because front-end still gets
               | to build business logic, and back-end still ultimately
               | decides the basis on which to build it, the decision
               | making is spread more equally between them. Perhaps
               | calling it "a washed out view" is not strictly
               | appropriate, but worth acknowledging that the front-end
               | is at the mercy of what back-end decides to provide it.
        
           | sroussey wrote:
           | A backend model is usually just called the model as it's
           | modeling the data domain (sometimes called 'domain model').
           | The thing you pass to the frontend is the 'view model' which
           | is often entirely different.
           | 
           | In some CRUD situations though, they can be nearly the same
           | and you can convert the domain model into a specific view
           | model with some kind of adapter (how people do this varies a
           | lot). This adapter will take the end user security level into
           | account, for example. Also, to avoid sending lots of useless
           | data for a list, you can have a list view model. But if you
           | do that, be sure to either keep the two in sync, or you have
           | one and keep track of whether it's partially or fully
           | hydrated.
        
             | jmilloy wrote:
             | I agree that mvvc sounds exactly right, but there is still
             | the question of whether the view model is created in the
             | back end (which is what the article is advocating) or in
             | the front end (which is what you have to do if the back end
             | serves the model like a general use API).
             | 
             | The MVC or mvvc or whatever paradigm is somewhat orthogonal
             | to the technical back end/front end.
        
         | simplify wrote:
         | Full static typing alleviates this greatly, allowing you to
         | pass in what you have now and decide to refactor later if/when
         | you need to.
         | 
         | For example, if you remove a field that's still needed, you'll
         | receive a type error, eliminating the problem of losing track
         | of use cases.
        
         | jlawson wrote:
         | It's an example of the general rule to name/implement functions
         | according to what they do, not how they're used.
         | 
         | Stated another way, when building a tool, don't let information
         | about the incidental context leak into the design of the tool
         | itself. It should be designed to serve its intended purpose
         | independent of when, how, where, or why it was built. This way,
         | it won't break when that context changes, or when it's used in
         | a new context.
        
           | xpe wrote:
           | I was nodding along until this part: "It should be designed
           | to serve its intended purpose independent of when, how,
           | where, or why it was built."
           | 
           | This is impossible and in many cases undesirable. As long as
           | the purpose and behavior of the function is clear, it is OK
           | if it has contextual roots. Actually, no, it isn't just OK,
           | it is the way it must be.
           | 
           | Take one aspect of a sorting function for example. Should it
           | be stable? Or not? This decision is rooted in the context. To
           | try to make the function independent of context is impossible
           | and unwise.
           | 
           | Are you making a different point?
        
             | adammarples wrote:
             | Whether it's stable or not is irrelevant, if it's
             | "stable_sort()" then it always should be, if it's
             | "sort(stable: bool)" then it could be. It shouldn't depend
             | on why and when I intend to use it. Most importantly it
             | shouldn't suddenly become stable when I pass
             | "sort(companyName=Walmart) because that's what we needed to
             | do for Walmart but none of the others. That's outside
             | context leaking in and a big mess to maintain.
        
       | ChrisMarshallNY wrote:
       | I've done this, and agree.
       | 
       | But it was a good exercise for me, and I ended up using the
       | general-purpose backend for a specific frontend.
       | 
       | It's just that it's way overkill. Much more complex than it needs
       | to be.
       | 
       | But it works really, really well, and is secure as hell.
        
       | jokethrowaway wrote:
       | Great article.
       | 
       | We used to call this common sense. It's insane we drifted so far
       | from being sensible.
       | 
       | I genuinely think 90% of frontend developers should not exist:
       | the web would be better and companies would have better products.
       | 
       | I include myself in the frontenders, I do terrible apps which
       | should just be simple static pages with a sprinkle of js - in my
       | defense, I need the money and nobody listens to me, they say this
       | is modern frontend development.
       | 
       | For my tech not-savy clients I can deliver awesome and simple
       | solutions without using the dreaded R framework.
        
       | solatic wrote:
       | Hard agree with the YAGNI conclusion. There's a certain minimal
       | amount of complexity needed to build your system, you need a good
       | reason to build out another layer of indirection / abstraction
       | here, something like needing web + mobile for the MVP or offering
       | users direct access to the API as part of the MVP. Remember: if
       | you think there's value in a REST-style layer, you don't need to
       | build a separate API to support that. You can just write a
       | getUsers() method on the server instead.
       | 
       | What do you get when you throw out the API layer? Easier
       | refactoring (no wondering who all the consumers of GET /users
       | are). No implicit contract with users who have reverse-engineered
       | your API (and complain if you break it). Easier security (who
       | needs API tokens?). No organizational footgun that leads to a
       | frontend/backend team split and then requires a group manager to
       | get new features shipped, because of course your API doesn't
       | actually expose feature-specific data for features that Product
       | hasn't dreamed up yet.
       | 
       | Sure, if you're FAANG scale, it'll be easier to work with APIs.
       | You'll have some Staff+ Engineer architecting everything and
       | coordinating between Product and a half-dozen teams that'll take
       | months if not years to ship, and everyone will be happy with
       | that. Strong fences make good neighbors, and contracts keep teams
       | independent of each other. But in the _early days_? Feel free to
       | ship things that don 't scale.
        
         | kstrauser wrote:
         | I beat the drum of _complexity_ vs _complication_. Solutions to
         | a given problem have an inherent complexity. That's the minimum
         | amount of sophistication and cleverness required to implement
         | them. And then there's complications (think of the watchmaker's
         | term) which extra features that don't directly solve the
         | problem but, well, they look kinda neat!
         | 
         | Strive to find that inherent, irreducible complexity and solve
         | at that level. Resist the urge to say "for just 20% more
         | effort..."
         | 
         | I want to get a YAGNI tattoo.
        
         | mediaman wrote:
         | If you use an API, but in a way the author suggests (conformed
         | to the UI, rather than an abstraction), what's the
         | simpler/better way to do auth than API tokens?
         | 
         | I have depth of experience in a niche industry and I'm working
         | to build solutions for that industry, but I'm still early on
         | the learning curve of being an effective full stack developer
         | to make those solutions.
        
         | drew-y wrote:
         | > Easier refactoring (no wondering who all the consumers of GET
         | /users are)
         | 
         | Unless your API calls are properly abstracted into function
         | calls. No reason you can't just have a `getUsers()` function on
         | the frontend, and then use your favorite "find all references"
         | tool from there.
        
         | rewmie wrote:
         | I think your comment doesn't really make sense. Unless you're
         | somehow assuming that the one and only way to do web apps is to
         | go the dynamic html path, I don't see how your suggestion can
         | even apply. Once you have a frontend that needs to retrieve
         | data from a backend, how do you even address that?
         | 
         | Your comment reads as if someone complains people don't
         | actually need cars because they can just show up somewhere.
        
       | kakapo88 wrote:
       | I'm finishing a project now, using exactly this design pattern.
       | Sort of backed into it, motivated pretty much by the issues
       | outlined. In addition, I wanted something that is clear and
       | sustainable far into the future. The simplicity of this approach
       | supports that. Quite liberating.
       | 
       | Complexity is the enemy.
       | 
       | True, one might reasonably propose a number of what-if
       | objections. But for many (most?) projects), imo this is a good
       | approach.
        
       | ChicagoDave wrote:
       | I'm going to get zapped once again, but if you're building
       | complex applications, custom read models automatically updated
       | based on events from operational writes is the optimal way to
       | connect a front-end to APIs.
       | 
       | Each read model should have a distinct business purpose.
       | 
       | Generic models will only confuse maintainers and they're very
       | likely going to see such code as brittle and tech debt.
        
       | TekMol wrote:
       | The way HN is build is the best way to build web applications.
       | 
       | There is a concept of a "page". A page is loaded as an html page.
       | This thread for example is a page.
       | 
       | And then there is JavaScript which does all kinds of dynamic
       | stuff on a page. Like when you update this commment or when you
       | collapse/expand comments.
        
         | osrec wrote:
         | I disagree. I understand a lot of people enjoy the simplicity
         | of HN, but when you find a developer who really knows how to
         | take advantage of the additional "bells and whistles" that come
         | with modern browsers, without making them annoying, the
         | experience can be significantly better than HN.
        
           | laurels-marts wrote:
           | By "bells and whistles" you mean the Web APIs?
           | https://developer.mozilla.org/en-US/docs/Web/API
        
           | TekMol wrote:
           | Sites like Reddit, Twitter, Facebook would be 100x better if
           | they would be built the HN way.
           | 
           | If these companies don't have the developers to show that
           | "Bloated React Single Page General API sites" make a better
           | UI then who has?
        
           | throwsubsun wrote:
           | Can you elaborate on this? I'm wondering what those bells and
           | whistles are, or how the experience could be "significantly
           | better."
        
             | robertoandred wrote:
             | Like not having to go through two page loads just to add a
             | comment.
        
         | MrPatan wrote:
         | I don't think this applies to bigger apps like an excel or
         | Photoshop. I don't think HN is very "appy", to be honest.
        
       | bofaGuy wrote:
       | This is how you lock yourself into a single front end design. And
       | when you get ready for the next generation of your app or site,
       | now you're locked in and changing that front end design becomes
       | exponentially harder.
        
         | hakunin wrote:
         | In case of a complete redesign, yes you're right. With a
         | generic API you will have about as much trouble writing the
         | redesign as you did the original design.
         | 
         | In practice, a complete redesign is an incredibly rare event,
         | and a good problem to have. Usually design of individual pages
         | and layouts undergoes gradual, incremental changes, driven by
         | real needs.
         | 
         | A redesign that requires front-end restructuring to such an
         | extent that the data supplied is no longer sufficient should
         | probably involve backend collaboration. Otherwise, you're
         | tasking your backend team with building a generic site builder,
         | which is much harder than a specific backend for your frontend.
        
       | gabrielmrts wrote:
       | is the first time that i see that idea, sounds crazy and out of
       | the box imagine a real project using it..
        
       | qudat wrote:
       | Very similar sentiment to this article https://bower.sh/dogma-of-
       | restful-api
        
       | jensneuse wrote:
       | An alternative to what's suggested in this post, how about going
       | API first or even API only? Don't build a frontend at all, just
       | build an API. E.g. you can deploy things on fly.io just by using
       | their GraphQL and REST APIs. The advantage of focussing on the
       | apis is that other developers can much easier integrate with your
       | service and embed it into their own applications.
        
       | sergioisidoro wrote:
       | My personal take: Don't put it all in the same box.
       | 
       | Just have a api/v1/rest/ base path for modular well defined
       | resources that can be used across your application, without
       | breaking changes, or even shared to third parties.
       | 
       | Then have a api/v1/features for coupled endpoints that return non
       | standard objects, and with a more flexible lifecycle.
       | 
       | Chances are you're better off having both instead of trying to
       | cram all the use cases into one approach
        
         | indymike wrote:
         | I can't agree more: having a separate API for functionality and
         | a separate one for non-standard (i.e. UI) is a great way to do
         | this.
        
         | nicodjimenez wrote:
         | That's a nice approach.
        
         | antonhag wrote:
         | Most times you won't need a well-formed (REST) API to start
         | with, and many times you will never need it. Most small
         | projects should start without one and create one when need
         | arises.
        
       | tootie wrote:
       | This is BFF pattern described many years ago. Here's the standard
       | way I build this kind of thing: Develop your APIs per functional
       | or really per system. One for content, one for identity, one for
       | ads or whatever. Then you build an orchestration tier that does
       | pretty much what OP says. It stitches the various services
       | together and returns a page model. The ideal is to reduce round-
       | trips and cognitive load on FE dev. If you need the top 3 pieces
       | of relevant content, plus an ad plus the user's first name,
       | return all of that and nothing else. The last piece is just SSR.
       | Use next or nuxt or whatever and you can output HTML on the
       | server or stich it on the client with one codebase seamlessly.
       | 
       | https://samnewman.io/patterns/architectural/bff/
        
       | [deleted]
        
       | kgeist wrote:
       | General purpose API helped us when we had several features to
       | implement in a row on a tight schedule: when I was busy
       | implementing feature N+1, our frontend dev was still polishing
       | feature N (with changing UI/UX requirements), and she didn't need
       | me (the backender) because the backend just exposed the model as
       | is without knowing what the frontend looked like. She could make
       | lots of changes to the UI without needing any changes to the
       | backend. Yeah it translated to more API calls but it allowed us
       | to decouple our work completely and deliver more features in
       | parallel.
        
       | ggregoire wrote:
       | I don't know when we started splitting people into "frontend" and
       | "backend" teams (FAANG influence?) and for what reasons, but 10
       | years ago we hired people with a general background, smart and
       | curious enough to learn SQL, HTML/CSS/JS and whatever language
       | you want to use on the server, able to build some end-to-end CRUD
       | features on their own. And that's like what 99% of the companies
       | need.
       | 
       | My point being: when you have the same person building the UI and
       | the API, you avoid a lot of the problems described in this
       | article.
        
         | nucleardog wrote:
         | After a couple decades of doing this... I'd pin it on an
         | explosion of complexity and scope in the frontend.
         | 
         | It used to be if you could find a solid engineer with some
         | vague aesthetic sense they could efficiently carry something
         | through from conception and design to completion.
         | 
         | These days the scope of frontend development has increased to
         | the point where learning and staying on top of it has become
         | too large (in my opinion) for most people to do while also
         | becoming and staying highly competent in everything else.
         | 
         | A "full stack" developer these days is supposed to understand
         | frontend development, backend development, systems
         | administration, cloud operations, and what else? All of these
         | are massive areas that are constantly shifting.
         | 
         | By way of analogy, we used to have the town barber handle
         | haircuts and shaves but also surgery because the main skill to
         | master was precision with a blade. Then as the scope of being a
         | surgeon expanded to include things besides being able to cut
         | precisely, that became its own specialization. Further on, even
         | within surgery each area of the body started to require so much
         | specific knowledge that we further broke that down into all the
         | different surgical specialties (heart surgeon, podiatric
         | surgeon, brain surgeon, etc).
        
           | ggregoire wrote:
           | > These days the scope of frontend development has increased
           | to the point where learning and staying on top of it has
           | become too large (in my opinion) for most people to do while
           | also becoming and staying highly competent in everything
           | else.
           | 
           | I feel like frontend complexity is just a meme on HN to be
           | honest. How complicated is it to learn a framework like React
           | (which celebrated its 10 years 3 months ago) if you have a
           | background in software engineering and some basic knowledge
           | of HTML/JS? Like an afternoon to read the doc? 3 days to
           | practice and be totally fluent? I managed graphic designers
           | who knew nothing about computers but were able to learn React
           | and be very productive. Then you pick one tool to build your
           | production app. Yes there are many options, but you choose
           | one (I use Vite.js) and stick with it for the next 5 or 10
           | years.
           | 
           | > A "full stack" developer these days is supposed to
           | understand frontend development, backend development, systems
           | administration, cloud operations, and what else? All of these
           | are massive areas that are constantly shifting.
           | 
           | There is a new big thing every 10 years or so. Like the last
           | one was Kubernetes and it almost 10 years old and you
           | probably don't even need it. HTML5, ES6, React, Python,
           | Django, SQL, Postgres, Docker, AWS, Terraform... all those
           | tools have been there since almost forever (it feels like it)
           | and mostly never changed. And you can build 99% of the web
           | with that stuff.
           | 
           | As I said in another comment, yes it's a lot if you are a
           | junior dev fresh out of college but you probably have some
           | solid knowledge of all of that if you have been doing this
           | for a very long time. At least enough understanding and
           | experience to know what to google when you need to do
           | something and what to do with what you found.
        
             | d357r0y3r wrote:
             | Yeah, it's this.
             | 
             | It's not that tough to keep up with FE. React has been
             | dominant for closing in on 10 years now. ~2015 was probably
             | peak framework fatigue. If you left the industry in 2016
             | and came back now, you could probably get productive and
             | you would even recognize a lot of the tools.
             | 
             | The HN meme is that "Well ackshually you could build Figma
             | with ASP.NET Forms, just like we used to do back in my
             | day." That just doesn't resonate with anyone doing the work
             | day to day because applications themselves (not necessarily
             | the front-end tech) have a much higher bar today.
        
         | hakunin wrote:
         | In a way, this article tries to bring the alignment between the
         | frontend and backend closer to the full stack days, while also
         | acknowledging the increased complexity of the front-end, that
         | may be deserving of its own team focused on great UX.
        
         | Phreaker00 wrote:
         | For someone who has been in this field for 20 years I remember
         | starting out doing every aspect of webdevelopment myself. Then
         | the bigger and more complex the projects became, the less that
         | made sense.
         | 
         | The requirements of the distinct fields have gotten to a point
         | where it's very impractical and hardly worthwhile for one
         | person to master them all. You can't expect someone to
         | translate a design into modern components that support all
         | types of devices, resolutions and contexts to also come up with
         | optimized SQL queries and knowing how to choose between Docker
         | and Ansible for their distributed serverless functions that
         | handle a variety of external endpoints.
         | 
         | Ofcourse not every project that uses this approach needs this
         | approach, and there's still a market for the Do-It-All
         | developer. My point is that the webdevelopment world of today
         | isn't that of a decade ago.
        
           | ggregoire wrote:
           | > You can't expect someone to translate a design into modern
           | components that support all types of devices, resolutions and
           | contexts to also come up with optimized SQL queries and
           | knowing how to choose between Docker and Ansible for their
           | distributed serverless functions that handle a variety of
           | external endpoints.
           | 
           | Why not? Obviously you can't expect this from someone fresh
           | out of college/bootcamp, but that's what I do on a daily
           | basis and I'd expect this from anyone with 10+ years of exp.
        
       | simonbarker87 wrote:
       | So basically an old style MVC framework style app like RoR,
       | CodeIgniter etc but made with a JSON response the describes the
       | page rather like Shopify's Store Theme 2.0?
       | 
       | Sounds great. Now since you have access to the server code
       | (unlike Shopify's system described above) just return HTML and
       | use your JS flavour of choice in the places where you need heavy
       | JS ... like we used to make web apps.
       | 
       | The happiest web devs I speak to are those working in the older
       | MVC style, mainly RoR people. While everyone in AWS/Serverless/JS
       | land is burning out and miserable with the house of cards stack
       | we are balancing React on top of.
        
       | zianKazi wrote:
       | I am not a big fan of building extremely fine grained general
       | purpose APIs for frontends. A lot of the burden of juggling with
       | data and presenting it is shifted to the UI layer. I am also not
       | a big fan of building a composite API for "pages". Now you have a
       | tightly coupled frontend/backend communication. What happens when
       | we split the page or have to change the format of the data? Also
       | the response of such an API can be quite big and nested. Ends up
       | being a dump of data with poor documentation. I would try to find
       | a middle path. Building composite APIs which have a concise
       | purpose for the frontend but are modular enough to be reused
       | across different areas of the application. Also, I feel that most
       | of the problems discussed in the post are amplified when we have
       | different groups working on the frontend and backend. If a single
       | team is responsible for both the backend and frontend, API
       | decisions are localized and can be changed as the development
       | progresses.
        
       | xg15 wrote:
       | And the htmx-ification trend continues. I guess this is sort of
       | the counter movement now to all the API-First/Data-First/SPA-
       | First evangelism of the last few decades.
       | 
       | I don't quite understand why though. Or rather, why those posts
       | always seem to have an intense emotional dislike to anything
       | data-driven.
       | 
       | What exactly is wrong with just using React? Or, heaven forbid,
       | plain Javascript, which browsers have spent the last decades
       | optimizing it make working with REST APIs and JSON as easy as
       | possible.
        
         | neon_electro wrote:
         | Can you expand on "just" using React? Are you saying "what is
         | wrong with using React (the framework including React the
         | library and all of its friends)?", or are you saying "what is
         | wrong with just using React (the library) only?"
        
           | xg15 wrote:
           | I was more thinking of React, the framework, with as little
           | addons as possible. React's data model always seemed the most
           | reasonable to me, if you have to use a framework or library
           | at all.
        
       | ahuth wrote:
       | Nice article
       | 
       | This is one thing I'm loving about Remix. It's how the framework
       | works, so there's no need to enforce this pattern or educate
       | folks about it.
       | 
       | AND Remix's nested routing still has you break down the data
       | loading into a couple different parts (1 per route segment).
       | 
       | So it feels like you're not loading everything in one place, and
       | may be less likely to make people feel like they're doing
       | something "different" or "wrong". It's
        
       | hot_gril wrote:
       | The complaint about general-purpose APIs is valid. I've seen
       | teammates, including senior ones, jump onto the bandwagon of some
       | monstrous "data service" at work where the entire API to the
       | frontend was an ORM. Absolute trainwreck.
       | 
       | This article advocates for another extreme that I've also seen at
       | work. They invented some UI language in JSON and built some
       | default JS components to render it. It works for very simple
       | cases, but it's too rigid for anything slightly advanced, so the
       | end result is some very clunky UIs and unhappy devs. You said
       | your experience was bored frontend devs; that's usually a sign
       | that their value is going to waste, and probably not because the
       | backend devs can do their job better.
       | 
       | There's a good middle ground that's pretty common. You don't
       | define the API to end all APIs, you don't pretend FE and BE are
       | totally decoupled, you just have the frontend team ask for what
       | they need and let the backend team serve it. Maybe you get an
       | endpoint per page this way, but it's just sending back the data
       | to populate the page rather than the actual layout. Maybe a few
       | things are separate endpoints, but a reasonably low number.
        
         | hakunin wrote:
         | > This article advocates for another extreme that I've also
         | seen at work. They invented some UI language in JSON
         | 
         | This is called server-driven UI, and not what the article is
         | advocating. I try to make that distinction by calling the whole
         | practice server-informed UI, rather than server-driven UI. The
         | article is meant to be advocating almost exactly what you wrote
         | in the 3rd paragraph.
        
           | hot_gril wrote:
           | Your note says, "A Server Driven UI is when the API tells the
           | client which components to display and with which content."
           | Your description of server-informed UI is, "Render concrete
           | boxes, sections, paragraphs, lists. Render the visual page
           | structure." What's the difference?
           | 
           | More concretely, in your example:                   {
           | "section1": {             "topBoxTitle": "Foo",
           | "leftBoxTitle": "Bar",             "linkToClose":
           | "https://..."           },           "section2": {
           | ...           }         }
           | 
           | I was thinking these keys are special and a different page
           | would also have "section1" with "topBoxTitle," but maybe I
           | misunderstood. If these keys aren't special and the frontend
           | dev is just humanly interpreting this differently on each
           | page then defining the actual layout to display it, that's
           | probably fine. But I wouldn't describe this as rendering the
           | visual page structure in the backend.
        
             | hakunin wrote:
             | It may totally be my bad for not making this part clearer
             | in the article, but these structures are never meant to be
             | fed into something that can automatically produce a UI.
             | They are not meant to be consistent.
             | 
             | The way I've been describing this lately -- the json
             | structure should come from you squinting at the page and
             | seeing approximately what needs to be on it, and creating
             | as-flat-as-possible way of sending it over, that makes it
             | clear enough what each field is for, but not so granular as
             | to be automatable.
             | 
             | If you have a designer in your company, I've been
             | increasingly preferring to use their terminology to name
             | fields. If page has "cards", "navigations", "banners"
             | whatever designer calls them, call them the same way in
             | JSON. This is a good middle ground. It makes sure that
             | back-end passes what front-end needs, while at the same
             | time making sure that front-end doesn't get the wrong idea
             | that their framework can dictate and accept this json
             | structure directly.
             | 
             | So if a full JSON-based language would allow you to
             | customize every page element in any way you like, this
             | approach only lets you to send over decisions about this
             | page, using a json payload specifically for this page and
             | the ways it can change, no more no less. You cannot add an
             | arbitrary box or an arbitrary section in json, and expect
             | it to appear.
        
       | rhuru wrote:
       | I have building most of my modern sites with NextJS and could not
       | have been happier as it gives me the flexibility of directly
       | quering DB, I dont have to worry about the general purpose API.
       | But if I wanted to I can just easily build it too.
        
       | lll-o-lll wrote:
       | This is good _general_ advice. Sometimes you are building a
       | general library or API, and sometimes there just happens to be a
       | network partition between two components that make one module. My
       | general rule of thumb is that it takes 3-5 times as long to build
       | a library /generic API over regular code. It also requires a very
       | different mindset.
       | 
       | Should you do that sometimes? Absolutely! In big companies you
       | probably have entire _teams_ doing this for API's that are
       | entirely internal. Just recognise that it is a _huge_ cost and
       | only do it when the benefits are likely to outweigh the costs.
       | 
       | That's not to say that you should _never_ think about
       | generalisation when writing normal code, (one of my pet peeves is
       | interfaces taking a single "something" when a collection could
       | just as easily have been used), there are many ways code can
       | evolve and some up-front thought can save a good deal of
       | refactoring later. Just don't write a generic library when domain
       | specific code will do.
        
       | over190bpm wrote:
       | My experience working on "medium sized" B2B apps in 10-20 people
       | teams is that the cleanest way to design API-s is to have a
       | regular REST API for the basic CRUD operations on the entities,
       | and then have more specialized endpoints for specific pages,
       | tables, dashboards etc. on top of that. Having specialized
       | endpoints is kind of required, as the data often needs to be
       | searchable, sortable, filterable and paginated, which would be
       | pretty wasteful, or sometimes even impossible to do on the
       | frontend. I find these kind of REST API-s pretty straight forward
       | to design and implement for the most part, and as others pointed
       | out, onboarding is extremely easy if the new developer on the
       | team has worked in software dev at least for a year or two. This
       | also makes it pretty easy and quick to transition to a fully
       | public API if needed (although I have rarely seen this as a
       | requirement).
       | 
       | Edit: fixed a typo.
        
       | davidy123 wrote:
       | When are we going to get away from all the YAGNI engineering that
       | has sold short the promise of the Web for more rented silos, and
       | get to something more like HATEOAS?
        
       | tuckerconnelly wrote:
       | I see the point of the article, and even on a principled level I
       | might agree with it (e.g., don't overly abstract). A few problems
       | I see though:
       | 
       | 1. If you make backend-only abstractions to keep your code even a
       | little bit DRY, you'll have a duplication of code (both the
       | abstraction and the BFF endpoint). I think it'd be better to go
       | all in on the abstraction up-front.
       | 
       | 2. This will impair the conceptual integrity of the system and
       | arguably lead to development slowdowns in the long run. To quote
       | Mythical Man Month: "I will contend that conceptual integrity is
       | the most important consideration in system design. It is better
       | to have a system omit certain anomalous features and
       | improvements, but to reflect one set of design ideas, than to
       | have one that contains many good but independent and
       | uncoordinated ideas."
       | 
       | 3. Your ad-hoc logic will likely be duplicated anyways across
       | pages.
       | 
       | 4. A general purpose API makes security features like RBAC much
       | simpler.
       | 
       | I think a general-purpose API is a well established abstraction
       | you can rely on for pretty much any project.
        
       | backendanon wrote:
       | > This is similar but not quite the same as Server Driven UI1.
       | Perhaps we could call it Server Informed UI.
       | 
       | I think we should just move back to server side rendering, JSP
       | and even ASP were great, plain HTML, some JavaScript where
       | desired since we can't seem to get away from JS.
        
         | cpursley wrote:
         | The sweet-spot seems to be LiveView (Phoenix) and it's
         | derivatives.
        
         | 9dev wrote:
         | Oh, right. Tell me how well that would work for Figma,
         | Photoshop, or VS Code?
        
       | unconed wrote:
       | This is entirely backwards.
       | 
       | Don't build a general purpose API so your front end can have half
       | the the logic outside.
       | 
       | Just build it the way you would as if it were local, and then
       | hook it up to a back end with a git-like synchronization
       | mechanism. You know, the same way you do all your own
       | development.
       | 
       | If you don't know how to do that, maybe you could learn that
       | instead of arguing over REST vs GraphQL, or whether your line
       | format should care what boxes are on the page.
       | 
       | All I know is, it's fantastic to be able to add features to a
       | front end, persisted in a back end, without having to write code
       | on both sides.
       | 
       | "What about validation??"
       | 
       | Guess what, if users each have their own workspace, isolated and
       | data driven, you don't need to worry about one bad request
       | ruining your whole service.
        
         | urbandw311er wrote:
         | Could you point me to a sample project/source that does this
         | "git-like synchronisation" you describe? At the moment this
         | proposal feels vague.
        
       | moomoo11 wrote:
       | I write all my api code using a business logic "service" layer
       | and a data ops "repository" layer.
       | 
       | The endpoints are by feature not entity, although most of the
       | time they overlap.
       | 
       | This lets me move fast while keeping it simple to build the UI
       | whether it's mobile or web.
        
       | willsmith72 wrote:
       | I totally agree with the general idea, and this is generally how
       | I build backends these days. If there are multiple clients, it's
       | usually even ok for each to have a backend which talks to the
       | "master" backend.
       | 
       | But I will never get on board with sending things like content or
       | UI related stuff from the backend. I've seen too many times,
       | engineers think "all our forms are the same, let's just have the
       | backend send a list of input field names and types like
       | 'address'". It's almost always a bad abstraction, causes pain on
       | the frontend, and restricts the creativity of engineers and
       | designers.
        
         | robcohen wrote:
         | Do you have the same opinion of headless CMS systems like
         | Strapi?
        
         | hakunin wrote:
         | The article doesn't disagree with your second paragraph. It
         | encourages to treat each "page" as a unique snowflake,
         | including forms in it. I should probably do a better job to
         | discourage consistency and standardization of these json
         | structures. This is addressed in another one of my comments if
         | you search for "my bad".
        
       | aabbcc1241 wrote:
       | previous discussion:
       | https://news.ycombinator.com/item?id=28511570
        
         | preommr wrote:
         | Quite surprised at how much people agreed with this post. I
         | personally don't think this is such a good idea - it's not that
         | hard to write a general purpose API that covers 80% of obvious
         | use cases, and have app-specific grouping of endpoints for the
         | remainder. And I include things like rollilng multiple requests
         | into one as part of the obvious use case. Because it's usually
         | very easy to implement - either copy/paste, or 5 lines for more
         | complex solutions like an orm, graphql, etc.
         | 
         | It seems like a terrible idea to couple the backend with the
         | front-end so strongly.
        
           | padjo wrote:
           | Seems like an over correction. Yes trying to make your front
           | end API be your public API is probably a bad idea, but making
           | your front end API completely coupled to the structure of
           | your app structure is probably a bad idea too. Best approach
           | is probably in the middle somewhere.
        
           | isaacremuant wrote:
           | It probably comes from misusing the API route and feeling
           | they want to keep it simple, but instead heavily coupling
           | things.
           | 
           | A motivated BE that wants to be productive avoiding
           | unnecessary work would probably hate being "support for
           | frontend" whenever they decide to change something and a
           | motivated frontend would probably want to turn themselves to
           | full stack powers to not depend on someone else.
           | 
           | It feels really bad as a pattern unless that webapp is your
           | only concern and is constantly moving or something, or if
           | there's no actually FE or BE but just few people maintaining
           | stuff as a side concern (backend for frontend works there).
        
       | projektfu wrote:
       | As a user, this approach often leaves things in a difficult
       | state. The front end works, but automating data access is a hard
       | slog through inconsistent API that's not fully revealed.
       | Reporting is dependent on what is planned for the front end, not
       | what is needed by the user. Because the front and back are
       | tightly coupled, everything is fragile unless it's baked in.
       | 
       | I think many business apps should focus on having an API be a
       | first-class citizen, and there needs to be better standardization
       | in how they're organized and used. GraphQL could be part of that
       | solution. It's also nice when the API lets you do the things you
       | can do from the front end as well as more data-oriented tasks.
       | For example, in Zoho Books, reporting isn't automated by the API,
       | you'd have to roll your own or script the UI. The API should
       | cover both reading and writing data items like transactions and
       | downloading a PDF or Excel report using the reporting interface.
        
       | codingclaws wrote:
       | I read some of the HTMX essays [0] last week due to it being
       | accepted into the GitHub accelerator program.
       | 
       | So, a fully RESTful API must output HTML. I'm not going to go
       | into why but that's what Roy Fielding (the creator of REST),
       | Martin Fowler and the HTMX guy(s) say.
       | 
       | The HTMX guy(s) also say that of course this fully RESTful API
       | that outputs HTML is sometimes bad because you don't want to have
       | to parse data out of HTML. So, the optimal setup is to have both
       | a fully RESTful HTML API and the more common JSON API.
       | 
       | I also think that for the fully RESTful HTML API, it doesn't make
       | sense for the outputted HTML to have any JS.
       | 
       | So, the question I'm pondering at the moment is, is a fully
       | RESTful HTML API simply a website that doesn't use any JS? If so,
       | then the optimal setup is to have an SSR website that doesn't use
       | JS and a JSON API. Of course, under the hood, the website and the
       | JSON API use the same lower level API (eg. SQL queries and back-
       | end functions).
       | 
       | What's crazy for me personally is that this is exactly how I have
       | set up Comment Castles. There's the no JS website [1] and the
       | JSON API [2]. But I didn't build a no JS website because of REST,
       | I just prefer websites that have no front-end JS.
       | 
       | [0] https://htmx.org/essays
       | 
       | [1] https://www.commentcastles.org
       | 
       | [2] https://www.commentcastles.org/api
        
       | theptip wrote:
       | Counterpoint: I did this and it worked out great. We ended up
       | wanting to support direct API access from our customers and we
       | were already in a good place to do so.
       | 
       | YMMV. An observation I have is that really flexible APIs make it
       | easy for the frontend to make small changes, instead of needing
       | to coordinate with backend changes. On the other hand this can
       | lead to maintenance problems down the road as it's hard to
       | control exactly what data/state your system can transition to.
       | 
       | I view this as one of the best pieces of tech debt to take on in
       | an early-stage startup, basically keeping your options open and
       | minimizing short-term friction, at the expense of taking on a bit
       | more cleanup after you find PMF and start to make your backend
       | more robust for the usecase you are scaling.
        
         | Attummm wrote:
         | Engineering is about tradeoffs, everything has its place. But
         | it would it be good standard? How would we look at that api
         | when:
         | 
         | New frontend is needed? Other team/company would like to acces
         | the data?
         | 
         | When we other clients for example anderiod/ios app?
         | 
         | Wouldn't a generic api, with some custom api calls. Ensure that
         | we are more consistent, and require less maintenance in the
         | future.
         | 
         | That way we could focus on adding business value, or solving
         | those hard problems, we normally don't have time for.
        
       | tanepiper wrote:
       | I read this and got to the end, and laughed because that's what
       | we're working on (more a composition tool from different data
       | sources using a headless CMS and a Knowledge Graph) - so in the
       | end we do need a general purpose API since that's part of the
       | USP.
        
       | kburman wrote:
       | Have to disagree with this. API is not always for FE. It can be
       | consumed by other service, or a script. Making generic API helps
       | reuse of common API across web pages. For example notification,
       | user profile.
        
       | caleblloyd wrote:
       | The past 2 years have seen some advancements in full-stack
       | frameworks with streaming components. Such as NextJS with React
       | Server Components or .NET Blazor.
       | 
       | Those would be my preference for an app that doesn't need a
       | public API. If each partial layout and page component does it's
       | own data loading server side, you can skip GraphQL or making a
       | Full Page API and partial update APIs.
       | 
       | Part of the problem with this is organizational though. For the
       | past decade teams have largely been split between
       | frontend/backend who typically work in 2 completely different
       | languages/frameworks. The steaming components approach is a
       | switch back to full stack and a single language/framework. Also
       | every language doesn't have one of these streaming component
       | frameworks, so it's not really possible to do an app completely
       | in Go for example.
        
       | rblatz wrote:
       | This pattern has a name Backend For Frontend (BFF)
       | 
       | https://aws.amazon.com/blogs/mobile/backends-for-frontends-p....
        
       | agentultra wrote:
       | Better, just don't write an HTTP API for your front end. Use a
       | server side framework. Done.
       | 
       | It's a pain coming into a project that was built the way the
       | article recommends. Endpoints become RPC calls instead of
       | resources serving entities. The hodgepodge of "API" calls becomes
       | difficult to scale horizontally due to implied (and never
       | documented) data dependencies. So you miss out on transport layer
       | caching, entity caching, and a host of other goodies.
       | 
       | All because your front end "framework" wants to live in a
       | separate codebase from the server.
        
         | hakunin wrote:
         | The "page" becomes the resource for reads. You get great
         | scalability, because you can use your database in the most
         | efficient way possible to provide entire data for the page. You
         | can maintain 100% back-end clarity on what each page depends on
         | (instead of letting front-end request anything they want in any
         | part of the view).
         | 
         | I personally prefer server-side frameworks. I also understand
         | when a front-end team prefers to work a certain way, has a lot
         | of knowledge and tooling built-up around a certain way, and is
         | worth accommodating for that reason.
        
         | [deleted]
        
       | Toine wrote:
       | The "Controller" part of an API conceptually belongs to the
       | "presentation" layer.
        
       | ricardo81 wrote:
       | It's also an ideal vector for scraping your site-specific data if
       | it's an XHR request, typically an enumerating id or something a
       | sitemap will spell out for more sparse IDs.
        
       | d_watt wrote:
       | I'd caveat that it can be a good idea to make it a general api if
       | you're building a B2B app. These days, purchasing checklists
       | often include "do you have a public api?" Saying no to that can
       | be a sign of product immaturity that is worth trying to get ahead
       | of, and having to maintain internal and external apis is a lot of
       | overhead.
       | 
       | It also can be good as you scale to have an API interface you can
       | have a services team learn how to work with to enable "special"
       | flows for customers.
        
         | runeks wrote:
         | There are clearly reasons for a backend to expose an API; no
         | one is disputing that. The article simply points out that it
         | should not be the default.
        
       | indymike wrote:
       | This article is good advice to get a working prototype or a
       | decent solo-dev MVP website that will be re-written later. I've
       | spent the last two months cleaning up the work of a developer who
       | thought this way. Here's what you run into:
       | 
       | * Front end and back end become conflated. Often times code that
       | should run on the backend runs on the front end and vice versa.
       | Often shortcuts like saving ui state using the same api endpoint
       | you use to save data become complex, and slow down improvements
       | to both the ui and the public API. Likewise data manipulation and
       | in some cases even validation gets done on the wrong end, too.
       | 
       | * You confuse UI code with application functionality. Code used
       | to save the order of columns, stuff you entered the last time a
       | dialog was displayed, and the convenient data structures (i.e.
       | easy, not best) for the front end leak into the back end. So you
       | end up spending a lot of time building back end functionality
       | that has literally no utility to anyone else other than the front
       | end developer.
       | 
       | * You lose focus on your other users: developers who integrate
       | and build on your product. Eventually, those developers become
       | in-house people who are doing integrations and implementations
       | for customers, and a messy API will really slow them down.
       | 
       | Better advice: separate the concerns and have a separate API UI
       | backend. Build exactly what you need to deal with UI state, and
       | component specific UI settings. Your front end team is a perfect
       | proxy for a third party developer for your public API. Take
       | advantage of that. If they can't use it, or they get paper cuts,
       | then paying customers will have problems, too. You'll also be
       | able to on-board developers faster (easier training) and have
       | better documentation.
        
         | zelphirkalt wrote:
         | Do I understand your advice/recommendation correctly?:
         | 
         | frontend <--> UI API, only has what frontend needs <--> backend
         | service with its own API
         | 
         | In that case: What design do you suggest for the backend's
         | actual API?
        
         | ozim wrote:
         | For me back end and front end being conflated is a good thing.
         | Because most of the time it ends up one application anyway.
         | 
         | If you need generic API you can make separate application that
         | will be API.
         | 
         | So if you make domain driven design your front end is separate
         | concern. API for third parties is separate concern.
         | 
         | Still in database you might have stuff not used by external
         | parties but then you don't expose it in your external API. But
         | you can make models on your front end API.
         | 
         | Making "generic" solution might seem like saving time and money
         | but as times go by and it turns out you have to fight with
         | generic API to get things done because one is stuck in his ways
         | - it definitely pays off.
        
         | wruza wrote:
         | I have some experience with it both as a user and a developer.
         | 
         |  _Code used to save the order of columns, stuff you entered the
         | last time a dialog was displayed, and the convenient data
         | structures (i.e. easy, not best) for the front end leak into
         | the back end_
         | 
         | As a user, I want the column order to persist when I'm moving
         | between PCs or browsers or private windows.
         | 
         |  _You lose focus on your other users: developers who integrate
         | and build on your product_
         | 
         | Having done enough integrations, I prefer "what you see is how
         | you work with it" mode. Because requirements usually come in a
         | form of "there's a button on page X, it produces a table, take
         | it". But when you approach it from the API side, this user
         | story appears smeared across complex frontend code with
         | numerous API calls and you basically have to reverse-engineer
         | this part. Includes hours of comparing sparse docs against the
         | network activity tab in the inspector pane. Very tempting to
         | just $.click() the button and rip these <tr>'s out of it.
         | 
         | That said, I don't think you don't need APIs. But your either-
         | or dichotomy is wrong. If you need an API, then build it. But
         | it has nothing to do with how pages work. Because if pages do
         | something clever, and there's value in it, your API users will
         | have to repeat it. Why not push that cleverness back to where
         | it belongs.
         | 
         | And finally,
         | 
         |  _Front end and back end become conflated_
         | 
         | It's a whole system. Drawing an arbitrary line between graphics
         | and logic _not where the boundary between them is_ and
         | repeating it in company's structure - _that_ creates a point of
         | view where they conflate. If you don't do that, there's no
         | conflation. Everyone just does the whole task like "add an
         | input there from this db column", without having to start
         | complex interactions or negotiations. This separation is
         | synthetic.
        
       | ricardobayes wrote:
       | This only works for small projects. Data-heavy frontend usually
       | sends multiple requests to allow async rendering of different
       | parts of a page with different loading times.
       | 
       | This also doesn't work if your design changes a lot. AKA a design
       | change will now mean a backend re-design too.
        
         | rrradical wrote:
         | Your first point is addressed in the article. For the second
         | point, my experience is that the backend probably needs some
         | work in that case anyway. If the backend is well designed, then
         | only the presentation API endpoint needs to change. So a BE
         | engineer is doing the tweaking instead of a FE engineer; not a
         | big deal. Less of a big deal if there's no line drawn between
         | FE and BE engineers.
        
       | smarkov wrote:
       | Based on my personal experience general purpose APIs lead to
       | backends for frontends, which is a colossal footgun unless
       | orchestrated by a mastermind. Even if you did have that kind of
       | mastermind, if that person decides to leave you're left with a
       | very expensive puzzle for everyone else to solve.
       | 
       | Here's my take: don't build general purpose APIs, build general
       | purpose domain actions. A user making an account is a domain
       | action. Sending a notification to the user is a domain action.
       | Make doing each separately easy. Make doing both at the same time
       | easy. Do this with all of your domain actions and now you have an
       | easy way of building exactly the kind of endpoints all your front
       | ends need.
        
         | tootie wrote:
         | Curious about this take, since I've done it successfully many
         | times. Orchestrating a backend for frontend is usually a pretty
         | trivial task. It's usually just mapping one json to another.
        
       | algem wrote:
       | It sounds almost like the author is advocating for a really
       | dumbed down BFF layer (backend for frontend) but what they are
       | missing is behind the bff layer you would have general purpose
       | apis. And if I interpret the article to the extreme what is the
       | difference between this pattern and how html is currently served.
       | Salesforce works sort of similar to what is described and it's a
       | nightmare, these restrictive ideals in my experience just aren't
       | good in practice because they tend to slow down development.
        
       ___________________________________________________________________
       (page generated 2023-08-20 23:01 UTC)