I've been thinking about the "spectrum of customizability" and its relationship to upgradeability. Also its relationship to the framework vs product distinction.

The Spectrum of customizability

In using an application how much customizability do you want? This is the spectrum of customizability:

   o--------------------------------------------o
very little                                  lots of
customizability                           customizability

Famously, Henry Ford is supposed to have said about the model T: "You can any color you want as long as its black". That's zero customizability. Today most cars have much a whole bunch of options for configuration.

Software is even easier to adapt so most standard applications we are familiar with have a whole bunch of options. Take a word processor like Microsoft Word or Google Docs. Just to start with I can configure the font, its size, its color etc. Note this doesn't have to be true of all writing applications: some make a feature of their lack of options like iA Writer - the idea being that focuses you on the writing!

At the extreme end of the customizability spectrum for software is raw code: with raw code I can do anything I want. There's another famous story about Steve Jobs: his coding team on the Mac got so fed up with him asking for tweaks to the screen layout they created a custom app so he could edit it himself without having to code! This illustrates the point: at the code level you can change anything.

Frameworks and Products

At this point I want to introduce some definitions: products and frameworks.

Products are applications where customization (configuration) is done via a specially design interface – for example, the preferences menu or the font choice toolbar.

Frameworks are used to scaffold and power an application which is then "finished" manually.

NB: of course, with an open-source product anyone who wants can customize the application by digging into the code – that's one of its big advantages. However, that isn't the primary way an ordinary user is intended to configure

customizability
  o----------------------------------------------------------o
 low |    ~~~~~~~                   ~~~~~~~~             |  high
     |       |                          |                |
     |    products                  frameworks           |
     |                                                   |
  product with no options                              raw code

Products have clear advantages: they can be mass-produced, they are easier to use etc. But they have limited customizeability

A Framework is half-way house of sorts or a meta-product: it's a product for rapidly building custom products.

Example: applications for building websites i.e. web applications and content management systems

This is an interesting area because you have a spectrum of options ranging from products to frameworks to pure code.

Frameworks

Framework examples: rails, flask, nextjs etc. What they consist of is:

  • Some core libraries (which can be upgraded)
  • app scaffolding (more painful to upgrade)
  • patterns and documentation

Products

Examples:

  • Webflow
  • Squarespace
  • wix

Hybrids

Hybrids are things like wordpress or drupal. They are half-framework, half-product. The core is pretty standard and you don't edit but there is a ton of plugins and themeing going on and you don't scaffold an app at the start - you install and start editing content like webflow.

Analogy with cars

Cars are definitely a classic product: you have a standard setup with some configuration options. Most people aren't building or customizing their cars (though they did so at beginning of cars). This is because the cost of customization is very high plus people's tastes/needs are reasonably similar.

But imagine people wanted to create all kinds of different cars, or even more analogously to create lots of different car factories to create different kind of cars. Then we want a car-building framework: we can then build any car we want and tweak it ourselves. concretely it would be a bit like a standard kit with standard parts that you could then compose together yourself in custom ways. At the simplest level maybe there are range of frames, a range of engines and then you can buy your paint from someone else entirely and then put it together to make your own car.

Info

One potential confusion is that a framework can be a "product" in the sense of a defined thing that you buy. For example, people talk about frameworks like Ruby on Rails or Django or ExpressJS being a product.

If customizability is good why don't we all prefer raw code?

Because raw code can only be edited by specialists i.e. coders, and not just any coder but coders familiar with that application. Such specialists are usually both expensive and rare. Plus a user has to be able to communicate to the specialist what they want.

Of course, if you are a coder – especially a coder with knowledge of that domain – then raw code may be very attractive. This explains, why so many developer tools are open source: as the users are coders the users can directly alter and improve them – and share what they've done with others.

The more you want to be able to customize the more you want to use a framework

From what we have said above it's clear that the more customizability you want, the more you want a framework.

So what's the downside?

Of course, frameworks do require some coder knowledge. But let's leave that aside for now – assume the target audience is technically sophisticated – people creating technical documentation for example. What other downsides are there?

The big downside is what we could upgrade-ability …

Customize-ability and Upgrade-ability and their trade-off

Let's take one example related to our situation in projects/FlowerShow: configuring theme colors.

We are using tailwind. Thus, it makes sense to use tailwind existing config system e.g. https://tailwindcss.com/docs/customizing-colors and especially https://tailwindcss.com/docs/customizing-colors#naming-your-colors (ie. using named colors like primary in the design and then allowing user to change the value for primary).

However, if we let users edit tailwind.config.js then what happens if the core app (Flowershow) wants to edit tailwind.config.js, for example to support a new version of tailwind? Now there is potentially a conflict that requires manual intervention.

The alternative is to define a specific subset of tailwind config that users can edit and expose that explicitly and separately in the Flowershow config. In its essence this is creating a clear interface between user domain and the app domain. It has obvious benefits in separating concerns. However, its cost is twofold. First, the app must now mirror any user-relevant changes down into the user config. Second, there is a limitation on what the user can do - only those things explicitly exposed are now available.

What this implies is there is a trade-off between customize-ability (power) and upgrade-ability. Total customize-ability is editing of anything! But that also means that almost nothing is automatically upgradeable.

Whilst there may be a trade-off what is the efficient frontier here and are there ways to move that efficient frontier?

Excalidraw/customizability-vs-upgradeability-efficient-frontier-2022-06-26

For example. Suppose we create the scaffolded app via a git clone of a template then it may be easier to track what user changes have been made – crudely git pull will fail when there are conflicts and the user will have some visibility into what they have to resolve manually.

NB: a problem for the git approach is in initial app creation: i am limited to one or a few specific templates. A code or cli based approach may allow much more variety via composition of different features into a working app.

Emerging dimensions

  • Customizability: how much can i customize my app (once created)
    • Create-ability: how much can i customize the creation of the app. Note this is really a subset of customizability and is identical in many situations e.g. a wordpress install. However, for many static site generators these are quite distinct and most of the customization opportunity is at this stage.
  • Upgradeability: how easy is it to upgrade my app to use a new version of the framework/product
  • Complexity: how complex is it for developers to build the framework/product and/or for users to use or customize it?

The ultimate question is where is the sweet-spot (for us)?

One the hand you can just ship a customized nextjs template and let's users have at it.

The major issue with that is that once users start modifying, upgrading is manual and often painful.

On the other end of the spectrum you keep the nextjs app template (or whatever it is) very private, creating a very clean separation of content and config. This makes it relatively easy to upgrade but potentially greatly limits what a user can do.

IMO our sweet spot lies more towards the latter for a few reasons:

  • There is already lot in the first category – and its close to plain nextjs
  • The lack of upgradeability is a major issue (and even if createability). cf e.g. notes/tailwind-nextjs-starter-blog
    • This upgrade-ability is especially an issue if the core product or its underlying components are rapidly developing (as is often the case here i.e. nextjs, tailwind etc)
  • There is a major set of users who want something they don't have to worry about maintaining (including me!). This is especially true if you want a product that can have a cloud option (and is ultimately financially sustainable ie. that users pay for)

The question is where exactly and how do we implement it.

Appendix: todos

Walk through ways to gain customizability whilst keeping product-like upgradeability:

  • Settings and options
  • Plugins (allow coding but in a controlled, cleanly separated way)
    • But not easy cf nextjs plugins etc