vibesuite 1.3.3 → 2.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (75) hide show
  1. package/README.md +75 -6
  2. package/assets/.agent/skills/avoid-feature-creep/SKILL.md +307 -0
  3. package/assets/.agent/skills/avoid-feature-creep/agents/openai.yaml +3 -0
  4. package/assets/.agent/skills/avoid-feature-creep/assets/large-logo.png +0 -0
  5. package/assets/.agent/skills/avoid-feature-creep/assets/small-logo.svg +17 -0
  6. package/assets/.agent/skills/convex/SKILL.md +62 -0
  7. package/assets/.agent/skills/convex/agents/openai.yaml +3 -0
  8. package/assets/.agent/skills/convex/assets/large-logo.png +0 -0
  9. package/assets/.agent/skills/convex/assets/small-logo.svg +17 -0
  10. package/assets/.agent/skills/convex-agents/SKILL.md +516 -0
  11. package/assets/.agent/skills/convex-agents/agents/openai.yaml +3 -0
  12. package/assets/.agent/skills/convex-agents/assets/large-logo.png +0 -0
  13. package/assets/.agent/skills/convex-agents/assets/small-logo.svg +17 -0
  14. package/assets/.agent/skills/convex-best-practices/SKILL.md +369 -0
  15. package/assets/.agent/skills/convex-best-practices/agents/openai.yaml +3 -0
  16. package/assets/.agent/skills/convex-best-practices/assets/large-logo.png +0 -0
  17. package/assets/.agent/skills/convex-best-practices/assets/small-logo.svg +17 -0
  18. package/assets/.agent/skills/convex-component-authoring/SKILL.md +457 -0
  19. package/assets/.agent/skills/convex-component-authoring/agents/openai.yaml +3 -0
  20. package/assets/.agent/skills/convex-component-authoring/assets/large-logo.png +0 -0
  21. package/assets/.agent/skills/convex-component-authoring/assets/small-logo.svg +17 -0
  22. package/assets/.agent/skills/convex-cron-jobs/SKILL.md +604 -0
  23. package/assets/.agent/skills/convex-cron-jobs/agents/openai.yaml +3 -0
  24. package/assets/.agent/skills/convex-cron-jobs/assets/large-logo.png +0 -0
  25. package/assets/.agent/skills/convex-cron-jobs/assets/small-logo.svg +17 -0
  26. package/assets/.agent/skills/convex-file-storage/SKILL.md +467 -0
  27. package/assets/.agent/skills/convex-file-storage/agents/openai.yaml +3 -0
  28. package/assets/.agent/skills/convex-file-storage/assets/large-logo.png +0 -0
  29. package/assets/.agent/skills/convex-file-storage/assets/small-logo.svg +17 -0
  30. package/assets/.agent/skills/convex-functions/SKILL.md +458 -0
  31. package/assets/.agent/skills/convex-functions/agents/openai.yaml +3 -0
  32. package/assets/.agent/skills/convex-functions/assets/large-logo.png +0 -0
  33. package/assets/.agent/skills/convex-functions/assets/small-logo.svg +17 -0
  34. package/assets/.agent/skills/convex-http-actions/SKILL.md +733 -0
  35. package/assets/.agent/skills/convex-http-actions/agents/openai.yaml +3 -0
  36. package/assets/.agent/skills/convex-http-actions/assets/large-logo.png +0 -0
  37. package/assets/.agent/skills/convex-http-actions/assets/small-logo.svg +17 -0
  38. package/assets/.agent/skills/convex-migrations/SKILL.md +712 -0
  39. package/assets/.agent/skills/convex-migrations/agents/openai.yaml +3 -0
  40. package/assets/.agent/skills/convex-migrations/assets/large-logo.png +0 -0
  41. package/assets/.agent/skills/convex-migrations/assets/small-logo.svg +17 -0
  42. package/assets/.agent/skills/convex-realtime/SKILL.md +443 -0
  43. package/assets/.agent/skills/convex-realtime/agents/openai.yaml +3 -0
  44. package/assets/.agent/skills/convex-realtime/assets/large-logo.png +0 -0
  45. package/assets/.agent/skills/convex-realtime/assets/small-logo.svg +17 -0
  46. package/assets/.agent/skills/convex-schema-validator/SKILL.md +400 -0
  47. package/assets/.agent/skills/convex-schema-validator/agents/openai.yaml +3 -0
  48. package/assets/.agent/skills/convex-schema-validator/assets/large-logo.png +0 -0
  49. package/assets/.agent/skills/convex-schema-validator/assets/small-logo.svg +17 -0
  50. package/assets/.agent/skills/convex-security-audit/SKILL.md +539 -0
  51. package/assets/.agent/skills/convex-security-audit/agents/openai.yaml +3 -0
  52. package/assets/.agent/skills/convex-security-audit/assets/large-logo.png +0 -0
  53. package/assets/.agent/skills/convex-security-audit/assets/small-logo.svg +17 -0
  54. package/assets/.agent/skills/convex-security-check/SKILL.md +378 -0
  55. package/assets/.agent/skills/convex-security-check/agents/openai.yaml +3 -0
  56. package/assets/.agent/skills/convex-security-check/assets/large-logo.png +0 -0
  57. package/assets/.agent/skills/convex-security-check/assets/small-logo.svg +17 -0
  58. package/assets/.agent/skills/github-ops/SKILL.md +4 -4
  59. package/assets/.agent/skills/google-trends/SKILL.md +7 -7
  60. package/assets/.agent/skills/optimize-agent-context/SKILL.md +97 -0
  61. package/assets/.agent/skills/youtube-pipeline/SKILL.md +10 -10
  62. package/assets/.agent/workflows/LEGACY/init_smart_ops.md +2 -2
  63. package/assets/.agent/workflows/agent_reset.md +4 -6
  64. package/assets/.agent/workflows/mode-orchestrator.md +17 -22
  65. package/assets/.agent/workflows/mode-visionary.md +3 -10
  66. package/assets/.agent/workflows/optimize-agent-context.md +54 -0
  67. package/assets/.agent/workflows/remotion-build.md +17 -17
  68. package/assets/.agent/workflows/stitch.md +4 -4
  69. package/assets/VibeCode-Agents/vibe-orchestrator.yaml +14 -33
  70. package/assets/VibeCode-Agents/vibe-visionary.yaml +3 -13
  71. package/package.json +1 -1
  72. package/src/cli.js +416 -20
  73. package/src/harness.js +281 -0
  74. package/src/store.js +239 -0
  75. package/assets/VibeCode-Agents/custom_modes.yaml +0 -979
