Build a Multi-Tab Todos App in Script Kit

John Lindquist
InstructorJohn Lindquist
Share this video with your friends

Social Share Links

Send Tweet
Published 3 years ago
Updated 2 years ago

Create, read, update, delete. Four actions that every developer becomes intimately familiar with over their career. Script Kit aims to make this process as pleasant as possible using a db helper and what better way to show it off than a Todos app?

You will also learn how to create and switch between tabs through Script Kit's onTab and setTab methods.

Install todos

// Name: Todos

import "@johnlindquist/kit"

let { todos, write } = await db({ todos: [] })

onTab("Todos", async () => {
  while (true) {
    let todo = await arg("Toggle todo:", todos)
    let t = _.find(todos, todo)
    t.tag = t.tag === "open" ? "done" : "open"
    await write()

onTab("New", async () => {
  let name = await arg("New todo:")
  todos.push({ name, id: uuid(), tag: "open" })
  await write()

onTab("Remove", async () => {
  let todo = await arg("Remove todo:", todos)
  _.remove(todos, todo)
  await write()

Instructor: [0:00] We'll start by using the database helper and pass in an initial data set. Just an object with todos, which we can read and write to. To read and write those, we'll pull out todos. Then our write method, we can invoke to commit our changes.

[0:18] To create some todos, we'll say, await arg new todo. Then this can be the name of our new todo. Then we say, todos.push. We'll push an object with a name and ID. We'll use the UUID helper to create the ID. Then we'll also add a tag of open.

[0:39] Then after we've pushed, we can await right to the DB to commit our changes. Once we save and run this here, we'll open todos. It will prompt for a new todo. We'll say beat. Hit Enter. Then if we check in our can, in the DB directory, you'll see a _todos. I'll open this to the side, and you'll see the data that we committed.

[1:04] This was named _todos based on the name of the script. If you don't give your DB a name, it'll automatically name it underscore and then the command name of your script. Let's add another todo. Watch this happen. We'll type sleep. Hit Enter.

[1:20] Then sleep shows up. To toggle these complete and incomplete, we'll separate new and toggle into separate tabs. Tabs are created using on tab, and then a name. We'll name this first tab todos.

[1:37] This takes a callback because on tab essentially means from the app, when you select a tab, call this function. We'll have on tab todos, and on tab new, and then we'll drop this inside of here because once we select the new tab, we want to do this.

[1:55] Our toggle logic, we want to show all the todos, so toggle todo and then show the todos as a list. Then the one that we select will be called todo. Then we can use underscore to find, from the todos, finder todo. This is the actual todo from the database.

[2:17] We'll say, todo.tag will be todo tag = open. If it's open, then switch it to done. Otherwise, switch it to open. Then we'll go ahead and write. If we launch our todos, you'll see we have eat and sleep. I'll hit Enter on eat and you'll see that this tag switches over to done. The nice thing about using tags with your args is that they're searchable.

[2:46] If I type done, it'll filter down to only the ones that are done or open. It's a nice way of grouping data and making it searchable. If I swap over to new, I can still add todos. I'll type code, hit Enter, and you'll see eat, sleep, and code.

[3:02] The behavior we probably want here is, once we toggle a todo, we still want the list open. We can wrap all of this inside of a while true loop. That just means once it gets here, go back to here and prompt again.

[3:21] You'll see when I open my todos, I hit Enter, we'll just keep the todos open. It'll toggle eat from open to done, open to done. I'll go down to sleep, open, done, open, done. You can see as I toggle this, you'll see it changing the database over here as well.

[3:40] A common thing for after I add a new todo, I probably want to switch back over to the todos tab. I can do that by saying setTab and then the name of the tab I want it switched back to. If I open my todos again, I'll go over to new. I'll type dance. Hit Enter.

[4:00] That will switch back to the todos tab, where I can see my data again. Let's go ahead and add another tab for removing todos. Just going to duplicate everything in here. We'll call this remove. I actually want to be able to find the todo.

[4:17] I'll just use this same list todos, call this remove todo, and then we'll use low dashes remove. Just say in the todos, take the todos, find the one where the todo ID is equal to todo.ID. That will remove it. Then we can write and set the tab back to todos.

[4:41] If I run this, go to todos, switch over to remove, I'll hit Enter on code, and now I have eat, sleep, and dance. I'll go back to remove, hit Enter on sleep. I have eat and dance. I can still toggle, create new ones, and manage this data however I want.

~ 3 minutes ago

Member comments are a way for members to communicate, interact, and ask questions about a lesson.

The instructor or someone from the community might respond to your question Here are a few basic guidelines to commenting on

Be on-Topic

Comments are for discussing a lesson. If you're having a general issue with the website functionality, please contact us at

Avoid meta-discussion

  • This was great!
  • This was horrible!
  • I didn't like this because it didn't match my skill level.
  • +1 It will likely be deleted as spam.

Code Problems?

Should be accompanied by code! Codesandbox or Stackblitz provide a way to share code and discuss it in context

Details and Context

Vague question? Vague answer. Any details and context you can provide will lure more interesting answers!

Markdown supported.
Become a member to join the discussionEnroll Today