Convex is a reactive backend-as-a-service that eliminates the gap between your database and your UI. Write queries and mutations in TypeScript — they run on the server but feel like local function calls.
Reactive Queries: Auto-Updating UI
// convex/products.ts (server)
import { query } from "./_generated/server";
import { v } from "convex/values";
export const list = query({
args: { category: v.string() },
handler: async (ctx, { category }) => {
return await ctx.db
.query("products")
.withIndex("by_category", (q) => q.eq("category", category))
.order("desc")
.take(50);
},
});
// React component — auto-updates when data changes!
import { useQuery } from "convex/react";
import { api } from "../convex/_generated/api";
function ProductList() {
const products = useQuery(api.products.list, { category: "electronics" });
// products automatically updates when ANY user adds/edits/deletes a product
return products?.map(p => <ProductCard key={p._id} product={p} />);
}
No WebSocket setup. No cache invalidation. No refetching. It just works.
Mutations: Type-Safe Writes
// convex/products.ts
import { mutation } from "./_generated/server";
import { v } from "convex/values";
export const add = mutation({
args: {
title: v.string(),
price: v.number(),
url: v.string(),
category: v.string(),
},
handler: async (ctx, args) => {
const id = await ctx.db.insert("products", {
...args,
scrapedAt: Date.now(),
});
return id;
},
});
// Client — fully typed
import { useMutation } from "convex/react";
const addProduct = useMutation(api.products.add);
await addProduct({ title: "Widget", price: 29.99, url: "...", category: "electronics" });
Actions: External API Calls
import { action } from "./_generated/server";
import { v } from "convex/values";
export const scrapeAndStore = action({
args: { url: v.string() },
handler: async (ctx, { url }) => {
// Call external scraping API
const response = await fetch(`https://api.apify.com/v2/acts/...`);
const data = await response.json();
// Store results using mutations
for (const item of data.items) {
await ctx.runMutation(api.products.add, item);
}
return { count: data.items.length };
},
});
Scheduled Functions: Cron Jobs
// convex/crons.ts
import { cronJobs } from "convex/server";
import { api } from "./_generated/api";
const crons = cronJobs();
crons.interval("scrape prices", { hours: 1 }, api.scraping.scrapeAndStore, {
url: "https://example.com/products"
});
crons.cron("daily report", "0 9 * * *", api.reports.generateDaily, {});
export default crons;
File Storage API
// Upload
const uploadUrl = await generateUploadUrl();
await fetch(uploadUrl, { method: "POST", body: file });
// Store reference in document
await ctx.db.insert("exports", { fileId: storageId, format: "csv" });
// Get URL
const url = await ctx.storage.getUrl(fileId);
Build real-time dashboards with scraped data? My Apify tools + Convex = live-updating data displays.
Custom real-time solution? Email spinov001@gmail.com
Top comments (0)