Congratulations!

Congratulations, your habit tracker works, and you've reached the end of the Vue course! The app loads its suggestions from a file, lets you check habits off, add your own and remove them, filters the list, shows your progress and your streak, and remembers all of it. And you built it yourself, piece by piece.

One last improvement. A streak can break, but your best one shouldn't be forgotten. Save it with the composable under the key "best", and in finishDay(), once the streak has changed, raise the best when the streak is longer:

const best = useLocalStorage("best", 0);
if (streak.value > best.value) {
    best.value = streak.value;
}

What you've learned. Look at how the whole course found its place in your app:

  • Components: App.vue holds the data, and HabitItem.vue shows one habit. Props bring the data down (:habit="habit"), and events go up (emit('toggle', habit.id) and @toggle="toggle").
  • The template: {{ }} shows values, :class crosses out a habit that's done, and :style sets the width of the bar.
  • State: refs hold what changes, with .value in the script and without it in the template, and whenever they change, Vue updates the page by itself.
  • Conditions and lists: v-if, v-else-if and v-else choose between loading, an error and the app, and v-for with :key shows the habits.
  • Forms: v-model with .trim, @submit.prevent and an error message.
  • Computed values: the count, the percentage, allDone and the filtered list, recomputed whenever the habits change.
  • The lifecycle: onMounted loads the habits with fetch() once the app is on the page.
  • Watchers and composables: useLocalStorage saves any value with watch, so three lines save three values.

The app has no slots, but you know them too: with them, a component such as the panel from the lesson Slots, or the lightbox of the photo gallery, takes whole pieces of the page from its parent.

Vue on your own computer. Here, our site prepares your files every time you click Run. On your own computer, a tool called Vite does that, and create-vue, Vue's official tool for starting a project, sets it all up for you. You need Node.js (take the LTS version), which comes with npm, a program for installing packages, and the terminal (the command line). In the terminal, go to the folder where you want your projects, and run:

npm create vue@latest

create-vue asks a few questions: first the project's name, such as habit-tracker, which also becomes the name of its folder, and then what to add to the project, such as TypeScript, Vue Router or Pinia. You don't need any of them yet, so don't choose any. If it asks anything else, keep the suggested answer. At the end, it shows the next commands:

cd habit-tracker
npm install
npm run dev

cd goes into the project's folder, npm install downloads Vue, Vite and everything else the project needs (into the folder node_modules), and npm run dev starts Vite. It shows an address such as http://localhost:5173/: open it in your browser. Leave the terminal running: whenever you save a file, the page in the browser updates by itself. Ctrl+C in the terminal stops it.

The project's files. They're the files of the exercises, just in folders:

  • index.html is in the project's main folder and has the same <div id="app">. Its script loads /src/main.js.
  • src/main.js mounts App with createApp(App).mount("#app"), just like your main.js.
  • src/App.vue is the main component. In a new project, it holds an example: replace it with yours.
  • src/components/ is for the other components, such as HabitItem.vue (if the folder isn't there, create it). The import in App.vue then becomes import HabitItem from "./components/HabitItem.vue";. You can delete the example components in the folder.
  • public/ is for files that the page loads as they are. Put habits.json there, and fetch("habits.json") finds it.

Put useLocalStorage.js into src, next to App.vue, and its import stays as it is. (Bigger projects often keep their composables in a folder of their own, src/composables.) Your style.css goes into src too, and src/main.js imports it with import "./style.css";, in place of the example's stylesheet if it has one.

The Vue DevTools. Add the Vue DevTools extension to your browser (for Chrome, Edge and Firefox; devtools.vuejs.org explains how). The developer tools (F12) then get a Vue tab, which shows your components as a tree, with their props and their state. You can even change a ref there and watch the page change. It works on pages that run with npm run dev.

Putting it online. When your app is ready, npm run build prepares it for the internet: Vite puts the finished files into the folder dist, with all the .vue files turned into plain JavaScript that any browser understands. npm run preview shows you the finished version on your own computer. Then the dist folder goes on a web server. The quickest way is Netlify Drop (app.netlify.com/drop): drag the dist folder onto the page, and you get an address you can send to anyone (to keep the site online, sign up for a free account). Services such as Netlify and Vercel can also build and publish a project by themselves, every time you change its code on GitHub, a website for keeping code.

What's next? You now know the core of Vue: the same components, refs and computed values are in every Vue app, small or big. These come next:

  • Vue Router, for apps with several pages, each with an address of its own, such as / and /stats. Each page is a component.
  • Pinia, for state that many components share, such as the café's order. It's like the module order.js from the lesson Composables, with more tools and with support in the DevTools.
  • TypeScript: with <script setup lang="ts">, you write down the types of your props and refs, and the editor finds many mistakes before you even run the app. The TypeScript course teaches it.
  • Nuxt, a framework built on Vue for whole websites. It makes a page from each file in its pages folder, it can render the pages on the server, so that visitors and search engines get finished HTML right away, and its server routes let your own code on the server answer the page's fetch().

In older tutorials, you'll meet the Options API from the first lesson again: components written with export default { data() { … }, methods: { … } } instead of <script setup>. Underneath, it's the same Vue, so with what you know, you'll understand it quickly. The documentation at vuejs.org explains everything you've met here, in both styles.

Instructions

  1. Add best with the composable, raise it in finishDay() as above, and show it under the streak: <p>Best: {{ best }}</p>. Finish two days in a row with all the habits checked off: Best: 2. Then finish a day with nothing done: the streak is back at 0, and the best stays at 2.