DEV Community

Cover image for Setting up Vite with TypeScript for a Simple To-Do List
Shayan
Shayan

Posted on

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 .
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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) return;
  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();
Enter fullscreen mode Exit fullscreen mode

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:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <link rel="icon" type="image/svg+xml" href="/vite.svg" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Vite + TS To-Do</title>
  </head>
  <body>
    <div id="app"></div>
    <script type="module" src="/src/main.ts"></script>
  </body>
</html>
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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.

Top comments (9)

Collapse
 
code42cate profile image
Jonas Scholz

What do the cool kids use these days besides vite?

Collapse
 
shayy profile image
Shayan

Honestly Vite is amazing! haha

Collapse
 
thecodingthesi profile image
Thesi

why no early return here?

if (text) return;
const newTodo: Todo = {
  id: nextTodoId++,
  text: text,
  completed: false,
};
todos.push(newTodo);
todoInput.value = '';
renderTodos();

Enter fullscreen mode Exit fullscreen mode
Thread Thread
 
shayy profile image
Shayan

That's a good catch! I also prefer guard statements over nested ifs but this one slipped my mind. I'll update the post now.

Thread Thread
 
adam_winick_42d3f9c0e7bd1 profile image
Adam Winick

Yeah your update was correct but the suggestion is not: you caught that it should be

// if there's no text, return.
if(!text) return;
Enter fullscreen mode Exit fullscreen mode

but also, you can shorthand the text property assignment

const newTodo: Todo = {
  id: nextTodoId++,
  text
  completed: false,
};
Enter fullscreen mode Exit fullscreen mode
Thread Thread
 
thecodingthesi profile image
Thesi

whoopsie, that was a typo. Thanks for correcting!

Thread Thread
 
adam_winick_42d3f9c0e7bd1 profile image
Adam Winick • Edited

You're very welcome, I love that you used Vanilla DOM for this! Big ups!

Collapse
 
firacode profile image
Firacode

This guide walks you through setting up a simple to-do list application using Vite and TypeScript. You'll first create a new Vite project with the vanilla-ts template and install the necessary dependencies. The project structure includes essential files like main.ts, index.html, and tsconfig.json. You'll modify main.ts to implement the to-do list functionality, such as adding, marking as completed, and deleting items, with type safety ensured by TypeScript. The index.html file is updated to link to the TypeScript code, and running npm run dev will start the Vite development server. Finally, npm run build will bundle your app for production.

Collapse
 
thomas_baseline profile image
Thomas Nixon

Nice article with a great step by step!

If you are looking for something already set up with Vite and Typescript, including hooking it up to the backend, check out the open-source serverless first fullstack framework ⚡️ Baseline ⚡️ github.com/Baseline-JS/core