Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/meteor/meteor/llms.txt

Use this file to discover all available pages before exploring further.

Directory Structure

Meteor uses a convention-based file structure that determines where code runs and how it’s loaded.

Standard Layout

A typical Meteor project follows this organization:
my-app/
├── client/              # Client-only code (browser)
   ├── main.js         # Client entry point
   └── main.html       # HTML templates
├── server/              # Server-only code (Node.js)
   └── main.js         # Server entry point
├── imports/             # Lazy-loaded modules
   ├── api/            # Collections, methods, publications
   ├── ui/             # React/Blaze/Vue components
   └── startup/        # Initialization code
├── public/              # Static assets (served as-is)
   ├── images/
   └── fonts/
├── private/             # Server-only assets
├── tests/               # Test files
├── .meteor/             # Meteor configuration
   ├── packages        # Package dependencies
   ├── versions        # Locked package versions
   └── release         # Meteor version
├── package.json         # npm dependencies
└── package-lock.json    # Locked npm versions

Load Order Rules

Meteor loads files in a specific order based on their location:

1. Special Directories

Files in client/ run only in the browser. Meteor automatically excludes this code from the server bundle.
client/main.js
// This code runs only in the browser
import { Meteor } from 'meteor/meteor';
import React from 'react';
import { createRoot } from 'react-dom/client';
import App from '/imports/ui/App';

Meteor.startup(() => {
  const root = createRoot(document.getElementById('root'));
  root.render(<App />);
});
Files in server/ run only on the server (Node.js). This is where you put sensitive logic, API keys, and database operations.
server/main.js
// This code runs only on the server
import { Meteor } from 'meteor/meteor';
import '/imports/api/tasks';

Meteor.startup(() => {
  // Server initialization
  console.log('Server started');
});
Files in imports/ are not loaded automatically. You must explicitly import them. This enables code splitting and lazy loading.
imports/api/tasks.js
// Not loaded until explicitly imported
import { Mongo } from 'meteor/mongo';
import { Meteor } from 'meteor/meteor';

export const Tasks = new Mongo.Collection('tasks');

if (Meteor.isServer) {
  Meteor.publish('tasks', function() {
    return Tasks.find();
  });
}
Files in public/ are served as static assets. They’re accessible at the root URL.
public/images/logo.png → http://localhost:3000/images/logo.png
Files in private/ are accessible only to server code via the Assets API.
const data = Assets.getText('config.json');
const binary = Assets.getBinary('image.png');
Files matching *.test.js, *.tests.js, or inside tests/ are excluded from production builds.
tasks.test.js
import { Meteor } from 'meteor/meteor';
import { assert } from 'chai';
import { Tasks } from './tasks.js';

if (Meteor.isServer) {
  describe('Tasks', () => {
    it('can be created', () => {
      const taskId = Tasks.insert({ text: 'Test task' });
      assert.ok(taskId);
    });
  });
}

2. Load Priority

Within each directory, files load in this order:
  1. Files in subdirectories load before files in parent directories
  2. Files are sorted alphabetically by name
  3. main.* files load last
  4. Files in lib/ directories load first
Don’t rely on load order. Use explicit imports instead. Load order is a legacy feature maintained for backwards compatibility.

File Architecture Patterns

Use the imports/ directory with explicit imports:
// imports/api/collections/Tasks.js
import { Mongo } from 'meteor/mongo';
export const Tasks = new Mongo.Collection('tasks');

// imports/api/methods/tasks.js
import { Meteor } from 'meteor/meteor';
import { Tasks } from '../collections/Tasks';

Meteor.methods({
  'tasks.insert'(text) {
    return Tasks.insert({ text, createdAt: new Date() });
  }
});

// server/main.js
import '/imports/api/methods/tasks';
import '/imports/api/publications/tasks';

Split by Feature

Organize code by feature rather than by type:
imports/
├── features/
   ├── tasks/
   ├── api/
   ├── collection.js
   ├── methods.js
   └── publications.js
   ├── ui/
   ├── TaskList.jsx
   └── TaskItem.jsx
   └── index.js
   └── users/
       ├── api/
       └── ui/

The .meteor Directory

The .meteor/ directory contains Meteor-specific configuration:

packages

Lists Meteor packages used by your app:
# Meteor packages used by this project, one per line.
meteor-base@1.5.2
mobile-experience@1.1.1
mongo@2.0.0
reactive-var@1.0.13
tracker@1.3.4
ecmascript@0.17.0

versions

Locks exact package versions (like package-lock.json for npm):
allow-deny@1.1.1
autoupdate@2.0.0
babel-compiler@7.11.3
base64@1.0.13
...

release

Specifies the Meteor version:
METEOR@3.2.2
Commit .meteor/packages and .meteor/release to version control, but you can ignore .meteor/versions if using npm packages exclusively.

Build Output Structure

When you build a Meteor app, it generates a “star” archive with this structure:

Star Archive Layout

output/
└── bundle/
    ├── star.json           # Build metadata
    ├── README              # Deployment instructions
    ├── main.js             # Node.js entry point
    └── programs/
        ├── server/         # Server program
   ├── program.json
   ├── server.js
   ├── npm/
   └── assets/
        └── web.browser/    # Client program
            ├── program.json
            ├── index.html
            └── app/

star.json

Describes the build output:
{
  "format": "site-archive-pre1",
  "builtBy": "Meteor 3.2.2",
  "programs": [
    {
      "name": "web.browser",
      "arch": "web.browser",
      "path": "programs/web.browser"
    },
    {
      "name": "server",
      "arch": "os.linux.x86_64",
      "path": "programs/server"
    }
  ],
  "meteorRelease": "METEOR@3.2.2"
}

program.json

Each program has a program.json describing its resources: Web Program:
{
  "format": "web-program-pre1",
  "manifest": [
    {
      "path": "app/client.js",
      "where": "client",
      "type": "js",
      "cacheable": true,
      "url": "/client.js?hash=abc123",
      "size": 245678,
      "hash": "abc123..."
    }
  ]
}
Server Program:
{
  "load": [
    {
      "path": "server.js",
      "node_modules": "npm/node_modules",
      "assets": {
        "config.json": "assets/app/config.json"
      }
    }
  ]
}

Best Practices

Put all application code in imports/ and explicitly import it. This gives you:
  • Explicit dependency graph
  • Better code splitting
  • Easier testing
  • No reliance on load order
Keep client/main.js and server/main.js minimal - just imports:
client/main.js
import '/imports/startup/client';
server/main.js
import '/imports/startup/server';
Organize by feature, not by file type:✅ Good:
imports/features/tasks/
imports/features/users/
❌ Avoid:
imports/collections/
imports/methods/
imports/components/
Code outside client/ and server/ runs on both sides. Be careful with:
  • API keys (use server-only)
  • Node.js modules (check Meteor.isServer)
  • Browser APIs (check Meteor.isClient)

Repository Structure

The Meteor source code itself follows this structure:
meteor/
├── packages/           # 140+ core packages
├── tools/              # CLI & build system (Isobuild)
   ├── cli/           # Command implementations
   ├── isobuild/      # Build system
   └── tests/         # Tool tests
├── npm-packages/       # Published @meteorjs/* packages
├── scripts/            # Build & release automation
├── docs/               # Documentation
└── v3-docs/            # Meteor 3.x docs

Learn More

Explore how Meteor’s package system works and how packages are structured