DEV Community

Alex Spinov
Alex Spinov

Posted on

Convex Has a Free API You're Not Using

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} />);
}
Enter fullscreen mode Exit fullscreen mode

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(),
    });
  },
});
Enter fullscreen mode Exit fullscreen mode

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;
  },
});
Enter fullscreen mode Exit fullscreen mode

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 });
  },
});
Enter fullscreen mode Exit fullscreen mode

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);
  },
});
Enter fullscreen mode Exit fullscreen mode

Getting Started

npm create convex@latest
npx convex dev
Enter fullscreen mode Exit fullscreen mode

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)