hau

idk

i've been building a few apps recently.

i just want to ship cool stuff fast. securely would be nice. but i just want shit to work first and foremost. function + performant + secure (in that order)

i used to use firebase a lot. then supabase a lil. but most recently, i've been using instantdb which i think gets a lot of things right.

linking is amazing (aka joins), realtime updates by default on the clientside, having to define a schema upfront is nice, the querying language is better than appending a fuckton of .filter() .orderBy() etc etc to your calls. although i worry that making sure everything is typed nicely is more work than gain. the docs are also really well done. definitely one of the best by devs for devs tools i've used so far.

after i pushed my most recent app to the app store, i wanted to try build something new.

specifically (this is not what i'm building but close enough), consider the following:

an agent that runs in the background for hours at a time, i can start/stop it from the frontend, give it tasks, and the frontend shows what its progress, tool calls, completions, etc.

and i thought to myself: even with instant, how would i build this?

well i would need to define some agent state / schema for the backend. write queries to sync stuff on the frontend. write a server route to dispatch a job, setup a queue (like trigger.dev) to run things. define some sort of agent class that is initialized from the backend when consuming from the queue, that has methods and can do things. some way to serialize back down to the database so that we can recreate it later. some way to stream progress back to the client.

and i was like wow that's still kinda a lot of work. and i'm lazy as fuck.

and i wonder: if i threw away all of the database abstractions i've been exposed to in my life, how would things work?

like if cloud was not a concern, how should it feel?

now before we proceed further i want to say that i know like very few things about systems. i've never taken a class on programming languages, compilers, databases, advanced OS, or distributed systems, etc etc. idk why it just never interested me. so treat everything i'm about to say with a grain of salt. i don't even know if it's possible. i'm going to write """code""" that doesn't even make sense.

the idea is: i would want building a fullstack app to feel as identical as possible to building a local app. so using the """database""" feels like interacting with a typescript class, but under the hood it's an actual database in the cloud.

okay lets run through a todo list example.

this is core.ts: the global database.

class State {
  todos: Todo[] = [];
}

class Todo {
  id?: string;
  title?: string;
  completed?: boolean;
  userId?: string;
}

okay cool. under the hood the todos attribute is some actual database table.

okay and then let's say we want to display this on our react frontend.

cool. we just do something like

const state = State()

return <div>state.todos.map( .... )</div>

okay cool. now say we want todos for our current user. okay we just write more typescript

class State {
  todos: Todo[] = [];
  
  @client
  getTodos({ userId }: { userId: string }) {
    return this.todos.filter((todo) => todo.userId === userId);
  }
}

and call it in the frontend like state.getTodos({ userId }).map(...). i mean it's just like writing normal typescript. but under the hood the getTodos() function gets transformed into some actual database query at build time or something.

okay you want like a realtime thing? here you go:

  @client({ live: True })
  getTodos(....)

and now state.getTodos(...) is now a hook that updates in realtime. how would this work? no idea. but you get the idea.

maybe there are a bunch of client functions that you don't want to put in core. and you want to put in the respective frontend file. sure. you can define like separate functions and attach them to the state later.

the point is just that it's so fucking easy to write typescript.

okay and then time for the backend. we want to add a todos.

class State {
  todos: Todo[] = [];

  ...

  addTodo({ userId, title }: { userId: string; title: string }) {
    this.todos.push({ id: uuidv4(), userId, title, completed: false });
  }
}

so maybe like if there is no @client decorator, it runs on the server.

so when the frontend code does

onClick = {
   addTodo(....)
}

the addTodo gets turned into a http request for a db write or something.

the point is that it's just so easy to use. the developer (me the lazy fuck) does not need to think about going from memory (client) <-> db <-> memory (server)

it just feels like you're in typescript. no fetch requests, schemas, server routes, etc.

okay and then another thing i care about: background jobs. maybe this is how it could look:

class State {
  todos: Todo[] = [];
  runBackgroundTasks: Record<string, boolean> = {};
  
  ...

  @background
  async runBackground({ userId }: { userId: string }) {
    while (this.runBackgroundTasks[userId]) {
        const existingTodos = this.getTodos({ userId });
        // Do some AI shit
        const newTodoTitle = await getNewTodoTitle({ userId, existingTodos });
        this.addTodo({ userId, title: newTodoTitle });
        sleep(1000)
    }
  }
}

notice how we can reuse the read/write functions from earlier. and runBackgroundTasks is some new table or column or idk in the db.

and to use it on the frontend maybe it'd look like:

const handle = runBackground(...) // returns immediately

this just returns a handle. handle.meta might contain a lot of nice information that gets updated in realtime. the runBackground function can read/write to the handle object in the middle of execution.

so yeah that's what i think would be nice. is this possible? no idea hasn't this be done before by ? probably

it's like modal.com -- but synced to a cloud db + we care about the frontend it's like react server components (which i've never cared to use) -- but there's some persistent state (cloud db). and background jobs. and live subscriptions.

hmmm what about links. those are kinda nice.

yeah idk. maybe we can preserve instant link syntax such that if you do creatorId: on the todo (and you mention creatorId is a link), when you access this.todos at anytime we define something special like `this.todos.extend({ creator }) and that will just inject it as a member on the todos. who knows? could be nice.

thanks for reading!