| name | meteor-3 |
| description | Use this skill whenever building, modifying, planning, scaffolding, testing, or debugging Meteor 3.x applications (Meteor 3.0 through 3.5+). Triggers on requests involving Meteor, Meteor.js, DDP, Minimongo, Atmosphere packages, `meteor create`, Blaze, Tracker, `Meteor.methods`, `Meteor.publish`, `Mongo.Collection`, `Meteor.callAsync`, `findOneAsync`, `insertAsync`, `updateAsync`, or any Meteor 3.x API. Also use when the user mentions Galaxy, MUP, Cordova with Meteor, or is migrating from Meteor 2.x (Fibers) to 3.x (async/await). Covers full-stack reactive architecture, collections/methods/publications, accounts, routing, security, testing, deployment, mobile, and package authoring. Provides scaffold scripts for fast, token-efficient agentic coding. Do NOT use for non-Meteor Node.js apps or Meteor 1.x/2.x projects that have not begun async migration.
|
| license | MIT |
| compatibility | Meteor 3.0+ (Node 22-24.15), MongoDB 6+ required for change streams |
| metadata | {"author":"agent-skills","version":"1.1","meteor-version":"3.5","tags":["meteor","fullstack","ddp","mongodb","async","rspack"]} |
Meteor 3 Developer Skill
Meteor 3 is a full-stack JavaScript platform built on Node 22-24.15, Express 5, and MongoDB driver 6.x. The defining change from Meteor 2 is the removal of Fibers: all server-side APIs that were synchronous are now async and return Promises. This skill targets Meteor 3.5+ and assumes async-first patterns throughout. New apps use the modern build stack (Rspack + SWC) by default.
Gotchas (read these first)
-
Server collections are async-only. findOne, insert, update, remove, fetch, count, forEach, map, observe, observeChanges all throw on the server. Use the *Async variants: findOneAsync, insertAsync, updateAsync, removeAsync, fetchAsync, countAsync, forEachAsync, mapAsync, observeAsync, observeChangesAsync. On the client, sync methods still work for reactivity โ only use *Async on the client when sharing isomorphic code.
-
Meteor.call โ Meteor.callAsync. On the client, use await Meteor.callAsync('name', ...args) for any method with an async stub. Meteor.call still works for sync-stub methods but logs a warning otherwise. On the server, Meteor.call is gone โ use Meteor.callAsync or call the function directly.
-
Meteor.user() is async on the server. Use await Meteor.userAsync(). On the client, Meteor.user() is still synchronous and reactive.
-
Meteor.wrapAsync is removed. Convert callback APIs with util.promisify or wrap in new Promise(...).
-
HTTP.call is deprecated. Use import { fetch } from 'meteor/fetch' (WHATWG fetch).
-
Email.send is removed. Use await Email.sendAsync({...}).
-
Assets.getText / Assets.getBinary are removed. Use await Assets.getTextAsync(path) / await Assets.getBinaryAsync(path).
-
Express 5 replaced Connect. โ . โ .
Quick Start
Create a new app and run it:
meteor create myapp
meteor create myapp --blaze
meteor create myapp --vue
meteor create myapp --svelte
meteor create myapp --solid
meteor create myapp --typescript
meteor create myapp --tailwind
meteor create myapp --apollo
cd myapp
meteor npm install
meteor
Create a full imports-based structure (recommended for real apps):
meteor create myapp --full
Scaffold a CRUD module in an existing project:
meteor generate tasks
meteor generate tasks --path=server/admin
Scaffold Scripts (token-efficient code generation)
This skill bundles scripts that generate consistent, idiomatic Meteor 3 code. Always prefer these scripts over hand-writing boilerplate โ they produce correct async patterns, naming conventions, and file structure without burning LLM tokens on repetitive code.
When to use meteor generate vs skill scripts:
meteor generate <name> (built-in CLI): Use for basic CRUD modules. Produces idiomatic Meteor 3 async code (exported async functions + Meteor.methods wrapper). Fastest, no script dependency.
scaffold-module.sh: Use when you need --with-schema (simpl-schema), --with-tests, or a custom --path.
scaffold-method.sh / scaffold-publication.sh: Use to add individual methods/publications to existing modules.
scaffold-react-component.sh / scaffold-blaze-template.sh: Use for UI components (not covered by meteor generate).
scaffold-migration.sh / scaffold-settings.sh: Use for migrations and settings (not covered by meteor generate).
Run scripts from the project root (where .meteor/ lives).
scripts/scaffold-module.sh โ Generate a complete API module
Generates a collection, methods, publications, schema, tests, and index file for a domain entity in imports/api/:
bash scripts/scaffold-module.sh <entity-name> [--typescript] [--with-schema] [--with-tests]
bash scripts/scaffold-module.sh tasks --typescript --with-schema --with-tests
scripts/scaffold-method.sh โ Generate a single method
bash scripts/scaffold-method.sh <entity> <action> [--typescript]
bash scripts/scaffold-method.sh tasks insert --typescript
scripts/scaffold-publication.sh โ Generate a publication
bash scripts/scaffold-publication.sh <entity> <publication-name> [--typescript]
bash scripts/scaffold-publication.sh tasks tasks.byOwner --typescript
scripts/scaffold-react-component.sh โ Generate a React + Meteor data component
bash scripts/scaffold-react-component.sh <ComponentName> [--typescript]
bash scripts/scaffold-react-component.sh TaskList --typescript
scripts/scaffold-blaze-template.sh โ Generate a Blaze template (html + js)
bash scripts/scaffold-blaze-template.sh <template_name>
bash scripts/scaffold-blaze-template.sh task_item
scripts/scaffold-migration.sh โ Generate a migration file
bash scripts/scaffold-migration.sh <version> <description>
bash scripts/scaffold-migration.sh 2 add-index-to-tasks
scripts/scaffold-settings.sh โ Generate settings.json files
bash scripts/scaffold-settings.sh
scripts/check-async.sh โ Scan for old sync APIs (migration helper)
bash scripts/check-async.sh
Reference Files (must read before coding)
Before writing any code for a task, you MUST read the corresponding reference file. These files contain detailed API signatures, edge cases, and security patterns that are not repeated in this main skill file. Skipping them will produce incorrect or insecure code.
| Task | You must read |
|---|
| Async API mapping (v2 โ v3), migration patterns | references/async-api-map.md |
| Collections, schemas, indexes, denormalization, collation | references/collections.md |
Methods, validation, rate limiting, jam:method | references/methods.md |
| Publications, subscriptions, low-level publish, strategies | references/publications.md |
| Accounts, OAuth, 2FA, email templates, roles, HttpOnly cookies | references/accounts.md |
React integration (useTracker, useSubscribe, suspense) | references/react-integration.md |
| Blaze integration (async helpers, templates) | references/blaze-integration.md |
| Routing (Flow Router, server routes, dynamic imports) | references/routing.md |
Security checklist, allow/deny, rate limiting, CSP, accounts-express | references/security.md |
| Testing (Mocha, factories, Cypress, CI) | references/testing.md |
Deployment (Galaxy, MUP, Docker, meteor build, PWA) | references/deployment.md |
| Modern build stack (Rspack, SWC, CSS, aliases, PWA) | references/build-stack.md |
| Performance (change streams, DDP transport, compression, monitoring) | references/performance.md |
| Community packages (jam:method, meteor-rpc, cluster, transactions) | references/community-packages.md |
| Mobile / Cordova (config, plugins, HCP, build) | references/mobile-cordova.md |
| Package authoring (Atmosphere, npm, build plugins) | references/packages.md |
| Environment variables and settings | references/environment.md |
| CLI commands reference |
Project Structure (Meteor 3 recommended)
myapp/
โโโ .meteor/
โโโ client/
โ โโโ main.html # <head>, <body> with #app
โ โโโ main.js # eager entry: import '/imports/startup/client'
โโโ server/
โ โโโ main.js # eager entry: import '/imports/startup/server'
โโโ imports/
โ โโโ startup/
โ โ โโโ client/
โ โ โ โโโ index.js
โ โ โ โโโ routes.js
โ โ โ โโโ useraccounts-configuration.js
โ โ โโโ server/
โ โ โโโ index.js
โ โ โโโ fixtures.js
โ โ โโโ register-api.js
โ โโโ api/
โ โ โโโ tasks/
โ โ โโโ collection.ts
โ โ โโโ schema.ts
โ โ โโโ methods.ts
โ โ โโโ publications.ts
โ โ โโโ tasks.tests.ts
โ โ โโโ index.ts
โ โโโ ui/
โ โโโ components/
โ โโโ layouts/
โ โโโ pages/
โโโ public/ # static assets served as-is
โโโ private/ # server-only assets (Assets.getTextAsync)
โโโ settings/
โ โโโ development.json
โ โโโ production.json
โโโ mobile-config.js # Cordova config (if mobile)
โโโ package.json
โโโ tsconfig.json # if TypeScript
Key rules:
client/ and server/ are eager entry points โ keep them thin (one import line).
- Everything else goes in
imports/ (lazily loaded, tree-shakeable).
- Set
meteor.mainModule in package.json for explicit entry points:
{
"meteor": {
"mainModule": {
"client": "client/main.js",
"server": "server/main.js"
}
}
}
Core Async Patterns (Meteor 3)
Collection CRUD
const doc = await MyCollection.findOneAsync({ _id: '123' });
const id = await MyCollection.insertAsync({ name: 'foo', createdAt: new Date() });
await MyCollection.updateAsync(id, { $set: { name: 'bar' } });
await MyCollection.removeAsync(id);
const docs = await MyCollection.find({ active: true }).fetchAsync();
const count = await MyCollection.find({}).countAsync();
await MyCollection.createIndexAsync({ email: 1 }, { unique: true });
const doc = MyCollection.findOne('123');
const docs = .({}).();
Methods (RPC)
import { Meteor } from 'meteor/meteor';
import { check } from 'meteor/check';
import { TasksCollection } from './collection';
Meteor.methods({
async 'tasks.insert'({ text, userId }) {
check(text, String);
check(userId, String);
if (!this.userId) throw new Meteor.Error('not-authorized');
return TasksCollection.insertAsync({
text,
owner: this.userId,
createdAt: new Date(),
});
},
async 'tasks.toggleComplete'({ taskId }) {
check(taskId, String);
const task = await TasksCollection.findOneAsync(taskId);
if (!task) throw new Meteor.Error();
(task. !== .) .();
.(taskId, { : { : !task. } });
},
});
result = .(, { : , : .() });
Publications
import { Meteor } from 'meteor/meteor';
import { check } from 'meteor/check';
import { TasksCollection } from './collection';
Meteor.publish('tasks.byOwner', async function () {
if (!this.userId) return this.ready();
return TasksCollection.find(
{ owner: this.userId },
{ projection: { text: 1, completed: 1, createdAt: 1 } }
);
});
React with Meteor data
import { useTracker, useSubscribe } from 'meteor/react-meteor-data';
import { TasksCollection } from '/imports/api/tasks/collection';
function TaskList() {
const isLoading = useSubscribe('tasks.byOwner');
const tasks = useTracker(() =>
TasksCollection.find({}, { sort: { createdAt: -1 } }).fetch()
);
if (isLoading()) return <Loading />;
return tasks.map(t => <TaskItem key={t._id} task={t} />);
}
Express middleware (WebApp)
import { WebApp } from 'meteor/webapp';
import { Meteor } from 'meteor/meteor';
WebApp.handlers.use('/api/health', Meteor.bindEnvironment(async (req, res) => {
const user = await Meteor.userAsync();
res.json({ status: 'ok', user: user?.username });
}));
Key Packages (Meteor 3.5)
| Package | Purpose |
|---|
meteor-base | Core bundle (autoupdate, hot-code-push, etc.) |
mongo | MongoDB collections + change streams |
rspack | Rspack bundler integration (default for new apps in 3.4+) |
accounts-password | Password auth (Argon2 support since 3.0) |
accounts-express | Authenticated REST endpoints via Accounts.auth() middleware (3.5) |
accounts-google/facebook/github | OAuth providers |
react-meteor-data | useTracker, useSubscribe, useFind hooks |
ecmascript | Babel ES2015+ transpilation |
typescript | TypeScript support |
hot-module-replacement | HMR for React/Blaze/Svelte/Vue |
fetch | WHATWG fetch() polyfill (replaces http) |
email | Email.sendAsync() via Nodemailer |
check | Argument validation |
ddp-rate-limiter | Rate limit methods/subscriptions (async matchers in 3.5) |
ostrio:flow-router-extra | Client routing (recommended) |
jam:method | Boilerplate-free methods with schema + rate limiting |
grubba-rpc | Type-safe RPC with Zod schemas and client/server type inference |
aldeed:collection2 | Schema-validated collections (v4 bundles simple-schema) |
meteortesting:mocha | Test runner |
percolate:migrations | Database migrations |
|
When the user asks to build a Meteor feature
- Check if a scaffold script covers it โ run the script first, then customize.
- Always use async server-side โ
*Async collection methods, Meteor.callAsync, await Meteor.userAsync().
- Validate inputs โ
check() or simpl-schema in every method and publication.
- Use
this.userId โ never pass userId from the client.
- Restrict publication fields โ always set
projection (or fields).
- Check if Rspack is configured โ new apps use Rspack by default; existing apps may need
meteor add rspack and "modern": true in package.json.
- Read the relevant reference file for detailed API signatures and edge cases.
- Run
meteor lint to catch issues after changes.
- Test with
meteor test --driver-package meteortesting:mocha.
Meteor 3.5 Highlights
- Modern Build Stack: Rspack bundler integration (3.4+) + SWC transpiler (3.3+) โ 4x faster builds, 8x smaller bundles. New apps use this by default. See
references/build-stack.md.
- MongoDB Change Streams as default reactivity (MongoDB 6+ required). Major resource savings, works on serverless/Atlas Shared tiers. See
references/performance.md.
- DDP Session Resumption: clients resume within
disconnectGracePeriod (default 15s) after reconnect. onConnection is NOT called on resume โ use DDP.onReconnect and heartbeat-based presence.
- Pluggable DDP Transport:
DDP_TRANSPORT=uws for lower latency, DISABLE_SOCKJS=true to drop SockJS entirely.
accounts-express: authenticated REST endpoints via Accounts.auth() middleware.
- Async DDPRateLimiter rules: matchers can be async (fetch from DB to gate by role/tier).
- MongoDB Collation: case-insensitive queries via
{ collation: { locale, strength } } on both client and server.
- Argon2 password hashing (3.0+):
Accounts.config({ argon2Enabled: true }).
Meteor.loginWithPasswordAsync / Meteor.loginWithTokenAsync / Meteor.logoutAllClientsAsync.
- Collection Extensions in core (3.4):
Mongo.Collection.addExtension, addPrototypeMethod, addStaticMethod.
Meteor.deferDev / Meteor.deferProd (3.4): defer non-critical setup per environment.
- HttpOnly cookies for accounts (3.3):
Accounts.config({ useHttpOnlyCookies: true }).
- Service Worker / PWA support (3.4.1): Workbox integration via Rspack.
- Node.js 24.15, Express 5, MongoDB driver 6.x.