Sticky architecture

What is Sticky?

Sticky allows anyone to make branded physical↔digital apps without writing any code. Our tech already improves convenience and productivity in hospitality, fitness, construction and discovery - and we're just getting started.

People interact with our premium branded stickers without having to download an app or sign up for anything. We make and distribute the stickers so we own the experience end-to-end.

What are no-code and low-code?

Sticky is both no-code and low-code. What's the difference?

No-code is the ability for knowledge workers (but not developers) to build things without knowing how to write software. The no-code space is taking off because the ratio of knowledge workers to developers is 10:1; in other words, there aren't enough developers in the world to develop all the things the world will need. Many problems have little enough complexity that they can be solved without writing code, but too much complexity that they can be solved in Excel. Sticky is a no-code platform because you can build ecommerce, check in and fitness flows as a knowledge worker, but not a developer. No-code is often described as a movement to democratize the creation of software: the idea that anyone can solve problems without needing a Computer Science degree or years of experience. Squarespace is a great example because it allows non-technical people to build websites.

Low-code is the ability for developers to build things without having deep knowledge of a language or problem space. Instead of writing thousands of lines of code to build a library of components like text boxes or checkboxes, a low-code platform would make it easy to show and manipuate these prebuilt components with just a few lines of code instead. Sticky is also a low-code platform because you can build discovery flows (and infinite other flows - anything you can imagine!) with minimal coding effort - often just a few lines of JavaScript. Stripe is a great example because whilst developers have to write code to integrate Stripe payments, their work is minimal (a few dozen lines of code) instead of deep (thousands of lines of code to integrate with every card processor in every country in the world).

Layers

There are three layers that matter. Splitting Sticky into these three layers is important because it's our vision that anyone can make products as good as ours. Anyone could build a dashboard better than ours, for example, using our SDK. In fact, they could build a better SDK with the API alone!

Dashboard

Sticky dashboard

Our dashboard is a simple and attractive web-based interface for doing everything Sticky, from editing low-code apps in our code editor to setting up products you want to sell. Most customers can do everything they need with the dashboard, and most of them use it daily to access reporting or see their payments. The dashboard is really just a nice interface that runs the right SDK functions at the right time, and displays what those functions do. For example, your apps in the dashboard are shown by running `applications.getAll()` once, and displaying the result in a list.

SDK

Our SDK is a frontend JavaScript library that allows you to build the low-code apps we're famous for. The dashboard uses it too. It provides simple functions like `applications.get()` to get the current app, or `Stickypay.pay()` to trigger Apple Pay on iOS and Google Pay on Android. Most functions are nice wrappers for our API; for example, `applications.get('123')` is really just a convenient way of making an API call to `GET /v1/applications/123`.

API

Our API is a restful HTTP API that works exactly like you'd expect an API to work. You can create products through `POST /v1/products` and you can delete a product through `DELETE /v1/products/123`. It always takes JSON and usually returns JSON, unless you tell it not to.

Sticky is event driven

Sticky is based upon an "event driven" architecture, which means it cares more about events over time than fixed state, which can be out of date and cause bugs.

Events are things that happen over time like updating an app (APPLICATION_UPDATE) or a consumer checking in (CHECK_IN). You can create create your own custom events with SESSION_CUSTOM_EVENT, for example for logging someone's BMI, which Sticky doesn't have a specific event for.

You can calculate state by "walking over" a set of events. For example, if the first event is "add 3 apples to my cart" and the second event is "remove 1 apple from my cart", then you can be sure there are 2 apples in the cart, without storing the number of apples in a record somewhere.

Another example is with BMI. Instead of storing the BMI in a user record, create an event whenever the BMI changes. To know the most recent BMI, pull it from the most recent event. You now have a timestamped 'audit log' of every BMI change, making it trivial to show progress over time.

This is very useful because it avoids storing state (like the BMI in a user record). State is bad because if two functions try to change state at nearly exactly the same time, one function's state will be overwritten by the other's (there can be just one state at any given time). It's also useful because you can go back in time: you can easily reproduce a bug by 'slicing' a set of events between two timestamps. On the other hand, reproducing different states manually is frustrating.

What happens when someone taps a sticker?

The two most important parts of Sticky are apps and stickers. The relationship between apps and stickers is one-to-many, meaning you can create one app and connect multiple stickers to it, so each sticker does the same thing. This avoids applying the same 'code' to stickers one by one, and makes updating your stickers trivial. Each sticker is still uniquely identifiable. That means that even though every sticker in a hospitality deployment shows and does the same thing, the bar staff know exactly which table ordered, and the consumer doesn't have to choose where they're sitting from a big list of tables.

Each sticker being uniquely identifiable means it has a unique ID written to it in the form of a URL (sticky.to/unique-id) which the phone 'visits' when tapping. This 'visit' is actually a request to our API. Our API looks up the sticker by its unique ID, then looks up the app it's connected to. It takes the code of the app and runs it to determine where to redirect the phone to, or, it can simply serve frontend code that the phone renders immediately without redirecting. In the process of doing all that, the API creates a 'tap' event for debugging and analytics. You can see individual taps in the dashboard because the dashboard shows every event that was created for every sticker.

The anatomy of a typical Sticky app

Most people write Sticky apps using the React JavaScript framework and our SDK.

They use React because it's the easiest and quickest way to build modern JavaScript apps. The barrier to entry on learning React is low, and the 'React way of thinking' means that React apps tend to be higher quality without having to try.

They use our SDK because it's easier than making calls to our API by hand. For example, the SDK takes care of authentication and handles errors gracefully. It's easy to call the SDK functions from React to get the data you need.

Let's say someone wanted to build a simple React app that lists stickers when someone clicks a button.

They would:

  • Import the SDK with a simple <script> tag
  • Render a HTML <button> with a click handler function
  • In the click handler function, run the SDK function const stickers = await sticky.stickers.getAll(), then run this.setState({ stickers })
  • Render a HTML <ul> (unordered list) tag which maps this.state.stickers to <li> (list item) tags.