Setting up Vite with TypeScript for a Simple To-Do List
In this guide, I'm going to walk you through the steps to set up a Vite project with TypeScript to create a basic to-do list application. We're going to keep it simple and build this without using a framework or library so we can focus on the core functionality of Vite. Project Setup To start, you need to have Node.js and npm installed on your computer. Once you have those, open your terminal and run the following commands to create a new Vite project: # Create a new Vite project npm create vite@latest my-todo-app -- --template vanilla-ts # Navigate into the project directory cd my-todo-app # Install dependencies npm install # Open the project in your code editor code . These commands will set up a new directory called my-todo-app with a basic Vite project that uses TypeScript. The npm create vite@latest command creates the project structure using the vanilla-ts template, which is perfect for our needs. After navigating into the directory and installing the dependencies, you can open the project in your code editor to start working on it. Project Structure After setting up the project, you'll see a structure that looks like this: my-todo-app/ ├── node_modules/ ├── public/ │ └── vite.svg ├── src/ │ ├── main.ts │ └── style.css ├── index.html ├── package.json ├── tsconfig.json ├── vite.config.ts └── package-lock.json This structure includes the necessary files for a Vite project with TypeScript. The src folder contains your main TypeScript file (main.ts), and the public folder holds static assets like the Vite logo. The index.html file is the entry point for your web application, and package.json lists your project's dependencies and scripts. Modifying src/main.ts Next, we need to modify the src/main.ts file to include our to-do list functionality. Replace the existing content with the following code: interface Todo { id: number; text: string; completed: boolean; } let todos: Todo[] = []; let nextTodoId = 1; const todoInput = document.createElement('input'); todoInput.type = 'text'; todoInput.placeholder = 'Enter a new todo'; const addButton = document.createElement('button'); addButton.textContent = 'Add Todo'; const todoList = document.createElement('ul'); document.body.appendChild(todoInput); document.body.appendChild(addButton); document.body.appendChild(todoList); function renderTodos() { todoList.innerHTML = ''; todos.forEach(todo => { const listItem = document.createElement('li'); const checkbox = document.createElement('input'); checkbox.type = 'checkbox'; checkbox.checked = todo.completed; checkbox.addEventListener('change', () => toggleTodo(todo.id)); const label = document.createElement('label'); label.textContent = todo.text; label.style.textDecoration = todo.completed ? 'line-through' : 'none'; const deleteButton = document.createElement('button'); deleteButton.textContent = 'Delete'; deleteButton.addEventListener('click', () => deleteTodo(todo.id)); listItem.appendChild(checkbox); listItem.appendChild(label); listItem.appendChild(deleteButton); todoList.appendChild(listItem); }); } function addTodo() { const text = todoInput.value.trim(); if (text) { const newTodo: Todo = { id: nextTodoId++, text: text, completed: false, }; todos.push(newTodo); todoInput.value = ''; renderTodos(); } } function toggleTodo(id: number) { todos = todos.map(todo => todo.id === id ? { ...todo, completed: !todo.completed } : todo ); renderTodos(); } function deleteTodo(id: number) { todos = todos.filter(todo => todo.id !== id); renderTodos(); } addButton.addEventListener('click', addTodo); renderTodos(); This code sets up a simple to-do list with the ability to add new items, mark them as completed, and delete them. We use TypeScript to define the structure of our to-do items and ensure type safety throughout our code. Modifying index.html Now, we need to update the index.html file to include our TypeScript code. Replace the contents of index.html with the following: Vite + TS To-Do This HTML file serves as the entry point for our application. It includes a script tag that points to our main.ts file, allowing our TypeScript code to run in the browser. Running the Development Server To see your to-do list in action, go back to your terminal and run the following command: npm run dev This command starts the Vite development server, which will bundle your code and make it available at http://localhost:5173. Open this URL in your browser, and you'll see your basic to-do list application up and running. Building the App Once you have made the final changes to the code and are ready to build the app, you can run the following command: npm run build This will create a production build of your application in th
In this guide, I'm going to walk you through the steps to set up a Vite project with TypeScript to create a basic to-do list application. We're going to keep it simple and build this without using a framework or library so we can focus on the core functionality of Vite.
Project Setup
To start, you need to have Node.js and npm installed on your computer. Once you have those, open your terminal and run the following commands to create a new Vite project:
# Create a new Vite project
npm create vite@latest my-todo-app -- --template vanilla-ts
# Navigate into the project directory
cd my-todo-app
# Install dependencies
npm install
# Open the project in your code editor
code .
These commands will set up a new directory called my-todo-app
with a basic Vite project that uses TypeScript. The npm create vite@latest
command creates the project structure using the vanilla-ts
template, which is perfect for our needs. After navigating into the directory and installing the dependencies, you can open the project in your code editor to start working on it.
Project Structure
After setting up the project, you'll see a structure that looks like this:
my-todo-app/
├── node_modules/
├── public/
│ └── vite.svg
├── src/
│ ├── main.ts
│ └── style.css
├── index.html
├── package.json
├── tsconfig.json
├── vite.config.ts
└── package-lock.json
This structure includes the necessary files for a Vite project with TypeScript. The src
folder contains your main TypeScript file (main.ts
), and the public
folder holds static assets like the Vite logo. The index.html
file is the entry point for your web application, and package.json
lists your project's dependencies and scripts.
Modifying src/main.ts
Next, we need to modify the src/main.ts
file to include our to-do list functionality. Replace the existing content with the following code:
interface Todo {
id: number;
text: string;
completed: boolean;
}
let todos: Todo[] = [];
let nextTodoId = 1;
const todoInput = document.createElement('input');
todoInput.type = 'text';
todoInput.placeholder = 'Enter a new todo';
const addButton = document.createElement('button');
addButton.textContent = 'Add Todo';
const todoList = document.createElement('ul');
document.body.appendChild(todoInput);
document.body.appendChild(addButton);
document.body.appendChild(todoList);
function renderTodos() {
todoList.innerHTML = '';
todos.forEach(todo => {
const listItem = document.createElement('li');
const checkbox = document.createElement('input');
checkbox.type = 'checkbox';
checkbox.checked = todo.completed;
checkbox.addEventListener('change', () => toggleTodo(todo.id));
const label = document.createElement('label');
label.textContent = todo.text;
label.style.textDecoration = todo.completed ? 'line-through' : 'none';
const deleteButton = document.createElement('button');
deleteButton.textContent = 'Delete';
deleteButton.addEventListener('click', () => deleteTodo(todo.id));
listItem.appendChild(checkbox);
listItem.appendChild(label);
listItem.appendChild(deleteButton);
todoList.appendChild(listItem);
});
}
function addTodo() {
const text = todoInput.value.trim();
if (text) {
const newTodo: Todo = {
id: nextTodoId++,
text: text,
completed: false,
};
todos.push(newTodo);
todoInput.value = '';
renderTodos();
}
}
function toggleTodo(id: number) {
todos = todos.map(todo =>
todo.id === id ? { ...todo, completed: !todo.completed } : todo
);
renderTodos();
}
function deleteTodo(id: number) {
todos = todos.filter(todo => todo.id !== id);
renderTodos();
}
addButton.addEventListener('click', addTodo);
renderTodos();
This code sets up a simple to-do list with the ability to add new items, mark them as completed, and delete them. We use TypeScript to define the structure of our to-do items and ensure type safety throughout our code.
Modifying index.html
Now, we need to update the index.html
file to include our TypeScript code. Replace the contents of index.html
with the following:
lang="en">
charset="UTF-8" />
rel="icon" type="image/svg+xml" href="/vite.svg" />
name="viewport" content="width=device-width, initial-scale=1.0" />
Vite + TS To-Do
id="app">
This HTML file serves as the entry point for our application. It includes a script tag that points to our main.ts
file, allowing our TypeScript code to run in the browser.
Running the Development Server
To see your to-do list in action, go back to your terminal and run the following command:
npm run dev
This command starts the Vite development server, which will bundle your code and make it available at http://localhost:5173
. Open this URL in your browser, and you'll see your basic to-do list application up and running.
Building the App
Once you have made the final changes to the code and are ready to build the app, you can run the following command:
npm run build
This will create a production build of your application in the dist
folder where all the files will be bundled and ready to be served to your users.
Final Thoughts
As you can see, it's very easy to set up Vite with a simple TypeScript project and get a lot of functionality out of the box. Vite takes care of the bundling, so you don't need to worry about setting up a complex build pipeline yourself. Of course, we can take this a lot further by adding a UI framework like React, Vue and other libraries like TailwindCSS for styling and more.