Skip to content

1. Set up starter project with React, Vite & Tailwind

Set up a starter project with React, Vite & Tailwind

Section titled “Set up a starter project with React, Vite & Tailwind”

We have prepared a starter project for you that you can use as a starting point for the tutorial. Download it via the following command:

Terminal window
bunx @livestore/cli@dev create \
--example tutorial-starter livestore-todo-app

Once you’ve downloaded the project, you can navigate to the project directory and install the dependencies:

The project currently is set up as follows:

Run the app with:

Terminal window
bun dev

Here’s the UI you’re going to see after adding a few todos:

Let’s take a quick moment to understand how the app is currently implemented:

All relevant code lives in App.tsx. Here’s a simplified version of it:

interface Todo {
id: number
text: string
}
function App() {
const [todos, setTodos] = useState<Todo[]>([])
const [input, setInput] = useState('')
const addTodo = () => {
const newTodo: Todo = {
id: Date.now(),
text: input
}
setTodos([...todos, newTodo])
setInput('')
}
const deleteTodo = (id: number) => {
setTodos(todos.filter(todo => todo.id !== id))
}
return (
// Render input text field and todo list ...
// ... and invoke `addTodo` and `deleteTodo`
// ... when the buttons are clicked.
)
}

For any React developer, this is a very familiar setup:

App State


todos: Todo[]

UI State


input: string

UI

updates

setTodos

updates

setInput

App State


todos: Todo[]

UI State


input: string

UI

updates

setTodos

updates

setInput

You have two pieces of state:

  • application state: todos: Todo[] → manipulated by the addTodo and deleteTodo functions.
  • UI state: input: string → manipulated when the text in the input field changes.

The “problem” with this code is that the todo items are not persisted, meaning they vanish when:

  • the page is refreshed in the browser.
  • the development server is restarted.

In the next chapters, you’ll learn how to persist the todos in the list, so that they’ll “survive” both actions.

Even more: They will not only persist, they will automatically sync across multiple browsers tabs/windows, and even across devices—without you needing to think about the syncing logic and managing remote state.

That’s the power of LiveStore!