---
# System prepended metadata

title: PSE Recommended Stacks

---

# PSE Recommended Stacks

On the PSE team we have lots of projects being built in parallel by different people. Ideally people can contribute to any project with minimal learning overhead. The goal of this document is to set communicate 

Good software is built by craftspeople. Good software is custom written to fit the requirements of the product. Good craftspeople find a balance between building and re-use that maximizes the quality of the product.

Using pre-built packages is a good way to abstract away what is happening. This is okay, but it's important to _understand_ what is happening internally. Using nothing but pre-built packages leads to less informed engineers (and less stable/predictable products).

## Static frontend

A static frontend website consists of a single repository with business logic limited to user interface management (e.g. dark/light mode, layout changes, etc). The website may use local storage or cookies to persist user state.

Core dependencies:
- React - for user interface
- mobx - for state management
  - mobx-react-lite - for use with react

Hosting:
- Cloudflare workers

Using this system we can build single page apps with SSR. We can avoid page flashes and customize the response by using cookies in the SSR script (see next section).

Note that Typescript is _not_ recommended. A static frontend website should have minimal business logic. The complexity of a Typescript build system should offer minimal value if stores and components are well designed.

CSS classes should be defined on a per-component basis. If a CSS class is used in **3** or more different components only then should it be moved to a shared CSS file. Rewriting CSS styles is acceptable if it makes the code more readable. Huge global CSS files should be **avoided**.

### State management

To hydrate the state we can inline a global variable `window.STATE` in the http response during SSR. On the client this variable is synchronously loaded into the stores on first render. State hydration should always be _optional_. e.g. the app should work if `window.STATE === undefined`. See an example [here](https://github.com/vimwitch/zerocompress_web/blob/main/worker/index.js#L55).

A good pattern for managing mobx state looks like the following. Note that we have multiple logical stores, each with access to the other. Component files only need to import the single root state file. Then they can deconstruct the individual stores from the root.

```js
import { createContext } from 'react'

// Individual stores are in their own files
import Interface from './interface'
import User from './User'
import Auth from './Auth'
import Message from './Message'

const state = {}

const ui = new Interface(state)
const user = new User(state)
const msg = new Message(state)
const auth = new Auth(state)

Object.assign(state, {
  ui,
  user,
  msg,
  auth,
})

export default createContext(state)
```

In a component:

```jsx
import React from 'react'
import { observer } from 'mobx-react-lite'
import state from '../contexts/state'

export default observer(() => {
    const { ui, user, msg, auth } = state
    return (
        <div style={{ background: ui.color }}>
            Hello!
        </div>
    )
})

```

[^ source](https://github.com/Unirep/zketh/blob/main/packages/frontend/src/contexts/state.js)

# Rationale

Engineers may not be comfortable with the technologies or patterns described above. This is okay! We want to build not just products, but also _good craftspeople_. This means thinking critically about the stack and how it's working. Writing custom CSS while keeping the codebase clean. Using cookies to change 10px element midway down the page based on what the user selected.

Building should be a learning experience, not just an exercise of knowledge.

## Cloudflare vs Vercel

Vercel suffers from "cold starts". If a website hasn't been accessed recently it may take more than 1 second to begin loading. This is because Vercel executes code inside of a _virtual machine_, which must boot up. 

Cloudflare offers a service called workers, which allows us to execute Javascript code in response to an http request. Cloudflare workers execute inside of _v8 isolates_. As a result Cloudflare workers do not have "cold start" times in any case.

Cloudflare workers also adhere to the the [webworker](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers) specification and are [open source](https://github.com/cloudflare/workerd) - an ethos I feel we should support.

Note that in the Cloudflare dashboard you can disable DDOS protection, and thus captchas for e.g. Tor users.