Ready to build something cool on the Internet Computer? Let's create a todo app together. Don't worry if you're new to this - I'll walk you through everything step by step, no fancy jargon required.
Why ICP Is Pretty Cool
Think of Internet Computer like a giant, shared computer that's always online. Instead of running your app on servers owned by big companies, it runs on a network that belongs to everyone. Pretty neat, right? Here's why it's awesome:
- Your app never goes down (unless the internet itself breaks!)
- You don't need to pay for expensive servers
- Users don't pay gas fees like on other blockchains
- It's fast - like, really fast
Getting Started
First, let's get your computer ready. Open your terminal and type:
sh -ci "$(curl -fsSL https://sdk.dfinity.org/install.sh)"
This installs dfx - your new best friend for building ICP apps. Now create your project:
dfx new todo_app
cd todo_app
Building the Brain (Backend)
Let's create the backend first. find a file called src/todo_app_backend/main.mo
and drop in this code:
import Array "mo:base/Array";
actor {
// This is what each todo looks like
type Todo = {
id: Nat;
text: Text;
completed: Bool;
};
// Keep all todos in one place
private var todos: [Todo] = [];
private var nextId: Nat = 0;
// Add a new todo to the list
public func addTodo(text: Text) : async Nat {
let todo: Todo = {
id = nextId;
text = text;
completed = false;
};
todos := Array.append(todos, [todo]);
nextId += 1;
return todo.id;
};
// Get all your todos
public query func getTodos() : async [Todo] {
return todos;
};
// Mark a todo as done (or not done)
public func toggleTodo(id: Nat) : async Bool {
todos := Array.map(todos, func (todo: Todo) : Todo {
if (todo.id == id) {
return {
id = todo.id;
text = todo.text;
completed = not todo.completed;
};
};
todo;
});
return true;
};
// Remove a todo
public func deleteTodo(id: Nat) : async Bool {
todos := Array.filter(todos, func(todo: Todo) : Bool {
todo.id != id
});
return true;
};
}
Making It Pretty (Frontend)
Now for the part you'll actually see! Create src/todo_app_frontend/src/main.jsx
:
import React, { useState, useEffect } from 'react';
import { todo_app_backend } from 'declarations/todo_app_backend';
function App() {
const [todos, setTodos] = useState([]);
const [newTodo, setNewTodo] = useState('');
// Get all todos when the app starts
const loadTodos = async () => {
const result = await todo_app_backend.getTodos();
setTodos(result);
};
// Add a new todo
const handleAdd = async (e) => {
e.preventDefault();
if (!newTodo.trim()) return;
await todo_app_backend.addTodo(newTodo);
setNewTodo('');
loadTodos();
};
// Mark a todo as done/not done
const handleToggle = async (id) => {
await todo_app_backend.toggleTodo(id);
loadTodos();
};
// Delete a todo
const handleDelete = async (id) => {
await todo_app_backend.deleteTodo(id);
loadTodos();
};
useEffect(() => {
loadTodos();
}, []);
return (
<div className="container mx-auto p-4">
<h1 className="text-2xl font-bold mb-4">Todo List</h1>
<form onSubmit={handleAdd} className="mb-4">
<input
type="text"
value={newTodo}
onChange={(e) => setNewTodo(e.target.value)}
className="border p-2 mr-2"
placeholder="Add new todo"
/>
<button type="submit" className="bg-blue-500 text-white px-4 py-2 rounded">
Add
</button>
</form>
<ul>
{todos.map((todo) => (
<li key={todo.id} className="flex items-center mb-2">
<input
type="checkbox"
checked={todo.completed}
onChange={() => handleToggle(todo.id)}
className="mr-2"
/>
<span className={todo.completed ? 'line-through' : ''}>
{todo.text}
</span>
<button
onClick={() => handleDelete(todo.id)}
className="ml-auto text-red-500"
>
Delete
</button>
</li>
))}
</ul>
</div>
);
}
export default App;
Starting It Up
Time to see your app in action! In your terminal:
dfx start --clean --background
dfx deploy
Your app will pop up at http://localhost:4943. Pretty cool, right?
What's Actually Happening Here?
Let's break down what we just built:
-
The Motoko code (backend) is like a super-secure notebook:
- It remembers all your todos
- Gives each todo a unique ID
- Keeps track of what's done and what isn't
- Can add, check off, or delete todos
-
The React code (frontend) is like a friendly interface:
- Shows you all your todos
- Lets you type in new ones
- Has checkboxes to mark things as done
- Includes delete buttons to remove todos
Cool Things You Can Add
Now that you've got the basics working, why not spice it up? You could:
- Add due dates
- Group todos into categories
- Share todos with friends
- Add file attachments
When Things Go Wrong
Don't panic! Here's what to check:
- Is dfx running? (check with
dfx status
) - Did you save all your files?
- Are there any red error messages?
- When in doubt, try
dfx deploy
again
Need Help?
Everyone gets stuck sometimes. Here's where to find help:
- DFINITY's Discord channel
- Stack Overflow (tag: 'internet-computer')
- Internet Computer forums
Remember: every developer started exactly where you are now. Take your time, have fun, and don't be afraid to experiment - that's how we learn!
Top comments (0)