home / skills / sstobo / convex-skills / convex-actions-general

convex-actions-general skill

/convex-actions-general

This skill provides comprehensive guidance for Convex actions, HTTP endpoints, validators, schemas, environment variables, scheduling, file storage, and

npx playbooks add skill sstobo/convex-skills --skill convex-actions-general

Review the files below or copy the command above to add this skill to your agents.

Files (2)
SKILL.md
7.1 KB
---
name: convex-actions-general
description: This skill should be used when working with Convex actions, HTTP endpoints, validators, schemas, environment variables, scheduling, file storage, and TypeScript patterns. It provides comprehensive guidelines for function definitions, API design, database limits, and advanced Convex features.
---

# Convex Actions and General Guidelines Skill

This skill provides comprehensive guidance for Convex actions, HTTP endpoints, validators, schema design, file storage, environment variables, scheduling, and TypeScript best practices.

## When to Use This Skill

Use this skill when:
- Implementing action functions for external API calls and long-running tasks
- Creating HTTP endpoints for webhooks or public APIs
- Defining validators for function arguments and database schemas
- Designing database schemas with tables, indexes, and search capabilities
- Setting up environment variables for secrets and configuration
- Implementing cron jobs and scheduled tasks
- Working with file storage for uploads and downloads
- Using Convex-specific TypeScript patterns and types
- Understanding Convex limits and performance constraints

## Skill Resources

This skill includes comprehensive reference documentation in `references/actions-and-general.md` that covers:

### Actions and HTTP
- **Actions**: Defining actions with `"use node"` for Node.js modules
  - V8 vs Node runtime differences
  - Action limitations (10-minute timeout, no database access)
  - Calling external APIs and services
- **HTTP Endpoints**: Setting up `convex/http.ts` with httpRouter
  - Path registration and exact matching
  - Request/response handling
  - Method definitions (POST, GET, etc.)

### Validators and Types
- Complete validator reference for all Convex types
- Common validators: `v.object()`, `v.array()`, `v.string()`, `v.number()`, `v.id()`, `v.boolean()`, `v.null()`
- Discriminated union types with `v.union()` and `v.literal()`
- ASCII field name requirements for objects
- Size and element count limits

### Function Development
- New function syntax for all function types
- Function registration patterns (`query`, `mutation`, `action`, `internalQuery`, `internalMutation`, `internalAction`)
- Function calling patterns across runtimes
- Function references via `api` and `internal` objects
- File-based routing conventions

### API Design
- Organizing public and private functions
- Thoughtful file structure within `convex/` directory
- Public vs. internal function visibility
- API surface consistency

### Database and Schema
- **Schema Definition**: `convex/schema.ts` structure
  - System fields (`_id`, `_creationTime`)
  - Table definitions with validators
- **Indexes**: Creating efficient indexes
  - Built-in indexes (by_id, by_creation_time)
  - Custom index naming and field ordering
  - Multiple field indexes for complex queries
- **Full Text Search**: Search index definitions
  - Search fields and filter fields
  - Nested field paths with dot notation

### Environment and Configuration
- **Environment Variables**: Using `process.env`
  - Storing secrets (API keys, credentials)
  - Per-deployment configuration
  - Access from any function type
