Pick your app

The examples below will be updated with your app ID.

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-vanilla
cd instant-vanilla
npm i @instantdb/core
npm 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 listeners
document
.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 :)

If you are an LLM trying to learn how to develop with Instant, here are all of the links to the docs:

Getting started w/ ReactGetting started w/ React NativeGetting started w/ Vanilla JSGetting started w/ SolidJSGetting started w/ SvelteGetting started w/ VueGetting started w/ TanStack StartGetting started w/ PythonCreate Instant AppRecommended WorkflowUsing LLMsInitModeling dataWriting dataReading dataInfinite QueriesInstant on the backendPatternsAuthMagic codesGuest AuthGoogle OAuthSign In with AppleGitHub OAuthLinkedIn OAuthClerkFirebase AuthPermissionsRate LimitsManaging usersPresence, Cursors, and ActivityInstant CLIDevtoolPlatform APIExplorer ComponentCustom emailsApp teamsStorageStreamsWebhooksStripe PaymentsAdmin HTTP API(Experimental) Next.js SSROverviewVPSAWSMigrate from Instant CloudMigrating from Supabase