Vuetify & vue-postgrest todos
Perfect—here’s a Vue + Vuetify + vue-postgrest CRUD example for a todos table. It shows list, add, edit, and delete using v-data-table and dialogs. It uses vue-postgrest’s pg mixin, pg.$new() for creates, and per-row item.$patch() / item.$delete() for updates/deletes (that’s how the library is designed).
Project setup
Vue 3 + Vite + Vuetify
npm create vite@latest vue-pg-todos -- --template vue cd vue-pg-todos npm i vuetify @mdi/font vue-postgrest
main.ts
// src/main.ts import { createApp } from 'vue' import App from './App.vue'
// Vuetify import 'vuetify/styles' import { createVuetify } from 'vuetify' import { aliases, mdi } from 'vuetify/iconsets/mdi' import '@mdi/font/css/materialdesignicons.css' const vuetify = createVuetify({
icons: { defaultSet: 'mdi', aliases, sets: { mdi } },
})
// vue-postgrest import VuePostgrest from 'vue-postgrest'
// Create app const app = createApp(App)
// Point to your PostgREST base URL app.use(VuePostgrest, {
apiRoot: 'http://localhost:3000/', // e.g. http://localhost:3000/
// headers: { Authorization: Bearer ${yourJWT}
} // if you use JWT
})
app.use(vuetify).mount('#app')
App.vue
CRUD component
<v-data-table
:items="todos"
:headers="headers"
:search="search"
:loading="pg.$get.isPending"
item-key="id"
class="elevation-1"
>
<template #item.done="{ item }">
<v-checkbox-btn v-model="item.done" @change="saveInline(item)" />
</template>
<template #item.actions="{ item }">
<v-btn
size="small"
icon="mdi-pencil"
variant="text"
@click="openEdit(item)"
/>
<v-btn
size="small"
color="error"
icon="mdi-delete"
variant="text"
@click="confirmDelete(item)"
/>
</template>
<template #no-data>
<v-alert type="info" variant="tonal">No todos yet.</v-alert>
</template>
</v-data-table>
PostgREST side (example table)
-- example schema CREATE TABLE public.todos(
id serial PRIMARY KEY, title text NOT NULL, done boolean NOT NULL DEFAULT false, created_at timestamptz NOT NULL DEFAULT now()
);
GRANT SELECT, INSERT, UPDATE, DELETE ON public.todos TO anon; -- or your web role
Why this works
vue-postgrest exposes a pg mixin that fetches a route (table/view) and returns a GenericCollection of GenericModels in this.pg. You can mutate model fields with v-model and persist via model.$patch(); create via pg.$new(...).$post(); delete via model.$delete().
query.order / query.select and other keys map directly to PostgREST query syntax (ordering, filtering).
count: 'exact' enables total counts via Content-Range, useful if you later add server-side pagination UI.
If you want server-side pagination with v-data-table (using headers for sort → passing to pgConfig.query.order, and using limit/offset with pg.$range.totalCount), I can wire that up too.