> ## Documentation Index
> Fetch the complete documentation index at: https://docs.basic.tech/llms.txt
> Use this file to discover all available pages before exploring further.

# Full Guide: Build a to-do app

> A step-by-step guide to building a simple to-do app using Basic

In this guide, you will:

1. Set up a new React project with Basic
2. Create a simple To-Do UI
3. Connect to a Basic project and set up your schema
4. Add sign in and sign out functionality
5. Hook up to Basic DB so that your users can save their to-dos across their devices

## Create a new React project

<Steps>
  <Step title="Create a new Vite React project">
    ```bash Terminal theme={null}
    npm create vite@latest my-todo-app -- --template react-ts
    cd my-todo-app
    npm install
    ```
  </Step>

  <Step title="Install Basic and Tailwind">
    ```bash Terminal theme={null}
    npm install @basictech/react
    npm install -D tailwindcss postcss autoprefixer
    npx tailwindcss init -p
    ```
  </Step>

  <Step title="Configure Tailwind">
    Update `tailwind.config.js`:

    ```js tailwind.config.js theme={null}
    /** @type {import('tailwindcss').Config} */
    export default {
      content: [
        "./index.html",
        "./src/**/*.{js,ts,jsx,tsx}",
      ],
      theme: {
        extend: {},
      },
      plugins: [],
    }
    ```

    Replace `src/index.css` with:

    ```css src/index.css theme={null}
    @tailwind base;
    @tailwind components;
    @tailwind utilities;
    ```
  </Step>

  <Step title="Start your dev server">
    ```bash Terminal theme={null}
    npm run dev
    ```

    Navigate to `http://localhost:5173` to see your app running.
  </Step>
</Steps>

## Create a simple To-Do UI

<Steps>
  <Step title="Create the basic layout">
    Replace the code in your `src/App.tsx` file:

    ```tsx src/App.tsx theme={null}
    import './App.css'

    function App() {
      return (
        <div className="flex flex-col items-center p-8">
          <h1 className="text-2xl font-bold mb-4">my lofi to-do app</h1>
          <div className="flex gap-2">
            <input
              type="text"
              placeholder="Add a to-do"
              className="border rounded px-2 py-1"
            />
            <button className="bg-blue-500 text-white px-3 py-1 rounded">
              Add
            </button>
          </div>
        </div>
      )
    }

    export default App
    ```
  </Step>
</Steps>

## Connect to a Basic project

