SaaS Scaffolder
alirezarezvani/claude-skills
Generates complete, production-ready SaaS project boilerplate including authentication, database schemas, billing integration, API routes, and a working dashboard using Next.js 14+ App Router…
Convex reactive backend expert: schema design, TypeScript functions, real-time subscriptions, auth, file storage, scheduling, and deployment.
$ npx skills add davila7/claude-code-templates --skill convex -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install davila7/claude-code-templates convex --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ git clone --depth 1 https://github.com/davila7/claude-code-templates.git skills-src && mkdir -p .claude/skills && cp -r skills-src/cli-tool/components/skills/development/convex .claude/skills/convex && rm -rf skills-srcUse ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.
Claude Code skills documentation · loads skills from .claude/skills/
Install the "convex" agent skill from https://github.com/davila7/claude-code-templates/tree/main/cli-tool/components/skills/development/convex into .claude/skills/convex/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "convex", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/davila7/claude-code-templates/tree/main/cli-tool/components/skills/development/convexType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add davila7/claude-code-templates --skill convex -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install davila7/claude-code-templates convex --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/davila7/claude-code-templates.git skills-src && mkdir -p .agents/skills && cp -r skills-src/cli-tool/components/skills/development/convex .agents/skills/convex && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "convex" agent skill from https://github.com/davila7/claude-code-templates/tree/main/cli-tool/components/skills/development/convex into .agents/skills/convex/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "convex", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add davila7/claude-code-templates --skill convex -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install davila7/claude-code-templates convex --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/davila7/claude-code-templates.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/cli-tool/components/skills/development/convex .cursor/skills/convex && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "convex" agent skill from https://github.com/davila7/claude-code-templates/tree/main/cli-tool/components/skills/development/convex into .cursor/skills/convex/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "convex", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/davila7/claude-code-templates.git --path cli-tool/components/skills/development/convex--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add davila7/claude-code-templates --skill convex -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install davila7/claude-code-templates convex --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/davila7/claude-code-templates.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/cli-tool/components/skills/development/convex .gemini/skills/convex && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "convex" agent skill from https://github.com/davila7/claude-code-templates/tree/main/cli-tool/components/skills/development/convex into .gemini/skills/convex/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "convex", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install davila7/claude-code-templates convexInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add davila7/claude-code-templates --skill convex -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/davila7/claude-code-templates.git skills-src && mkdir -p .github/skills && cp -r skills-src/cli-tool/components/skills/development/convex .github/skills/convex && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "convex" agent skill from https://github.com/davila7/claude-code-templates/tree/main/cli-tool/components/skills/development/convex into .github/skills/convex/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "convex", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add davila7/claude-code-templates --skill convex -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install davila7/claude-code-templates convex --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/davila7/claude-code-templates.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/cli-tool/components/skills/development/convex .opencode/skills/convex && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "convex" agent skill from https://github.com/davila7/claude-code-templates/tree/main/cli-tool/components/skills/development/convex into .opencode/skills/convex/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "convex", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
convexConvex reactive backend expert: schema design, TypeScript functions, real-time subscriptions, auth, file storage, scheduling, and deployment.
Convex is an agent skill from davila7/claude-code-templates. Convex reactive backend expert: schema design, TypeScript functions, real-time subscriptions, auth, file storage, scheduling, and deployment.
Its SKILL.md is about 6.4k tokens, which your agent loads only when the skill is triggered. It is a single SKILL.md file with no bundled scripts.
It sits in Databases, covering Database schema design and File uploads and storage. It works with TypeScript and Next.js. The repository describes itself as: CLI tool for configuring and monitoring Claude Code. The licence is MIT.
5 steps, taken from the first numbered list in SKILL.md.
Read from SKILL.md and the folder at commit 46b4d8b. It shows what the files ask for, not the result of running them.
Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.
From allowed-tools in the SKILL.md frontmatter.
Shell commands in SKILL.md call:
npxnpmFrom the folder's file list and the shell code blocks in SKILL.md.
Hosts in commands or code, which the agent is likely to contact:
api.sendgrid.comapi.openai.comAlso links to:
docs.convex.devstack.convex.devgithub.comconvex.devchef.convex.devFrom URLs in SKILL.md, links to its own repository left out.
Names these keys or tokens, usually read from environment variables:
OPENAI_API_KEYSENDGRID_API_KEYNEXT_PUBLIC_CLERK_PUBLISHABLE_KEYBETTER_AUTH_SECRETFrom names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
Convex loads about 6.4k tokens when it runs. Until then it costs about 37 tokens; SKILL.md has 1,096 words of instructions outside code blocks.
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
The automated check noted patterns worth knowing about, such as sudo or a known installer.
5. Creates `.env.local` with `CONVEX_DEPLOYMENT` and `NEXT_PUBLIC_CONVEX_URL`├── .env.local ← CONVEX_DEPLOYMENT, NEXT_PUBLIC_CONVEX_URLAutomated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.
The full file from davila7/claude-code-templates at commit 46b4d8b, republished under its MIT licence (© davila7). 1,096 words, ~6,377 tokens.
.claude/skills/convex/SKILL.md (or your agent's skills folder).You are an expert in Convex — the open-source, reactive backend platform where queries are TypeScript code. You have deep knowledge of schema design, function authoring (queries, mutations, actions), real-time data subscriptions, authentication, file storage, scheduling, and deployment workflows across React, Next.js, Angular, Vue, Svelte, React Native, and server-side environments.
Convex is a document-relational database with a fully managed backend. Key differentiators:
| Type | Purpose | Can Read DB | Can Write DB | Can Call External APIs | Cached/Reactive |
|---|---|---|---|---|---|
| Query | Read data | ✅ | ❌ | ❌ | ✅ |
| Mutation | Write data | ✅ | ✅ | ❌ | ❌ |
| Action | Side effects | via runQuery | via runMutation | ✅ | ❌ |
| HTTP Action | Webhooks/custom endpoints | via runQuery | via runMutation | ✅ | ❌ |
npx create-next-app@latest my-app
cd my-app && npm install convex
npx convex devnpm install convex
npx convex devThe npx convex dev command:
convex/ folder for backend functions.env.local with CONVEX_DEPLOYMENT and NEXT_PUBLIC_CONVEX_URLmy-app/
├── convex/
│ ├── _generated/ ← Auto-generated (DO NOT EDIT)
│ │ ├── api.d.ts
│ │ ├── dataModel.d.ts
│ │ └── server.d.ts
│ ├── schema.ts ← Database schema definition
│ ├── tasks.ts ← Query/mutation functions
│ └── http.ts ← HTTP actions (optional)
├── .env.local ← CONVEX_DEPLOYMENT, NEXT_PUBLIC_CONVEX_URL
└── convex.json ← Project config (optional)Define your schema in convex/schema.ts using the validator library:
import { defineSchema, defineTable } from "convex/server";
import { v } from "convex/values";
export default defineSchema({
users: defineTable({
name: v.string(),
email: v.string(),
avatarUrl: v.optional(v.string()),
tokenIdentifier: v.string(),
})
.index("by_token", ["tokenIdentifier"])
.index("by_email", ["email"]),
messages: defineTable({
authorId: v.id("users"),
channelId: v.id("channels"),
body: v.string(),
attachmentId: v.optional(v.id("_storage")),
})
.index("by_channel", ["channelId"])
.searchIndex("search_body", { searchField: "body" }),
channels: defineTable({
name: v.string(),
description: v.optional(v.string()),
isPrivate: v.boolean(),
}),
});| Validator | TypeScript Type | Notes |
|---|---|---|
v.string() | string | |
v.number() | number | IEEE 754 float |
v.bigint() | bigint | |
v.boolean() | boolean | |
v.null() | null | |
v.id("tableName") | Id<"tableName"> | Document reference |
v.array(v.string()) | string[] | |
v.object({...}) | {...} | Nested objects |
v.optional(v.string()) | string | undefined | |
v.union(v.string(), v.number()) | string | number | |
v.literal("active") | "active" | Literal types |
v.bytes() | ArrayBuffer | Binary data |
v.float64() | number | Explicit 64-bit float (used in vector indexes) |
v.any() | any | Escape hatch |
// Single-field index
defineTable({ email: v.string() }).index("by_email", ["email"]);
// Compound index (order matters for range queries)
defineTable({
orgId: v.string(),
createdAt: v.number(),
}).index("by_org_and_date", ["orgId", "createdAt"]);
// Full-text search index
defineTable({ body: v.string(), channelId: v.id("channels") }).searchIndex(
"search_body",
{
searchField: "body",
filterFields: ["channelId"],
},
);
// Vector search index (for AI/embeddings)
defineTable({ embedding: v.array(v.float64()), text: v.string() }).vectorIndex(
"by_embedding",
{
vectorField: "embedding",
dimensions: 1536,
},
);Queries are reactive — clients automatically get updates when data changes.
import { query } from "./_generated/server";
import { v } from "convex/values";
// Simple query — list all tasks
export const list = query({
args: {},
handler: async (ctx) => {
return await ctx.db.query("tasks").collect();
},
});
// Query with arguments and filtering
export const getByChannel = 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);
},
});
// Query with auth check
export const getMyProfile = query({
args: {},
handler: async (ctx) => {
const identity = await ctx.auth.getUserIdentity();
if (!identity) return null;
return await ctx.db
.query("users")
.withIndex("by_token", (q) =>
q.eq("tokenIdentifier", identity.tokenIdentifier),
)
.unique();
},
});
### Paginated Queries
Use cursor-based pagination for lists or infinite scroll UIs.
```typescript
import { query } from "./_generated/server";
import { paginationOptsValidator } from "convex/server";
export const listPaginated = query({
args: {
paginationOpts: paginationOptsValidator
},
handler: async (ctx, args) => {
return await ctx.db
.query("messages")
.order("desc")
.paginate(args.paginationOpts);
},
});
```
### Mutations (Write Data)
Mutations run as ACID transactions with serializable isolation.
```typescript
import { mutation } from "./_generated/server";
import { v } from "convex/values";
// Insert a document
export const create = mutation({
args: { text: v.string(), isCompleted: v.boolean() },
handler: async (ctx, args) => {
const taskId = await ctx.db.insert("tasks", {
text: args.text,
isCompleted: args.isCompleted,
});
return taskId;
},
});
// Update a document
export const update = mutation({
args: { id: v.id("tasks"), isCompleted: v.boolean() },
handler: async (ctx, args) => {
await ctx.db.patch(args.id, { isCompleted: args.isCompleted });
},
});
// Delete a document
export const remove = mutation({
args: { id: v.id("tasks") },
handler: async (ctx, args) => {
await ctx.db.delete(args.id);
},
});
// Multi-document transaction (automatically atomic)
export const transferCredits = mutation({
args: {
fromUserId: v.id("users"),
toUserId: v.id("users"),
amount: v.number(),
},
handler: async (ctx, args) => {
const fromUser = await ctx.db.get(args.fromUserId);
const toUser = await ctx.db.get(args.toUserId);
if (!fromUser || !toUser) throw new Error("User not found");
if (fromUser.credits < args.amount) throw new Error("Insufficient credits");
await ctx.db.patch(args.fromUserId, {
credits: fromUser.credits - args.amount,
});
await ctx.db.patch(args.toUserId, {
credits: toUser.credits + args.amount,
});
},
});Actions can call third-party services but cannot directly access the database — they must use ctx.runQuery and ctx.runMutation.
import { action } from "./_generated/server";
import { v } from "convex/values";
import { api } from "./_generated/api";
export const sendEmail = action({
args: { to: v.string(), subject: v.string(), body: v.string() },
handler: async (ctx, args) => {
// Call external API
const response = await fetch("https://api.sendgrid.com/v3/mail/send", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.SENDGRID_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
personalizations: [{ to: [{ email: args.to }] }],
from: { email: "noreply@example.com" },
subject: args.subject,
content: [{ type: "text/plain", value: args.body }],
}),
});
if (!response.ok) throw new Error("Failed to send email");
// Write result back to database via mutation
await ctx.runMutation(api.emails.recordSent, {
to: args.to,
subject: args.subject,
sentAt: Date.now(),
});
},
});
// Generate AI embeddings
export const generateEmbedding = action({
args: { text: v.string(), documentId: v.id("documents") },
handler: async (ctx, args) => {
const response = await fetch("https://api.openai.com/v1/embeddings", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.OPENAI_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
model: "text-embedding-3-small",
input: args.text,
}),
});
const { data } = await response.json();
await ctx.runMutation(api.documents.saveEmbedding, {
documentId: args.documentId,
embedding: data[0].embedding,
});
},
});import { httpRouter } from "convex/server";
import { httpAction } from "./_generated/server";
import { api } from "./_generated/api";
const http = httpRouter();
http.route({
path: "/webhooks/stripe",
method: "POST",
handler: httpAction(async (ctx, request) => {
const body = await request.text();
const signature = request.headers.get("stripe-signature");
// Verify webhook signature here...
const event = JSON.parse(body);
await ctx.runMutation(api.payments.handleWebhook, { event });
return new Response("OK", { status: 200 });
}),
});
export default http;// app/ConvexClientProvider.tsx
"use client";
import { ConvexProvider, ConvexReactClient } from "convex/react";
import { ReactNode } from "react";
const convex = new ConvexReactClient(process.env.NEXT_PUBLIC_CONVEX_URL!);
export function ConvexClientProvider({ children }: { children: ReactNode }) {
return <ConvexProvider client={convex}>{children}</ConvexProvider>;
}// app/layout.tsx — wrap children
import { ConvexClientProvider } from "./ConvexClientProvider";
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en">
<body>
<ConvexClientProvider>{children}</ConvexClientProvider>
</body>
</html>
);
}// Component using Convex hooks
"use client";
import { useQuery, useMutation } from "convex/react";
import { api } from "@/convex/_generated/api";
export function TaskList() {
// Reactive query — auto-updates when data changes
const tasks = useQuery(api.tasks.list);
const addTask = useMutation(api.tasks.create);
const toggleTask = useMutation(api.tasks.update);
if (tasks === undefined) return <p>Loading...</p>;
return (
<div>
{tasks.map((task) => (
<div key={task._id}>
<input
type="checkbox"
checked={task.isCompleted}
onChange={() =>
toggleTask({ id: task._id, isCompleted: !task.isCompleted })
}
/>
{task.text}
</div>
))}
<button onClick={() => addTask({ text: "New task", isCompleted: false })}>
Add Task
</button>
</div>
);
}// Component using Paginated Queries
"use client";
import { usePaginatedQuery } from "convex/react";
import { api } from "@/convex/_generated/api";
export function MessageLog() {
const { results, status, loadMore } = usePaginatedQuery(
api.messages.listPaginated,
{}, // args
{ initialNumItems: 20 }
);
return (
<div>
{results.map((msg) => (
<div key={msg._id}>{msg.body}</div>
))}
{status === "LoadingFirstPage" && <p>Loading...</p>}
{status === "CanLoadMore" && (
<button onClick={() => loadMore(20)}>Load More</button>
)}
</div>
);
}Convex provides a robust, native authentication library (@convex-dev/auth) featuring Magic Links, Passwords, and 80+ OAuth providers without needing a third-party service.
// app/ConvexClientProvider.tsx
"use client";
import { ConvexAuthProvider } from "@convex-dev/auth/react";
import { ConvexReactClient } from "convex/react";
import { ReactNode } from "react";
const convex = new ConvexReactClient(process.env.NEXT_PUBLIC_CONVEX_URL!);
export function ConvexClientProvider({ children }: { children: ReactNode }) {
return (
<ConvexAuthProvider client={convex}>
{children}
</ConvexAuthProvider>
);
}// Client-side sign in
import { useAuthActions } from "@convex-dev/auth/react";
export function Login() {
const { signIn } = useAuthActions();
return <button onClick={() => signIn("github")}>Sign in with GitHub</button>;
}If you prefer a hosted third-party solution like Clerk:
// app/ConvexClientProvider.tsx
"use client";
import { ConvexProviderWithClerk } from "convex/react-clerk";
import { ClerkProvider, useAuth } from "@clerk/nextjs";
import { ConvexReactClient } from "convex/react";
const convex = new ConvexReactClient(process.env.NEXT_PUBLIC_CONVEX_URL!);
export function ConvexClientProvider({ children }: { children: ReactNode }) {
return (
<ClerkProvider publishableKey={process.env.NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY!}>
<ConvexProviderWithClerk client={convex} useAuth={useAuth}>
{children}
</ConvexProviderWithClerk>
</ClerkProvider>
);
}Convex also has a community component (@convex-dev/better-auth) that integrates the Better Auth library directly into the Convex backend. This is currently in early alpha.
npm install better-auth @convex-dev/better-auth
npx convex env set BETTER_AUTH_SECRET your-secret-here
npx convex env set SITE_URL http://localhost:3000Better Auth provides email/password, social logins, two-factor authentication, and session management — all running inside Convex functions rather than an external auth server.
Convex does not have an official Angular client library, but Angular apps can use the core convex package directly with Angular's Dependency Injection and Signals.
// services/convex.service.ts
import { Injectable, signal, effect, OnDestroy } from "@angular/core";
import { ConvexClient } from "convex/browser";
import { api } from "../../convex/_generated/api";
import { FunctionReturnType } from "convex/server";
@Injectable({ providedIn: "root" })
export class ConvexService implements OnDestroy {
private client = new ConvexClient(environment.convexUrl);
// Reactive signal — updates automatically when data changes
tasks = signal<FunctionReturnType<typeof api.tasks.list> | undefined>(
undefined,
);
constructor() {
// Subscribe to a reactive query
this.client.onUpdate(api.tasks.list, {}, (result) => {
this.tasks.set(result);
});
}
async addTask(text: string) {
await this.client.mutation(api.tasks.create, {
text,
isCompleted: false,
});
}
ngOnDestroy() {
this.client.close();
}
}// Component usage
import { Component, inject } from "@angular/core";
import { ConvexService } from "./services/convex.service";
@Component({
selector: "app-task-list",
template: `
@if (convex.tasks(); as tasks) {
@for (task of tasks; track task._id) {
<div>{{ task.text }}</div>
}
} @else {
<p>Loading...</p>
}
<button (click)="convex.addTask('New task')">Add Task</button>
`,
})
export class TaskListComponent {
convex = inject(ConvexService);
}Note: The community library
@robmanganelly/ngx-convexprovides a more Angular-native experience with React-like hooks adapted for Angular DI and Signals.
import { mutation } from "./_generated/server";
import { api } from "./_generated/api";
export const sendReminder = mutation({
args: { userId: v.id("users"), message: v.string(), delayMs: v.number() },
handler: async (ctx, args) => {
await ctx.scheduler.runAfter(args.delayMs, api.notifications.send, {
userId: args.userId,
message: args.message,
});
},
});// convex/crons.ts
import { cronJobs } from "convex/server";
import { api } from "./_generated/api";
const crons = cronJobs();
crons.interval("clear old logs", { hours: 24 }, api.logs.clearOld);
crons.cron(
"weekly digest",
"0 9 * * 1", // Every Monday at 9 AM
api.emails.sendWeeklyDigest,
);
export default crons;// Generate an upload URL (mutation)
export const generateUploadUrl = mutation({
args: {},
handler: async (ctx) => {
return await ctx.storage.generateUploadUrl();
},
});
// Save file reference after upload (mutation)
export const saveFile = mutation({
args: { storageId: v.id("_storage"), name: v.string() },
handler: async (ctx, args) => {
await ctx.db.insert("files", {
storageId: args.storageId,
name: args.name,
});
},
});
// Get a URL to serve a file (query)
export const getFileUrl = query({
args: { storageId: v.id("_storage") },
handler: async (ctx, args) => {
return await ctx.storage.getUrl(args.storageId);
},
});# Set environment variables for your deployment
npx convex env set OPENAI_API_KEY sk-...
npx convex env set SENDGRID_API_KEY SG...
# List current env vars
npx convex env list
# Remove an env var
npx convex env unset OPENAI_API_KEYAccess in actions (NOT in queries or mutations):
// Only available in actions
const apiKey = process.env.OPENAI_API_KEY;# Development (watches for changes, syncs to dev deployment)
npx convex dev
# Deploy to production
npx convex deploy
# Import data
npx convex import --table tasks data.jsonl
# Export data
npx convex export --path ./backup
# Open Convex dashboard
npx convex dashboard
# Run a function from CLI
npx convex run tasks:list
# View logs
npx convex logsDate.now() and Math.random() are 100% safe to use in queries and mutations because Convex freezes time at the start of every function execution!v.id("tableName") for document references instead of plain stringsctx.runQuery / ctx.runMutation from actions — never access ctx.db directly in actionsnull when a document isn't found instead of throwing an error unless missing is exceptionalwithIndex over .filter() for query performance.collect() on large tables without limits: Fetches all documents into memory. Use .take(N) or .paginate()..filter() instead of indexes: .filter() does a full table scan. Define an index and use .withIndex()._storage) for files; keep documents lean.runQuery/runMutation chains: Actions calling mutations that schedule actions can create infinite loops.Problem: "Query returns undefined on first render"
Solution: This is expected — Convex queries are async. Check for undefined before rendering (this means loading, not empty).
Problem: "Mutation throws Document not found"
Solution: Documents may have been deleted between your read and write due to optimistic concurrency. Re-read inside the mutation.
Problem: "process.env is undefined in query/mutation"
Solution: Environment variables are only accessible in actions (not queries or mutations) because queries/mutations run in the deterministic transaction engine.
Problem: "Function handler is too slow"
Solution: Add indexes for your query patterns. Use withIndex() instead of .filter(). For complex operations, break into smaller mutations.
Problem: "Schema push fails with existing data"
Solution: Convex validates existing data against new schemas. Either migrate existing documents first, or use v.optional() for new fields.
@firebase — Alternative BaaS with Firestore (compare: Convex is TypeScript-first with ACID transactions)@supabase-automation — Alternative with PostgreSQL backend (compare: Convex is document-relational with built-in reactivity)@prisma-expert — ORM for traditional databases (Convex replaces both ORM and database)@react-patterns — Frontend patterns that pair well with Convex React hooks@nextjs-app-router — Next.js App Router integration patterns@authentication-oauth — Auth patterns (Convex supports Clerk, Auth0, Convex Auth)@stripe — Payment integration via Convex actions and HTTP webhooks© davila7, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
Just SKILL.md in cli-tool/components/skills/development/convex of davila7/claude-code-templates.
Open the folder on GitHubat commit 46b4d8b
We found 12 copies of this SKILL.md (exact, near-identical or edited) in other folders, from 3 other GitHub owners. This page covers the copy in davila7/claude-code-templates, which our catalogue first saw on October 7, 2026.
Convex next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| Convex this skilldavila7/claude-code-templates | 32k | 3 repos | ~6.4k | Automated safety check: Notes | MIT | |
| SaaS Scaffolderalirezarezvani/claude-skills | 28k | 1 repos | ~2.6k | Automated safety check: Pass | MIT | |
| SaaS Scaffolderborghei/Claude-Skills | 886 | — | ~1.8k | Automated safety check: Pass | MIT | |
| Fullstack DevHHU3637kr/skills | 145 | 3 repos | ~8.6k | Automated safety check: Notes | MIT | |
| Javascript SDKaiskillstore/marketplace | 430 | 1 repos | ~3.3k | Automated safety check: Pass | None | |
| Amplify Workflowawslabs/agent-plugins | 915 | — | ~3.2k | Automated safety check: Pass | Apache-2.0 |
alirezarezvani/claude-skills
Generates complete, production-ready SaaS project boilerplate including authentication, database schemas, billing integration, API routes, and a working dashboard using Next.js 14+ App Router…
borghei/Claude-Skills
Generate SaaS boilerplate with auth, database schemas, Stripe billing, multi-tenancy, API routes, and dashboard UI on a Next.js/TypeScript/Tailwind stack.
HHU3637kr/skills
Full-stack backend architecture and frontend-backend integration guide.
aiskillstore/marketplace
JavaScript/TypeScript SDK for inference.sh - run AI apps, build agents, integrate with all models.
awslabs/agent-plugins
Build and deploy full-stack web and mobile apps with AWS Amplify Gen2 (TypeScript code-first).
aws/agent-toolkit-for-aws
Build and deploy full-stack web and mobile apps with AWS Amplify Gen2 (TypeScript code-first).
davila7/claude-code-templates
Runs web-grounded searches through Perplexity's Sonar models over OpenRouter for current events, recent literature and cited facts beyond the model's training cutoff.
davila7/claude-code-templates
Analyzes Neuropixels recordings from SpikeGLX or Open Ephys through preprocessing, drift correction, Kilosort4 spike sorting, quality metrics and curation.
davila7/claude-code-templates
Supplies LaTeX templates and formatting rules for journals, conferences, posters, and grant proposals, then can check a draft against them.
davila7/claude-code-templates
Analyzes a brand's existing writing to lock in a consistent voice, then builds SEO blog posts and platform-specific social content around it.
davila7/claude-code-templates
Guides corrective and preventive action (CAPA) work in a quality management system, from initiation and root cause analysis through effectiveness verification.
davila7/claude-code-templates
Senior FDA consultant and specialist for medical device companies including HIPAA compliance and requirement management.
Works with
Categories
Convex reactive backend expert: schema design, TypeScript functions, real-time subscriptions, auth, file storage, scheduling, and deployment. Convex is an agent skill from davila7/claude-code-templates. Convex reactive backend expert: schema design, TypeScript functions, real-time subscriptions, auth, file storage, scheduling, and deployment.
Convex fits situations like: tasks that involve Database schema design; tasks that involve File uploads and storage.
Run `npx skills add davila7/claude-code-templates --skill convex -a claude-code`. Or copy the skill folder (cli-tool/components/skills/development/convex in davila7/claude-code-templates) into .claude/skills/convex in your project. Claude Code loads it when a task matches its description.
Run `npx skills add davila7/claude-code-templates --skill convex -a codex`. Or copy the skill folder (cli-tool/components/skills/development/convex in davila7/claude-code-templates) into .agents/skills/convex in your project. Codex loads it when a task matches its description.
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add davila7/claude-code-templates --skill convex -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/convex, .gemini/skills/convex, .github/skills/convex and .opencode/skills/convex in your project.
Going by SKILL.md and its folder, Convex needs the command-line tools its instructions call (npx and npm) and credentials named OPENAI_API_KEY, SENDGRID_API_KEY, NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY and BETTER_AUTH_SECRET. Our summary lists: Node.js; A credential in SENDGRID_API_KEY; A credential in OPENAI_API_KEY.
SKILL.md names 7 domains. In commands or code: api.sendgrid.com and api.openai.com; the agent is likely to contact these when it follows the instructions. As links in the text: docs.convex.dev, stack.convex.dev, github.com, convex.dev and chef.convex.dev. This is read from the text; nothing was executed.
Our automated static check of SKILL.md found notes only (mentions a .env file), nothing it rates as a warning. It is not a guarantee. Review the folder before installing.
Convex is published under the MIT licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.
About 6.4k tokens (SKILL.md is roughly 26k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.
Skills that share tags, products or a category with Convex: SaaS Scaffolder (alirezarezvani/claude-skills, 28k stars), SaaS Scaffolder (borghei/Claude-Skills, 886 stars), Fullstack Dev (HHU3637kr/skills, 145 stars) and Javascript SDK (aiskillstore/marketplace, 430 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
davila7 (a GitHub user) maintains it in davila7/claude-code-templates, which has 32,483 GitHub stars. The repository holds 478 skills in this directory. The repository was last updated on October 9, 2026.
Source: davila7/claude-code-templates on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.