Introduction
Getting started with Vanilla JS
You can use Instant with plain ol' Javascript/Typescript too. You may find this helpful to integrate Instant with a framework that doesn't have an official SDK yet.
To use Instant in a brand new project fire up your terminal set up a new project with Vite.
npx create-vite@latest -t vanilla-ts instant-vanillacd instant-vanillanpm i @instantdb/corenpm run dev
Now open up src/main.ts in your favorite editor and replace the entirety of the file with the following code.
import { init, i, id, InstaQLEntity } from "@instantdb/core";// Visit https://instantdb.com/dash to get your APP_ID :)const APP_ID = "__APP_ID__";// Optional: Declare your schema!const schema = i.schema({entities: {todos: i.entity({text: i.string(),done: i.boolean(),createdAt: i.date(),}),},});type Todo = InstaQLEntity<typeof schema, "todos">;// Initialize the database// ---------const db = init({ appId: APP_ID, schema });// Subscribe to data// ---------db.subscribeQuery({ todos: {} }, (resp) => {if (resp.error) {renderError(resp.error.message); // Pro-tip: Check you have the right appId!return;}if (resp.data) {render(resp.data);}});// Write Data// ---------function addTodo(text: string) {db.transact(db.tx.todos[id()].update({text,done: false,createdAt: Date.now(),}));focusInput();}function deleteTodoItem(todo: Todo) {db.transact(db.tx.todos[todo.id].delete());}function toggleDone(todo: Todo) {db.transact(db.tx.todos[todo.id].update({ done: !todo.done }));}function deleteCompleted(todos: Todo[]) {const completed = todos.filter((todo) => todo.done);const txs = completed.map((todo) => db.tx.todos[todo.id].delete());db.transact(txs);}function toggleAllTodos(todos: Todo[]) {const newVal = !todos.every((todo) => todo.done);db.transact(todos.map((todo) => db.tx.todos[todo.id].update({ done: newVal })));}// Styles// ---------const styles: Record<string, string> = {container: `box-sizing: border-box;background-color: #fafafa;font-family: code, monospace;height: 100vh;display: flex;justify-content: center;align-items: center;flex-direction: column;`,header: `letter-spacing: 2px;font-size: 50px;color: lightgray;margin-bottom: 10px;`,form: `box-sizing: inherit;display: flex;border: 1px solid lightgray;border-bottom-width: 0px;width: 350px;`,toggleAll: `font-size: 30px;cursor: pointer;margin-left: 11px;margin-top: -6px;width: 15px;margin-right: 12px;`,input: `background-color: transparent;font-family: code, monospace;width: 287px;padding: 10px;font-style: italic;`,todoList: `box-sizing: inherit;width: 350px;`,checkbox: `font-size: 30px;margin-left: 5px;margin-right: 20px;cursor: pointer;`,todo: `display: flex;align-items: center;padding: 10px;border: 1px solid lightgray;border-bottom-width: 0px;`,todoText: `grow: 1;overflow: hidden;`,delete: `width: 25px;cursor: pointer;color: lightgray;`,actionBar: `display: flex;justify-content: space-between;width: 328px;padding: 10px;border: 1px solid lightgray;font-size: 10px;`,footer: `margin-top: 20px;font-size: 10px;`,};// Render// ---------const app = document.getElementById("app")!;app.style.cssText = styles.container;function render(data: { todos: Todo[] }) {app.innerHTML = "";const { todos } = data;const containerHTML = `<div style="${styles.container}"><div style="${styles.header}">todos</div>${TodoForm()}${TodoList(todos)}${ActionBar(todos)}<div style="${styles.footer}">Open another tab to see todos update in realtime!</div></div>`;app.innerHTML = containerHTML;// Attach event listenersdocument.querySelector(".toggle-all")?.addEventListener("click", () => toggleAllTodos(todos));document.querySelector("form")?.addEventListener("submit", submitForm);todos.forEach((todo) => {document.getElementById(`toggle-${todo.id}`)?.addEventListener("change", () => toggleDone(todo));document.getElementById(`delete-${todo.id}`)?.addEventListener("click", () => deleteTodoItem(todo));});document.querySelector(".delete-completed")?.addEventListener("click", () => deleteCompleted(todos));}function renderError(errorMessage: string) {app.innerHTML = `<div>${errorMessage}</div>`;}function TodoForm() {return `<div style="${styles.form}"><div class="toggle-all" style="${styles.toggleAll}">⌄</div><form><input style="${styles.input}" placeholder="What needs to be done?" type="text" autofocus></form></div>`;}function TodoList(todos: Todo[]) {return `<div style="${styles.todoList}">${todos.map((todo) => `<div style="${styles.todo}"><input id="toggle-${todo.id}" type="checkbox" style="${styles.checkbox}" ${todo.done ? "checked" : ""}><div style="${styles.todoText}">${todo.done? `<span style="text-decoration: line-through;">${todo.text}</span>`: `<span>${todo.text}</span>`}</div><span id="delete-${todo.id}" style="${styles.delete}">𝘟</span></div>`).join("")}</div>`;}function ActionBar(todos: Todo[]) {return `<div style="${styles.actionBar}"><div>Remaining todos: ${todos.filter((todo) => !todo.done).length}</div><div class="delete-completed" style="cursor: pointer;">Delete Completed</div></div>`;}function focusInput() {const input = document.querySelector<HTMLInputElement>('input[type="text"]');if (input) {input.focus();}}function submitForm(event: Event) {event.preventDefault();const input = (event.target as HTMLFormElement).querySelector("input");if (input && input.value.trim()) {addTodo(input.value);input.value = "";}}
Go to localhost:5173 and follow the final instruction to load the app!
Huzzah 🎉 You've got your first Instant web app running! Check out the Working with data section to learn more about how to use Instant :)