<Steps>
  <Step title="Create a Basic account">
    Go to [admin.basic.tech](https://admin.basic.tech) and create a free account. Then create a new project and copy your Project ID.
  </Step>

  <Step title="Create basic.config.ts">
    Create a `basic.config.ts` file in your project root:

    ```ts basic.config.ts theme={null}
    export const schema = {
      project_id: "YOUR_PROJECT_ID", // Replace with your project ID
      version: 0,
      tables: {
        todos: {
          type: "collection",
          fields: {
            name: {
              type: "string"
            },
            completed: {
              type: "boolean"
            }
          }
        }
      }
    }
    ```
  </Step>

  <Step title="Add BasicProvider to main.tsx">
    Update `src/main.tsx`:

    ```tsx src/main.tsx theme={null}
    import { StrictMode } from 'react'
    import { createRoot } from 'react-dom/client'
    import { BasicProvider } from '@basictech/react'
    import { schema } from '../basic.config'
    import App from './App'
    import './index.css'

    createRoot(document.getElementById('root')!).render(
      <StrictMode>
        <BasicProvider schema={schema}>
          <App />
        </BasicProvider>
      </StrictMode>,
    )
    ```
  </Step>
</Steps>

## Add sign in and sign out functionality

<Steps>
  <Step title="Add auth buttons to App.tsx">
    Update `src/App.tsx`:

    ```tsx src/App.tsx theme={null}
    import { useBasic } from '@basictech/react'
    import './App.css'

    function App() {
      const { signIn, signOut, isSignedIn, user } = useBasic()

      return (
        <div className="flex flex-col items-center p-8">
          <h1 className="text-2xl font-bold mb-4">my lofi to-do app</h1>
          <div className="flex gap-2">
            <input
              type="text"
              placeholder="Add a to-do"
              className="border rounded px-2 py-1"
            />
            <button className="bg-blue-500 text-white px-3 py-1 rounded">
              Add
            </button>
          </div>

          <div className="mt-8">
            {isSignedIn ? (
              <div className="text-center">
                <p>Signed in as: {user?.email}</p>
                <button 
                  onClick={signOut}
                  className="mt-2 text-red-500 hover:underline"
                >
                  Sign Out
                </button>
              </div>
            ) : (
              <button 
                onClick={signIn}
                className="bg-green-500 text-white px-4 py-2 rounded"
              >
                Sign In
              </button>
            )}
          </div>
        </div>
      )
    }

    export default App
    ```
  </Step>
</Steps>

## Hook up to Basic DB

<Steps>
  <Step title="Add task creation">
    Update `src/App.tsx` to add state and the `addTask` function:

    ```tsx src/App.tsx theme={null}
    import { useBasic } from '@basictech/react'
    import { useState } from 'react'
    import './App.css'

    function App() {
      const { signIn, signOut, isSignedIn, user, db } = useBasic()
      const [taskInput, setTaskInput] = useState('')

      const addTask = async () => {
        if (!taskInput.trim()) return
        
        await db.collection('todos').add({
          name: taskInput,
          completed: false
        })
        setTaskInput('')
      }

      return (
        <div className="flex flex-col items-center p-8">
          <h1 className="text-2xl font-bold mb-4">my lofi to-do app</h1>
          <div className="flex gap-2">
            <input
              type="text"
              placeholder="Add a to-do"
              className="border rounded px-2 py-1"
              value={taskInput}
              onChange={(e) => setTaskInput(e.target.value)}
              onKeyDown={(e) => e.key === 'Enter' && addTask()}
            />
            <button 
              className="bg-blue-500 text-white px-3 py-1 rounded"
              onClick={addTask}
            >
              Add
            </button>
          </div>

          <div className="mt-8">
            {isSignedIn ? (
              <div className="text-center">
                <p>Signed in as: {user?.email}</p>
                <button 
                  onClick={signOut}
                  className="mt-2 text-red-500 hover:underline"
                >
                  Sign Out
                </button>
              </div>
            ) : (
              <button 
                onClick={signIn}
                className="bg-green-500 text-white px-4 py-2 rounded"
              >
                Sign In
              </button>
            )}
          </div>
        </div>
      )
    }

    export default App
    ```
  </Step>

  <Step title="Display and delete tasks">
    Add `useQuery` to display tasks and a delete function:

    ```tsx src/App.tsx theme={null}
    import { useBasic, useQuery } from '@basictech/react'
    import { useState } from 'react'
    import './App.css'

    function App() {
      const { signIn, signOut, isSignedIn, user, db } = useBasic()
      const [taskInput, setTaskInput] = useState('')
      
      // Subscribe to all todos - auto-updates when data changes
      const tasks = useQuery(() => db.collection('todos').getAll())

      const addTask = async () => {
        if (!taskInput.trim()) return
        
        await db.collection('todos').add({
          name: taskInput,
          completed: false
        })
        setTaskInput('')
      }

      const deleteTask = async (id: string) => {
        await db.collection('todos').delete(id)
      }

      return (
        <div className="flex flex-col items-center p-8">
          <h1 className="text-2xl font-bold mb-4">my lofi to-do app</h1>
          <div className="flex gap-2">
            <input
              type="text"
              placeholder="Add a to-do"
              className="border rounded px-2 py-1"
              value={taskInput}
              onChange={(e) => setTaskInput(e.target.value)}
              onKeyDown={(e) => e.key === 'Enter' && addTask()}
            />
            <button 
              className="bg-blue-500 text-white px-3 py-1 rounded"
              onClick={addTask}
            >
              Add
            </button>
          </div>

          {/* Task list */}
          <div className="mt-6 w-full max-w-md">
            {tasks?.map((task: any) => (
              <div
                key={task.id}
                className="flex items-center justify-between p-3 border-b"
              >
                <span>{task.name}</span>
                <button
                  onClick={() => deleteTask(task.id)}
                  className="text-red-500 hover:text-red-700"
                >
                  Delete
                </button>
              </div>
            ))}
          </div>

          <div className="mt-8">
            {isSignedIn ? (
              <div className="text-center">
                <p>Signed in as: {user?.email}</p>
                <button 
                  onClick={signOut}
                  className="mt-2 text-red-500 hover:underline"
                >
                  Sign Out
                </button>
              </div>
            ) : (
              <button 
                onClick={signIn}
                className="bg-green-500 text-white px-4 py-2 rounded"
              >
                Sign In
              </button>
            )}
          </div>
        </div>
      )
    }

    export default App
    ```
  </Step>
</Steps>

And that's it! You've built a local-first to-do app that allows your users to sign in and save their to-dos across their devices.

Notice how snappily all the changes are reflected - from task creation to deletion. This is the power of local-first architecture!

## Next steps

* [Database Methods](/sdk-reference/react-db) - Learn about all available database operations
* [React Hooks](/sdk-reference/react-hooks) - Explore all available hooks
* [Schema Guide](/basic-react/react-schema) - Learn how to customize your schema
