Quick Start
Let's build a simple todo app to see Cuppa in action!
Step 1: Create the Project
mkdir cuppa-todo
cd cuppa-todo
pnpm init -y
pnpm add @mycuppa/core @mycuppa/ui @mycuppa/router react react-dom
pnpm add -D typescript vite @vitejs/plugin-react
Step 2: Configure Vite
Create vite.config.ts:
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
export default defineConfig({
plugins: [react()],
})
Step 3: Create the Todo App
Create src/App.tsx:
import { useState } from 'react'
import { Button, Container } from '@mycuppa/ui'
import { generateId } from '@mycuppa/core'
interface Todo {
id: string
text: string
completed: boolean
}
export function App() {
const [todos, setTodos] = useState<Todo[]>([])
const [input, setInput] = useState('')
const addTodo = () => {
if (input.trim()) {
setTodos([
...todos,
{ id: generateId('todo'), text: input, completed: false },
])
setInput('')
}
}
const toggleTodo = (id: string) => {
setTodos(
todos.map((todo) =>
todo.id === id ? { ...todo, completed: !todo.completed } : todo
)
)
}
return (
<Container maxWidth="medium" padding centered>
<h1>Cuppa Todo</h1>
<div>
<input
type="text"
value={input}
onChange={(e) => setInput(e.target.value)}
onKeyPress={(e) => e.key === 'Enter' && addTodo()}
placeholder="What needs to be done?"
/>
<Button onClick={addTodo} variant="primary">
Add
</Button>
</div>
<ul>
{todos.map((todo) => (
<li key={todo.id} onClick={() => toggleTodo(todo.id)}>
<span
style={{
textDecoration: todo.completed ? 'line-through' : 'none',
}}
>
{todo.text}
</span>
</li>
))}
</ul>
</Container>
)
}
Step 4: Run the App
Add scripts to package.json:
{
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview"
}
}
Run the development server:
pnpm dev
What's Next?
You've just built your first Cuppa app! Here are some ideas to extend it:
- Add data persistence with
@mycuppa/data - Add routing with
@mycuppa/router - Add authentication with
@mycuppa/auth - Style it with Tailwind CSS
Check out the full documentation to learn more!