@@ -0,0 +1,604 @@
1
+ ---
2
+ name: convex-cron-jobs
3
+ displayName: Convex Cron Jobs
4
+ description: Scheduled function patterns for background tasks including interval scheduling, cron expressions, job monitoring, retry strategies, and best practices for long-running tasks
5
+ version: 1.0.0
6
+ author: Convex
7
+ tags: [convex, cron, scheduling, background-jobs, automation]
8
+ ---
9
+
10
+ # Convex Cron Jobs
11
+
12
+ Schedule recurring functions for background tasks, cleanup jobs, data syncing, and automated workflows in Convex applications.
13
+
14
+ ## Documentation Sources
15
+
16
+ Before implementing, do not assume; fetch the latest documentation:
17
+
18
+ - Primary: https://docs.convex.dev/scheduling/cron-jobs
19
+ - Scheduling Overview: https://docs.convex.dev/scheduling
20
+ - Scheduled Functions: https://docs.convex.dev/scheduling/scheduled-functions
21
+ - For broader context: https://docs.convex.dev/llms.txt
22
+
23
+ ## Instructions
24
+
25
+ ### Cron Jobs Overview
26
+
27
+ Convex cron jobs allow you to schedule functions to run at regular intervals or specific times. Key features:
28
+
29
+ - Run functions on a fixed schedule
30
+ - Support for interval-based and cron expression scheduling
31
+ - Automatic retries on failure
32
+ - Monitoring via the Convex dashboard
33
+
34
+ ### Basic Cron Setup
35
+
36
+ ```typescript
37
+ // convex/crons.ts
38
+ import { cronJobs } from "convex/server";
39
+ import { internal } from "./_generated/api";
40
+
41
+ const crons = cronJobs();
42
+
43
+ // Run every hour
44
+ crons.interval(
45
+ "cleanup expired sessions",
46
+ { hours: 1 },
47
+ internal.tasks.cleanupExpiredSessions,
48
+ {}
49
+ );
50
+
51
+ // Run every day at midnight UTC
52
+ crons.cron(
53
+ "daily report",
54
+ "0 0 * * *",
55
+ internal.reports.generateDailyReport,
56
+ {}
57
+ );
58
+
59
+ export default crons;
60
+ ```
61
+
62
+ ### Interval-Based Scheduling
63
+
64
+ Use `crons.interval` for simple recurring tasks:
65
+
66
+ ```typescript
67
+ // convex/crons.ts
68
+ import { cronJobs } from "convex/server";
69
+ import { internal } from "./_generated/api";
70
+
71
+ const crons = cronJobs();
72
+
73
+ // Every 5 minutes
74
+ crons.interval(
75
+ "sync external data",
76
+ { minutes: 5 },
77
+ internal.sync.fetchExternalData,
78
+ {}
79
+ );
80
+
81
+ // Every 2 hours
82
+ crons.interval(
83
+ "cleanup temp files",
84
+ { hours: 2 },
85
+ internal.files.cleanupTempFiles,
86
+ {}
87
+ );
88
+
89
+ // Every 30 seconds (minimum interval)
90
+ crons.interval(
91
+ "health check",
92
+ { seconds: 30 },
93
+ internal.monitoring.healthCheck,
94
+ {}
95
+ );
96
+
97
+ export default crons;
98
+ ```
99
+
100
+ ### Cron Expression Scheduling
101
+
102
+ Use `crons.cron` for precise scheduling with cron expressions:
103
+
104
+ ```typescript
105
+ // convex/crons.ts
106
+ import { cronJobs } from "convex/server";
107
+ import { internal } from "./_generated/api";
108
+
109
+ const crons = cronJobs();
110
+
111
+ // Every day at 9 AM UTC
112
+ crons.cron(
113
+ "morning notifications",
114
+ "0 9 * * *",
115
+ internal.notifications.sendMorningDigest,
116
+ {}
117
+ );
118
+
119
+ // Every Monday at 8 AM UTC
120
+ crons.cron(
121
+ "weekly summary",
122
+ "0 8 * * 1",
123
+ internal.reports.generateWeeklySummary,
124
+ {}
125
+ );
126
+
127
+ // First day of every month at midnight
128
+ crons.cron(
129
+ "monthly billing",
130
+ "0 0 1 * *",
131
+ internal.billing.processMonthlyBilling,
132
+ {}
133
+ );
134
+
135
+ // Every 15 minutes
136
+ crons.cron(
137
+ "frequent sync",
138
+ "*/15 * * * *",
139
+ internal.sync.syncData,
140
+ {}
141
+ );
142
+
143
+ export default crons;
144
+ ```
145
+
146
+ ### Cron Expression Reference
147
+
148
+ ```
149
+ ┌───────────── minute (0-59)
150
+ │ ┌───────────── hour (0-23)
151
+ │ │ ┌───────────── day of month (1-31)
152
+ │ │ │ ┌───────────── month (1-12)
153
+ │ │ │ │ ┌───────────── day of week (0-6, Sunday=0)
154
+ │ │ │ │ │
155
+ * * * * *
156
+ ```
157
+
158
+ Common patterns:
159
+ - `* * * * *` - Every minute
160
+ - `0 * * * *` - Every hour
161
+ - `0 0 * * *` - Every day at midnight
162
+ - `0 0 * * 0` - Every Sunday at midnight
163
+ - `0 0 1 * *` - First day of every month
164
+ - `*/5 * * * *` - Every 5 minutes
165
+ - `0 9-17 * * 1-5` - Every hour from 9 AM to 5 PM, Monday through Friday
166
+
167
+ ### Internal Functions for Crons
168
+
169
+ Cron jobs should call internal functions for security:
170
+
171
+ ```typescript
172
+ // convex/tasks.ts
173
+ import { internalMutation, internalQuery } from "./_generated/server";
174
+ import { v } from "convex/values";
175
+
176
+ // Cleanup expired sessions
177
+ export const cleanupExpiredSessions = internalMutation({
178
+ args: {},
179
+ returns: v.number(),
180
+ handler: async (ctx) => {
181
+ const oneHourAgo = Date.now() - 60 * 60 * 1000;
182
+
183
+ const expiredSessions = await ctx.db
184
+ .query("sessions")
185
+ .withIndex("by_lastActive")
186
+ .filter((q) => q.lt(q.field("lastActive"), oneHourAgo))
187
+ .collect();
188
+
189
+ for (const session of expiredSessions) {
190
+ await ctx.db.delete(session._id);
191
+ }
192
+
193
+ return expiredSessions.length;
194
+ },
195
+ });
196
+
197
+ // Process pending tasks
198
+ export const processPendingTasks = internalMutation({
199
+ args: {},
200
+ returns: v.null(),
201
+ handler: async (ctx) => {
202
+ const pendingTasks = await ctx.db
203
+ .query("tasks")
204
+ .withIndex("by_status", (q) => q.eq("status", "pending"))
205
+ .take(100);
206
+
207
+ for (const task of pendingTasks) {
208
+ await ctx.db.patch(task._id, {
209
+ status: "processing",
210
+ startedAt: Date.now(),
211
+ });
212
+
213
+ // Schedule the actual processing
214
+ await ctx.scheduler.runAfter(0, internal.tasks.processTask, {
215
+ taskId: task._id,
216
+ });
217
+ }
218
+
219
+ return null;
220
+ },
221
+ });
222
+ ```
223
+
224
+ ### Cron Jobs with Arguments
225
+
226
+ Pass static arguments to cron jobs:
227
+
228
+ ```typescript
229
+ // convex/crons.ts
230
+ import { cronJobs } from "convex/server";
231
+ import { internal } from "./_generated/api";
232
+
233
+ const crons = cronJobs();
234
+
235
+ // Different cleanup intervals for different types
236
+ crons.interval(
237
+ "cleanup temp files",
238
+ { hours: 1 },
239
+ internal.cleanup.cleanupByType,
240
+ { fileType: "temp", maxAge: 3600000 }
241
+ );
242
+
243
+ crons.interval(
244
+ "cleanup cache files",
245
+ { hours: 24 },
246
+ internal.cleanup.cleanupByType,
247
+ { fileType: "cache", maxAge: 86400000 }
248
+ );
249
+
250
+ export default crons;
251
+ ```
252
+
253
+ ```typescript
254
+ // convex/cleanup.ts
255
+ import { internalMutation } from "./_generated/server";
256
+ import { v } from "convex/values";
257
+
258
+ export const cleanupByType = internalMutation({
259
+ args: {
260
+ fileType: v.string(),
261
+ maxAge: v.number(),
262
+ },
263
+ returns: v.number(),
264
+ handler: async (ctx, args) => {
265
+ const cutoff = Date.now() - args.maxAge;
266
+
267
+ const oldFiles = await ctx.db
268
+ .query("files")
269
+ .withIndex("by_type_and_created", (q) =>
270
+ q.eq("type", args.fileType).lt("createdAt", cutoff)
271
+ )
272
+ .collect();
273
+
274
+ for (const file of oldFiles) {
275
+ await ctx.storage.delete(file.storageId);
276
+ await ctx.db.delete(file._id);
277
+ }
278
+
279
+ return oldFiles.length;
280
+ },
281
+ });
282
+ ```
283
+
284
+ ### Monitoring and Logging
285
+
286
+ Add logging to track cron job execution:
287
+
288
+ ```typescript
289
+ // convex/tasks.ts
290
+ import { internalMutation } from "./_generated/server";
291
+ import { v } from "convex/values";
292
+
293
+ export const cleanupWithLogging = internalMutation({
294
+ args: {},
295
+ returns: v.null(),
296
+ handler: async (ctx) => {
297
+ const startTime = Date.now();
298
+ let processedCount = 0;
299
+ let errorCount = 0;
300
+
301
+ try {
302
+ const expiredItems = await ctx.db
303
+ .query("items")
304
+ .withIndex("by_expiresAt")
305
+ .filter((q) => q.lt(q.field("expiresAt"), Date.now()))
306
+ .collect();
307
+
308
+ for (const item of expiredItems) {
309
+ try {
310
+ await ctx.db.delete(item._id);
311
+ processedCount++;
312
+ } catch (error) {
313
+ errorCount++;
314
+ console.error(`Failed to delete item ${item._id}:`, error);
315
+ }
316
+ }
317
+
318
+ // Log job completion
319
+ await ctx.db.insert("cronLogs", {
320
+ jobName: "cleanup",
321
+ startTime,
322
+ endTime: Date.now(),
323
+ duration: Date.now() - startTime,
324
+ processedCount,
325
+ errorCount,
326
+ status: errorCount === 0 ? "success" : "partial",
327
+ });
328
+ } catch (error) {
329
+ // Log job failure
330
+ await ctx.db.insert("cronLogs", {
331
+ jobName: "cleanup",
332
+ startTime,
333
+ endTime: Date.now(),
334
+ duration: Date.now() - startTime,
335
+ processedCount,
336
+ errorCount,
337
+ status: "failed",
338
+ error: String(error),
339
+ });
340
+ throw error;
341
+ }
342
+
343
+ return null;
344
+ },
345
+ });
346
+ ```
347
+
348
+ ### Batching for Large Datasets
349
+
350
+ Handle large datasets in batches to avoid timeouts:
351
+
352
+ ```typescript
353
+ // convex/tasks.ts
354
+ import { internalMutation } from "./_generated/server";
355
+ import { internal } from "./_generated/api";
356
+ import { v } from "convex/values";
357
+
358
+ const BATCH_SIZE = 100;
359
+
360
+ export const processBatch = internalMutation({
361
+ args: {
362
+ cursor: v.optional(v.string()),
363
+ },
364
+ returns: v.null(),
365
+ handler: async (ctx, args) => {
366
+ const result = await ctx.db
367
+ .query("items")
368
+ .withIndex("by_status", (q) => q.eq("status", "pending"))
369
+ .paginate({ numItems: BATCH_SIZE, cursor: args.cursor ?? null });
370
+
371
+ for (const item of result.page) {
372
+ await ctx.db.patch(item._id, {
373
+ status: "processed",
374
+ processedAt: Date.now(),
375
+ });
376
+ }
377
+
378
+ // Schedule next batch if there are more items
379
+ if (!result.isDone) {
380
+ await ctx.scheduler.runAfter(0, internal.tasks.processBatch, {
381
+ cursor: result.continueCursor,
382
+ });
383
+ }
384
+
385
+ return null;
386
+ },
387
+ });
388
+ ```
389
+
390
+ ### External API Calls in Crons
391
+
392
+ Use actions for external API calls:
393
+
394
+ ```typescript
395
+ // convex/sync.ts
396
+ "use node";
397
+
398
+ import { internalAction } from "./_generated/server";
399
+ import { internal } from "./_generated/api";
400
+ import { v } from "convex/values";
401
+
402
+ export const syncExternalData = internalAction({
403
+ args: {},
404
+ returns: v.null(),
405
+ handler: async (ctx) => {
406
+ // Fetch from external API
407
+ const response = await fetch("https://api.example.com/data", {
408
+ headers: {
409
+ Authorization: `Bearer ${process.env.API_KEY}`,
410
+ },
411
+ });
412
+
413
+ if (!response.ok) {
414
+ throw new Error(`API request failed: ${response.status}`);
415
+ }
416
+
417
+ const data = await response.json();
418
+
419
+ // Store the data using a mutation
420
+ await ctx.runMutation(internal.sync.storeExternalData, {
421
+ data,
422
+ syncedAt: Date.now(),
423
+ });
424
+
425
+ return null;
426
+ },
427
+ });
428
+
429
+ export const storeExternalData = internalMutation({
430
+ args: {
431
+ data: v.any(),
432
+ syncedAt: v.number(),
433
+ },
434
+ returns: v.null(),
435
+ handler: async (ctx, args) => {
436
+ await ctx.db.insert("externalData", {
437
+ data: args.data,
438
+ syncedAt: args.syncedAt,
439
+ });
440
+ return null;
441
+ },
442
+ });
443
+ ```
444
+
445
+ ```typescript
446
+ // convex/crons.ts
447
+ import { cronJobs } from "convex/server";
448
+ import { internal } from "./_generated/api";
449
+
450
+ const crons = cronJobs();
451
+
452
+ crons.interval(
453
+ "sync external data",
454
+ { minutes: 15 },
455
+ internal.sync.syncExternalData,
456
+ {}
457
+ );
458
+
459
+ export default crons;
460
+ ```
461
+
462
+ ## Examples
463
+
464
+ ### Schema for Cron Job Logging
465
+
466
+ ```typescript
467
+ // convex/schema.ts
468
+ import { defineSchema, defineTable } from "convex/server";
469
+ import { v } from "convex/values";
470
+
471
+ export default defineSchema({
472
+ cronLogs: defineTable({
473
+ jobName: v.string(),
474
+ startTime: v.number(),
475
+ endTime: v.number(),
476
+ duration: v.number(),
477
+ processedCount: v.number(),
478
+ errorCount: v.number(),
479
+ status: v.union(
480
+ v.literal("success"),
481
+ v.literal("partial"),
482
+ v.literal("failed")
483
+ ),
484
+ error: v.optional(v.string()),
485
+ })
486
+ .index("by_job", ["jobName"])
487
+ .index("by_status", ["status"])
488
+ .index("by_startTime", ["startTime"]),
489
+
490
+ sessions: defineTable({
491
+ userId: v.id("users"),
492
+ token: v.string(),
493
+ lastActive: v.number(),
494
+ expiresAt: v.number(),
495
+ })
496
+ .index("by_user", ["userId"])
497
+ .index("by_lastActive", ["lastActive"])
498
+ .index("by_expiresAt", ["expiresAt"]),
499
+
500
+ tasks: defineTable({
501
+ type: v.string(),
502
+ status: v.union(
503
+ v.literal("pending"),
504
+ v.literal("processing"),
505
+ v.literal("completed"),
506
+ v.literal("failed")
507
+ ),
508
+ data: v.any(),
509
+ createdAt: v.number(),
510
+ startedAt: v.optional(v.number()),
511
+ completedAt: v.optional(v.number()),
512
+ })
513
+ .index("by_status", ["status"])
514
+ .index("by_type_and_status", ["type", "status"]),
515
+ });
516
+ ```
517
+
518
+ ### Complete Cron Configuration Example
519
+
520
+ ```typescript
521
+ // convex/crons.ts
522
+ import { cronJobs } from "convex/server";
523
+ import { internal } from "./_generated/api";
524
+
525
+ const crons = cronJobs();
526
+
527
+ // Cleanup jobs
528
+ crons.interval(
529
+ "cleanup expired sessions",
530
+ { hours: 1 },
531
+ internal.cleanup.expiredSessions,
532
+ {}
533
+ );
534
+
535
+ crons.interval(
536
+ "cleanup old logs",
537
+ { hours: 24 },
538
+ internal.cleanup.oldLogs,
539
+ { maxAgeDays: 30 }
540
+ );
541
+
542
+ // Sync jobs
543
+ crons.interval(
544
+ "sync user data",
545
+ { minutes: 15 },
546
+ internal.sync.userData,
547
+ {}
548
+ );
549
+
550
+ // Report jobs
551
+ crons.cron(
552
+ "daily analytics",
553
+ "0 1 * * *",
554
+ internal.reports.dailyAnalytics,
555
+ {}
556
+ );
557
+
558
+ crons.cron(
559
+ "weekly summary",
560
+ "0 9 * * 1",
561
+ internal.reports.weeklySummary,
562
+ {}
563
+ );
564
+
565
+ // Health checks
566
+ crons.interval(
567
+ "service health check",
568
+ { minutes: 5 },
569
+ internal.monitoring.healthCheck,
570
+ {}
571
+ );
572
+
573
+ export default crons;
574
+ ```
575
+
576
+ ## Best Practices
577
+
578
+ - Never run `npx convex deploy` unless explicitly instructed
579
+ - Never run any git commands unless explicitly instructed
580
+ - Only use `crons.interval` or `crons.cron` methods, not deprecated helpers
581
+ - Always call internal functions from cron jobs for security
582
+ - Import `internal` from `_generated/api` even for functions in the same file
583
+ - Add logging and monitoring for production cron jobs
584
+ - Use batching for operations that process large datasets
585
+ - Handle errors gracefully to prevent job failures
586
+ - Use meaningful job names for dashboard visibility
587
+ - Consider timezone when using cron expressions (Convex uses UTC)
588
+
589
+ ## Common Pitfalls
590
+
591
+ 1. **Using public functions** - Cron jobs should call internal functions only
592
+ 2. **Long-running mutations** - Break large operations into batches
593
+ 3. **Missing error handling** - Unhandled errors will fail the entire job
594
+ 4. **Forgetting timezone** - All cron expressions use UTC
595
+ 5. **Using deprecated helpers** - Avoid `crons.hourly`, `crons.daily`, etc.
596
+ 6. **Not logging execution** - Makes debugging production issues difficult
597
+
598
+ ## References
599
+
600
+ - Convex Documentation: https://docs.convex.dev/
601
+ - Convex LLMs.txt: https://docs.convex.dev/llms.txt
602
+ - Cron Jobs: https://docs.convex.dev/scheduling/cron-jobs
603
+ - Scheduling Overview: https://docs.convex.dev/scheduling
604
+ - Scheduled Functions: https://docs.convex.dev/scheduling/scheduled-functions
@@ -0,0 +1,3 @@
1
+ interface:
2
+ icon_small: "./assets/small-logo.svg"
3
+ icon_large: "./assets/large-logo.png"
@@ -0,0 +1,17 @@
1
+ <svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <g clip-path="url(#clip0_3_23)">
3
+ <g clip-path="url(#clip1_3_23)">
4
+ <path d="M10.0643 12.5735C12.3769 12.3166 14.5572 11.0843 15.7577 9.02756C15.1892 14.1148 9.62646 17.3302 5.08583 15.356C4.66743 15.1746 4.30728 14.8728 4.06013 14.4848C3.03973 12.8825 2.7043 10.8437 3.18626 8.99344C4.56327 11.37 7.3632 12.8267 10.0643 12.5735Z" fill="#F3B01C"/>
5
+ <path d="M3.1018 7.50072C2.16436 9.66714 2.12376 12.2034 3.27303 14.2907C-0.771507 11.2479 -0.72737 4.7362 3.2236 1.72378C3.58904 1.44535 4.02333 1.2801 4.47881 1.25494C6.3519 1.15614 8.25501 1.88006 9.58963 3.22909C6.87799 3.25604 4.23695 4.99308 3.1018 7.50072Z" fill="#8D2676"/>
6
+ <path d="M10.8974 3.89562C9.52924 1.98794 7.38779 0.68921 5.04156 0.649695C9.57686 -1.40888 15.1555 1.92867 15.7629 6.86314C15.8194 7.32119 15.7452 7.78824 15.5421 8.20138C14.6948 9.92223 13.1236 11.2569 11.2876 11.7508C12.6328 9.25579 12.4668 6.20748 10.8974 3.89562Z" fill="#EE342F"/>
7
+ </g>
8
+ </g>
9
+ <defs>
10
+ <clipPath id="clip0_3_23">
11
+ <rect width="16" height="16" fill="white"/>
12
+ </clipPath>
13
+ <clipPath id="clip1_3_23">
14
+ <rect width="16" height="16" fill="white"/>
15
+ </clipPath>
16
+ </defs>
17
+ </svg>