/Projects/

Todo app

A simple fullstack app to experiment with optimistic updates and microinteractions

Skills: #typescript#react#react-query#trpc#vitejs#tailwind#react-router#prisma#sql#supabase#storybook#github-actions#vitest#cypress

I used this small app to experiment with some of the tools in the react.js ecosystem.

The app is deployed using vercel, that allows to easily deploy and scale jamstack apps using serverless functions

It consists in a simple database-persisted todo app with register/login functionality

Screenshot of the login screen
The input fields take care of both the validation and the visual hints for an accessible navigation
Async validation is also handled
Creation of new tasks
A subtle microinteraction helps checking completed tasks

Optimistic updates

Optimistic updates is a way to refer to the UX pattern in which the app performs the success action before actually receiving information back from the server. It's a notoriously tricky pattern to implement, as the frontend has to partially reimplement the backend's logic. In addition to that, the frontend has to handle many edge cases such as handling the errors after the client showed a confermation feedback, or taking care of race conditions with some combinations of fast user actions. While it is possibile to implement manually all of this, a pragmatic solution is to use libraries such as react query, that take care of all the logic that is not app-specific.

Continuos integration

Using a combination of vercel and github actions, it's possible to implement a CI/CD pipeline that performs automated checks before deploying. In order to merge the code to the main branch (so that vercel deploys to the production environment) the following checks are performed:

The tests are designed using the so-called test pyramid in mind:

  • unit tests against simple units of code
  • integrations tests to check that different units of code work within each other
  • e2e tests to check the actual behaviour of the whole app

Each kind of test has its own tradeoffs: the more you go up in the testing pyramid, the more powerful and abstract the test is (so that even if the internal behaviour changes, the high-level, e2e specification should remain valid). On the other hand, e2e tests tend to be extremely fleaky, complex to write and mantain, take more time to execute, and don't always provide a clear answer of what is actually broken when the test is red.

Backend

The backend is realized using serverless functions and persisting the state via a supabase remote sql database.

Prisma is used as ORM for the great developer experience it offers. Some of its greatest features are:

  • Ergonomic, type safe, easy to use typescript client
  • A tool to visualize the sql table called prisma studio
  • Developer tools to help generate, prototype and apply migrations
  • A custom DSL to define the schema, that looks like the following:
model Todo {
  id        Int      @id @default(autoincrement())
  text      String
  completed Boolean
  createdAt DateTime @default(now())
  User      User     @relation(fields: [userId], references: [id])
  userId    Int
}

model User {
  id             Int    @id @default(autoincrement())
  username       String @unique
  hashedPassword String
  todos Todo[]
}