Convex is a reactive backend-as-a-service with real-time sync, ACID transactions, and type-safe queries. Think Firebase but with a real database and TypeScript.
The Free APIs You're Missing
1. Reactive Queries — Automatic Real-Time
// convex/messages.ts
import { query } from "./_generated/server";
import { v } from "convex/values";
export const list = query({
args: { channelId: v.id("channels") },
handler: async (ctx, args) => {
return await ctx.db
.query("messages")
.withIndex("by_channel", q => q.eq("channelId", args.channelId))
.order("desc")
.take(50);
},
});
// React component — AUTOMATICALLY re-renders when data changes
function Chat({ channelId }) {
const messages = useQuery(api.messages.list, { channelId });
return messages?.map(m => <Message key={m._id} message={m} />);
}
2. Mutations — ACID Transactions
export const send = mutation({
args: { channelId: v.id("channels"), text: v.string() },
handler: async (ctx, args) => {
const user = await ctx.auth.getUserIdentity();
if (!user) throw new Error("Unauthenticated");
await ctx.db.insert("messages", {
channelId: args.channelId,
text: args.text,
author: user.name,
createdAt: Date.now(),
});
},
});
3. Actions — External API Calls
export const generateImage = action({
args: { prompt: v.string() },
handler: async (ctx, args) => {
const response = await fetch("https://api.openai.com/v1/images/generations", {
method: "POST",
headers: { Authorization: "Bearer " + process.env.OPENAI_KEY },
body: JSON.stringify({ prompt: args.prompt }),
});
const data = await response.json();
// Store result in database via mutation
await ctx.runMutation(api.images.store, { url: data.data[0].url });
return data.data[0].url;
},
});
4. Scheduled Functions — Cron and Delays
// crons.ts
import { cronJobs } from "convex/server";
const crons = cronJobs();
crons.interval("cleanup", { minutes: 30 }, api.cleanup.run);
crons.cron("daily-report", "0 9 * * *", api.reports.daily);
export default crons;
// Or schedule from mutations
export const scheduleReminder = mutation({
handler: async (ctx, args) => {
await ctx.scheduler.runAfter(3600000, api.notifications.send, { userId: args.userId });
},
});
5. File Storage — Built-In
export const upload = mutation({
handler: async (ctx) => {
return await ctx.storage.generateUploadUrl();
},
});
export const getImageUrl = query({
args: { storageId: v.id("_storage") },
handler: async (ctx, args) => {
return await ctx.storage.getUrl(args.storageId);
},
});
Getting Started
npm create convex@latest
npx convex dev
Need data from any website delivered as clean JSON? I build production web scrapers that handle anti-bot, proxies, and rate limits. 77 scrapers running in production. Email me: Spinov001@gmail.com
Check out my awesome-web-scraping list for the best scraping tools and resources.
Top comments (0)