Create your models
You have tables, but no way to talk to them yet. You could scatter database calls across every route file, but that gets messy fast. A model wraps a table and gives you simple methods — Form.create(data), Form.findByID(id), Form.delete(id) — so each table has one place that handles its operations.
The model factory
Your starter includes an app/models/.server/base/ folder with files for queries, types, and error handling. Together they export a createModel function that takes a table and returns an object with methods (functions attached to an object) like create, findBy, update, and delete. You don't need to dig into those files — just know that they handle the database calls for you.
Here's what each method does:
| Method | What it does |
|---|---|
create(data) | Insert a new row |
findByID(id) | Get one row by its ID |
findBy({ column: value }) | Get one row where column = value |
newest() / oldest() | Get all rows, newest or oldest first |
update(id, data) | Update a row by ID |
delete(id) | Delete a row by ID |
These are the same basic operations every table needs. Instead of writing raw database queries in every route, you call Form.create() or Submission.newest() and the model handles the rest.
Create the models
Ask your AI:
Create two model files. `app/models/.server/form.ts` should create a base with `createModel(forms)`, then export `Form` by spreading the base into a new object. `app/models/.server/submission.ts` should do the same with `createModel(submissions)`. Import the tables from the schema file.
The models should look like this:
import { createModel } from './base'
import { forms } from '~/.server/db/schema'
const base = createModel(forms)
export const Form = { ...base }
import { createModel } from './base'
import { submissions } from '~/.server/db/schema'
const base = createModel(submissions)
export const Submission = { ...base }
Simple. The ...base copies all the built-in methods into your model object. You don't need to understand this syntax yet — just know that Form and Submission now have all the methods from the table above, and you can add your own later.
Route → Model → Database
Here's the flow that you'll use from now on:
- Route receives a request (a page load or a form submission)
- Model handles the data operation (
Form.create(),Submission.newest()) - Database stores and retrieves the actual rows
The route doesn't talk to the database directly. The model is the middleman — it keeps your routes clean and your database logic in one place.
?What is a model?