- **Scheduling**:
  - **Crons**: Using `crons.interval()` and `crons.cron()`
  - **Scheduler**: Using `ctx.scheduler.runAfter()` from mutations/actions
  - Auth state propagation (doesn't propagate to scheduled jobs)
  - Timing constraints and best practices

### File Storage
- Upload URL generation with `ctx.storage.generateUploadUrl()`
- Signed URL retrieval with `ctx.storage.getUrl()`
- File metadata from `_storage` system table
- Blob conversion for storage operations
- Complete example: image upload in chat application

### Limits and Performance
- Function arguments and return values: 8 MiB maximum
- Database operations: 8192 document writes per mutation, 16384 reads per query
- Execution timeouts: 1 second for queries/mutations, 10 minutes for actions
- Array element limits: 8192 maximum
- Object/Record field limits: 1024 maximum
- Nesting depth: 16 maximum
- Record size: 1 MiB maximum
- HTTP streaming: 20 MiB maximum output

### TypeScript
- `Id<'tableName'>` types for strict document IDs
- `Doc<'tableName'>` types for document type safety
- `Record<KeyType, ValueType>` with proper typing
- `as const` for discriminated unions
- Type annotations for same-file function calls
- `@types/node` for Node.js modules

## How to Use This Skill

1. **Read the reference documentation** at `references/actions-and-general.md` for comprehensive patterns
2. **Follow the syntax** for defining actions with proper Node.js module handling
3. **Use validators** correctly for all function arguments and schema fields
4. **Design schemas** with appropriate indexes for your access patterns
5. **Set up environment variables** for secrets and configuration
6. **Implement scheduling** for background tasks using crons or the scheduler
7. **Handle file storage** with proper URL generation and metadata lookup
8. **Understand limits** and design applications to respect them
9. **Use TypeScript strictly** with `Id` types and proper generics

## Key General Guidelines

- ALWAYS use argument validators for all functions (queries, mutations, actions)
- Do NOT store file URLs in the database; store file IDs instead
- Remapping non-ASCII characters (emoji) to ASCII codes before storing in objects
- Auth state does NOT propagate to scheduled jobs; use internal functions
- Scheduled functions should not run more than once every 10 seconds
- Never call actions from other actions unless crossing runtimes (V8 to Node)
- Objects in Convex must have ASCII-only field names
- Be strict with TypeScript types, especially for document IDs

## Example: Complete Action with HTTP Endpoint

```ts
// convex/ai.ts
"use node";
import { action } from "./_generated/server";
import { v } from "convex/values";
import { internal } from "./_generated/api";
import OpenAI from "openai";

const openai = new OpenAI({
  apiKey: process.env.OPENAI_API_KEY,
});

export const generateResponse = action({
  args: {
    channelId: v.id("channels"),
  },
  handler: async (ctx, args) => {
    // Actions can't access ctx.db, but can call mutations
    const context = await ctx.runQuery(internal.functions.loadContext, {
      channelId: args.channelId,
    });

    const response = await openai.chat.completions.create({
      model: "gpt-4o-mini",
      messages: context,
    });

    const content = response.choices[0].message.content;
    if (!content) throw new Error("No content in response");

    await ctx.runMutation(internal.functions.writeAgentResponse, {
      channelId: args.channelId,
      content,
    });

    return null;
  },
});
```

## Example: HTTP Endpoint

```ts
// convex/http.ts
import { httpRouter } from "convex/server";
import { httpAction } from "./_generated/server";

const http = httpRouter();

http.route({
  path: "/webhook",
  method: "POST",
  handler: httpAction(async (ctx, req) => {
    const body = await req.json();
    // Process webhook payload
    return new Response(JSON.stringify({ success: true }), { status: 200 });
  }),
});

export default http;
```

For more detailed information and additional patterns, refer to the complete reference documentation.

Overview

This skill distills best practices for working with Convex actions, HTTP endpoints, validators, schemas, environment variables, scheduling, file storage, and TypeScript patterns. It gives concrete guidance for defining functions, designing APIs and indexes, handling files and secrets, and staying within Convex limits. Use it to build reliable server-side logic and integrations that interoperate across Convex runtimes.

How this skill works

The skill explains what each function type can and cannot do (queries, mutations, actions, internal variants) and describes runtime distinctions (V8 vs Node). It covers HTTP endpoint routing, argument validation with Convex validators, schema and index definitions, file upload/download flows, environment variable usage, scheduling patterns, and relevant TypeScript typings. It highlights limits and performance constraints so you can design safe, efficient code.

When to use it

  • Implementing long-running tasks or external API calls from actions
  • Exposing webhooks or public APIs via Convex HTTP endpoints
  • Defining and enforcing argument and schema validators
  • Designing tables, indexes, and full-text search fields
  • Scheduling background jobs and cron-style tasks
  • Managing file uploads, signed URLs, and storage metadata

Best practices

  • Always validate function arguments with v.* validators and validate schema fields
  • Use actions for Node.js-only work ("use node") and remember actions can’t access ctx.db directly
  • Store file IDs in the database, not raw URLs; generate signed URLs for access
  • Design indexes to match access patterns and use built-in indexes where possible
  • Keep objects ASCII-only for field names; remap emojis or non-ASCII keys before storing
  • Use strict TypeScript types (Id<'table'>, Doc<'table'>) and annotate same-file calls

Example use cases

  • A Node.js action calling an external LLM API, then invoking a mutation to persist results
  • A POST /webhook HTTP endpoint that parses JSON and triggers internal functions
  • A scheduled job that runs cleanup every few minutes using crons.interval or ctx.scheduler.runAfter
  • Image upload flow generating an upload URL, saving file ID to _storage metadata, and returning a signed download URL
  • Schema with a compound index for multi-field queries and a search index for full-text queries

FAQ

Can actions access the Convex database (ctx.db)?

No. Actions cannot access ctx.db directly; call internal queries or mutations from actions to read or write data.

How should I store uploads in the database?

Store file IDs and metadata from the _storage table. Generate signed URLs for client upload/download instead of persisting raw URLs.