---
url: /api/accounts.md
---
# Accounts
## Accounts-base {#accounts-base}
The Meteor Accounts system builds on top of the `userId` support in
[`publish`](./meteor#Subscription-userId) and [`methods`](./meteor#methods-userId). The core
packages add the concept of user documents stored in the database, and
additional packages add [secure password authentication](#passwords),
[integration with third party login services](#Meteor-loginWith%3CExternalService%3E),
and a [pre-built userinterface](/packages/accounts-ui.html).
The basic Accounts system is in the `accounts-base` package, but
applications typically include this automatically by adding one of the
login provider packages: `accounts-password`, `accounts-facebook`,
`accounts-github`, `accounts-google`, `accounts-meetup`,
`accounts-twitter`, or `accounts-weibo`.
Read more about customizing user accounts in the [Accounts](http://guide.meteor.com/accounts.html) article in the Meteor Guide.
### Accounts with Session Storage {#accounts-session-storage}
By default, Meteor uses Local Storage to store, among other things, login tokens in your browser session. But, for some applications, it makes sense to use Session Storage instead. Session Storage will not persist across client sessions. You can achieve this by adding this to your settings:
```json
{
// ... all other settings,
"public": {
// ... all your public settings
"packages": {
"accounts": {
"clientStorage": "session"
}
}
}
}
```
Retrieves the user record for the current user from
the [`Meteor.users`](#Meteor-users) collection.
On the client, the available fields will be those that
are published from the server (other fields won't be available on the
client). By default the server publishes `username`, `emails`, and
`profile` (writable by user). See [`Meteor.users`](#Meteor-users) for more on
the fields used in user documents.
On the server, this will fetch the record from the database. To improve the
latency of a method that uses the user document multiple times, save the
returned record to a variable instead of re-calling `Meteor.user()`.
Fetching the full user document can cause unnecessary database usage on the
server and over-reactivity on the client, particularly if you store lots of
custom data on it. Therefore it is recommended to use the `options`
parameter to only fetch the fields you need:
```js
import { Meteor } from "meteor/meteor";
const userName = Meteor.user({ fields: { "profile.name": 1 } }).profile.name;
```
Same as [`Meteor.user`](#Meteor-user), but returns a promise and is available on the server.
```js
import { Meteor } from "meteor/meteor";
const user = await Meteor.userAsync();
```
This collection contains one document per registered user. Here's an example
user document:
```js
{
_id: 'QwkSmTCZiw5KDx3L6', // Meteor.userId()
username: 'cool_kid_13', // Unique name
emails: [
// Each email address can only belong to one user.
{ address: 'cool@example.com', verified: true },
{ address: 'another@different.com', verified: false }
],
createdAt: new Date('Wed Aug 21 2013 15:16:52 GMT-0700 (PDT)'),
profile: {
// The profile is writable by the user by default.
name: 'Joe Schmoe'
},
services: {
facebook: {
id: '709050', // Facebook ID
accessToken: 'AAACCgdX7G2...AbV9AZDZD'
},
resume: {
loginTokens: [
{ token: '97e8c205-c7e4-47c9-9bea-8e2ccc0694cd',
when: 1349761684048 }
]
}
}
}
```
A user document can contain any data you want to store about a user. Meteor
treats the following fields specially:
- `username`: a unique String identifying the user.
- `emails`: an Array of Objects with keys `address` and `verified`;
an email address may belong to at most one user. `verified` is
a Boolean which is true if the user has [verified the address](#Accounts-verifyEmail) with a token sent over email.
- `createdAt`: the Date at which the user document was created.
- `profile`: an Object which the user can create and update with any data.
Do not store anything on `profile` that you wouldn't want the user to edit
unless you have a deny rule on the `Meteor.users` collection.
- `services`: an Object containing data used by particular
login services. For example, its `reset` field contains
tokens used by [forgot password](#Accounts-forgotPassword) links,
and its `resume` field contains tokens used to keep you
logged in between sessions.
Like all [Mongo.Collection](./collections.md)s, you can access all
documents on the server, but only those specifically published by the server are
available on the client. You can also use all Collection methods, for instance
`Meteor.users.remove` on the server to delete a user.
By default, the current user's `username`, `emails` and `profile` are
published to the client. You can publish additional fields for the
current user with:
::: code-group
```js [server.js]
Meteor.publish("userData", function () {
if (this.userId) {
return Meteor.users.find(
{ _id: this.userId },
{
fields: { other: 1, things: 1 },
}
);
} else {
this.ready();
}
});
```
```js [client.js]
Meteor.subscribe("userData");
```
:::
If the autopublish package is installed, information about all users
on the system is published to all clients. This includes `username`,
`profile`, and any fields in `services` that are meant to be public
(eg `services.facebook.id`,
`services.twitter.screenName`). Additionally, when using autopublish
more information is published for the currently logged in user,
including access tokens. This allows making API calls directly from
the client for services that allow this.
Users are by default allowed to specify their own `profile` field with
[`Accounts.createUser`](#Accounts-createUser) and modify it with
`Meteor.users.update`. To allow users to edit additional fields, use
[`Meteor.users.allow`](./collections.md#Mongo-Collection-allow). To forbid users from making any modifications to
their user document:
```js
import { Meteor } from "meteor/meteor";
Meteor.users.deny({ update: () => true });
```
For example, [the `accounts-ui` package](../packages/accounts-ui.md) uses this to display an
animation while the login request is being processed.
For example, when called in a user's browser, connections in that browser
remain logged in, but any other browsers or DDP clients logged in as that user
will be logged out.
If there are multiple users with a username or email only differing in case, a case sensitive match is required. Although `createUser` won't let you create users with ambiguous usernames or emails, this could happen with existing databases or if you modify the users collection directly.
This method can fail throwing one of the following errors:
- "Unrecognized options for login request [400]" if `user` or `password` is undefined.
- "Match failed [400]" if `user` isn't an Object or String, or `password` isn't a String.
- "User not found [403]" if the email or username provided in `user` doesn't belong to a registered user.
- "Incorrect password [403]" if the password provided is incorrect.
- "User has no password set [403]" if `user` doesn't have a password.
This function is provided by the `accounts-password` package. See the
[Passwords](#passwords) section below.
Available functions are:
- `Meteor.loginWithMeteorDeveloperAccount`
- `Meteor.loginWithFacebook`
- `options` may also include [Facebook's `auth_type` parameter](https://developers.facebook.com/docs/facebook-login/manually-build-a-login-flow#reaskperms)
- `Meteor.loginWithGithub`
- `Meteor.loginWithGoogle`
- `options` may also include [Google's additional URI parameters](https://developers.google.com/identity/protocols/OpenIDConnect#authenticationuriparameters)
- `Meteor.loginWithMeetup`
- `Meteor.loginWithTwitter`
- `options` may also include [Twitter's `force_login` parameter](https://dev.twitter.com/oauth/reference/get/oauth/authenticate)
- `Meteor.loginWithWeibo`
These functions initiate the login process with an external
service (eg: Facebook, Google, etc), using OAuth. When called they open a new pop-up
window that loads the provider's login page. Once the user has logged in
with the provider, the pop-up window is closed and the Meteor client
logs in to the Meteor server with the information provided by the external
service.
Requesting Permissions
In addition to identifying the user to your application, some services
have APIs that allow you to take action on behalf of the user. To
request specific permissions from the user, pass the
`requestPermissions` option the login function. This will cause the user
to be presented with an additional page in the pop-up dialog to permit
access to their data. The user's `accessToken` — with permissions
to access the service's API — is stored in the `services` field of
the user document. The supported values for `requestPermissions` differ
for each login service and are documented on their respective developer
sites:
- Facebook:
- GitHub:
- Google:
- Meetup:
- Twitter, Weibo, Meteor developer accounts: `requestPermissions` currently not supported
External login services typically require registering and configuring
your application before use. The easiest way to do this is with the
[`accounts-ui` package](../packages/accounts-ui.md) which presents a step-by-step guide
to configuring each service. However, the data can be also be entered
manually in the `ServiceConfiguration.configurations` collection, which
is exported by the `service-configuration` package.
## Configuring Services {#service-configuration}
First, add the service configuration package:
```bash
meteor add service-configuration
```
Then, inside the server of your app (this example is for the Weebo service), import `ServiceConfiguration`:
```js
import { ServiceConfiguration } from "meteor/service-configuration";
ServiceConfiguration.configurations.upsert(
{ service: "weibo" },
{
$set: {
loginStyle: "popup",
clientId: "1292962797", // See table below for correct property name!
secret: "75a730b58f5691de5522789070c319bc",
},
}
);
```
Since Meteor 2.7 you no longer need to manually set the configuration and instead can use Meteor settings by setting your services under `Meteor.settings.packages.service-configuration.`. All the properties can be set under the service and will be added to the database as is, so make sure that they are correct. For the example above, the settings would look like:
```json
{
"packages": {
"service-configuration": {
"weibo": {
"loginStyle": "popup",
"clientId": "1292962797",
"secret": "75a730b58f5691de5522789070c319bc"
}
}
}
}
```
The correct property name to use for the API identifier (i.e. `clientId` in the above example) depends on the login service being used, so be sure to use the correct one:
| Property Name | Services |
| ------------- | -------------------------------------------------------- |
| `appId` | Facebook |
| `clientId` | Github, Google, Meetup, Meteor Developer Accounts, Weibo |
| `consumerKey` | Twitter |
Additionally, each external service has its own login provider package and login function. For
example, to support GitHub login, run the following in your terminal:
```bash
meteor add accounts-github
```
and use the `Meteor.loginWithGithub` function:
```js
import { Meteor } from "meteor/meteor";
Meteor.loginWithGithub(
{
requestPermissions: ["user", "public_repo"],
},
(error) => {
if (error) {
Session.set("errorMessage", error.reason || "Unknown error");
}
}
);
```
Login service configuration is sent from the server to the client over DDP when
your app starts up; you may not call the login function until the configuration
is loaded. The function `Accounts.loginServicesConfigured()` is a reactive data
source that will return true once the login service is configured; you should
not make login buttons visible or active until it is true.
Ensure that your [`$ROOT_URL`](./meteor.md#Meteor-absoluteUrl) matches the authorized
domain and callback URL that you configure with the external service (for
instance, if you are running Meteor behind a proxy server, `$ROOT_URL` should be
the externally-accessible URL, not the URL inside your proxy).
## Manual service configuration {#manual-service-configuration}
You can use `Accounts.loginServiceConfiguration` to view and edit the settings collection:
```js
import { Accounts } from "meteor/accounts-base";
Accounts.loginServiceConfiguration.find();
```
## Popup versus redirect flow {#popup-vs-redirect-flow}
When configuring OAuth login with a provider (such as Facebook or Google), Meteor lets you choose a popup- or redirect-based flow. In a popup-based flow, when a user logs in, they will be prompted to login at the provider in a popup window. In a redirect-based flow, the user's whole browser window will be redirected to the login provider, and the window will redirect back to your app when the login is completed.
You can also pick which type of login to do by passing an option to [`Meteor.loginWith`](#Meteor-loginWith%3CExternalService%3E)
Usually, the popup-based flow is preferable because the user will not have to reload your whole app at the end of the login flow. However, the popup-based flow requires browser features such as `window.close` and `window.opener` that are not available in all mobile environments. In particular, we recommend using `Meteor.loginWith({ loginStyle: 'redirect' })` in the following environments:
- Inside UIWebViews (when your app is loaded inside a mobile app)
- In Safari on iOS8 (`window.close` is not supported due to a bug)
Example:
```js
import { Accounts } from "meteor/accounts-base";
Accounts.ui.config({
requestPermissions: {
facebook: ["user_likes"],
github: ["user", "repo"],
},
requestOfflineToken: {
google: true,
},
passwordSignupFields: "USERNAME_AND_OPTIONAL_EMAIL",
});
```
Since Meteor 2.7 you can configure these in your Meteor settings under `Meteor.settings.public.packages.accounts-ui-unstyled`.
## Multi-server {#multi-server}
The `accounts-base` package exports two constructors, called
`AccountsClient` and `AccountsServer`, which are used to create the
`Accounts` object that is available on the client and the server,
respectively.
This predefined `Accounts` object (along with similar convenience methods
of `Meteor`, such as [`Meteor.logout`](#Meteor-logout)) is sufficient to
implement most accounts-related logic in Meteor apps. Nevertheless, these
two constructors can be instantiated more than once, to create multiple
independent connections between different accounts servers and their
clients, in more complicated authentication situations.
The `AccountsClient` and `AccountsServer` classes share a common
superclass, `AccountsCommon`. Methods defined on
`AccountsCommon.prototype` will be available on both the client and the
server, via the predefined `Accounts` object (most common) or any custom
`accountsClientOrServer` object created using the `AccountsClient` or
`AccountsServer` constructors (less common).
Here are a few of those methods:
From Meteor 2.5 you can set these in your Meteor settings under `Meteor.settings.packages.accounts-base`. Note that due to the nature of settings file you won't be able to set parameters that require functions.
See description of [AccountsCommon#onLoginFailure](#AccountsCommon-onLoginFailure)
for details.
Either the `onLogin` or the `onLoginFailure` callbacks will be called
for each login attempt. The `onLogin` callbacks are called after the
user has been successfully logged in. The `onLoginFailure` callbacks are
called after a login attempt is denied.
These functions return an object with a single method, `stop`. Calling
`stop()` unregisters the callback.
On the server, the callbacks get a single argument, the same attempt info
object as [`validateLoginAttempt`](#AccountsServer-validateLoginAttempt). On the
client, the callback argument is an object containing a single `error`
property set to the `Error`-object which was received from the failed login
attempt.
On the server, the `func` callback receives a single argument with the object below. On the
client, no arguments are passed.
```js
import { AccountsCommon } from "meteor/accounts-base";
const options = {
//...
};
const accountsCommon = new AccountsCommon(options);
accountsCommon.onLogout(({ user, connection, collection }) => {
console.log(user);
// ˆˆˆˆˆˆ The Meteor user object of the user which just logged out
console.log(connection);
// ˆˆˆˆˆˆ The connection object the request came in on. See
// `Meteor.onConnection` for details.
console.log(collection);
// ˆˆˆˆˆˆ The `collection` The name of the Mongo.Collection or the
// Mongo.Collection object to hold the users.
});
```
At most one of `options.connection` and `options.ddpUrl` should be
provided in any instantiation of `AccountsClient`. If neither is provided,
`Meteor.connection` will be used as the `.connection` property of the
`AccountsClient` instance.
Note that `AccountsClient` is currently available only on the client, due
to its use of browser APIs such as `window.localStorage`. In principle,
though, it might make sense to establish a client connection from one
server to another remote accounts server. Please [let us
know](https://github.com/meteor/meteor/wiki/Contributing-to-Meteor#feature-requests)
if you find yourself needing this server-to-server functionality.
These methods are defined on `AccountsClient.prototype`, and are thus
available only on the client:
These methods are defined on `AccountsServer.prototype`, and are thus
available only on the server:
This can be called multiple times. If any of the functions return `false` or
throw an error, the new user creation is aborted. To set a specific error
message (which will be displayed by [`accounts-ui`](../packages/accounts-ui.md)), throw a new
[`Meteor.Error`](./meteor#meteor-api).
Example:
```js
import { Accounts } from "meteor/accounts-base";
// Validate username, sending a specific error message on failure.
Accounts.validateNewUser((user) => {
if (user.username && user.username.length >= 3) {
return true;
} else {
throw new Meteor.Error(403, "Username must have at least 3 characters");
}
});
// Validate username, without a specific error message.
Accounts.validateNewUser((user) => {
return user.username !== "root";
});
```
If the user is being created as part of a login attempt from a client (eg,
calling [`Accounts.createUser`](#Accounts-createUser) from the client, or
[logging in for the first time with an external
service](#meteor_loginwithexternalservice)), these callbacks are called _before_
the [`Accounts.validateLoginAttempt`](#Accounts-validateLoginAttempt)
callbacks. If these callbacks succeed but those fail, the user will still be
created but the connection will not be logged in as that user.
Use this when you need to do more than simply accept or reject new user
creation. With this function you can programatically control the
contents of new user documents.
The function you pass will be called with two arguments: `options` and
`user`. The `options` argument comes
from [`Accounts.createUser`](#Accounts-createUser) for
password-based users or from an external service login flow. `options` may come
from an untrusted client so make sure to validate any values you read from
it. The `user` argument is created on the server and contains a
proposed user object with all the automatically generated fields
required for the user to log in, including a temporary `_id` (the final _id is
generated upon document insertion and not available in this function).
The function should return the user document (either the one passed in or a
newly-created object) with whatever modifications are desired. The returned
document is inserted directly into the [`Meteor.users`](#Meteor-users) collection.
The default create user function simply copies `options.profile` into
the new user document. Calling `onCreateUser` overrides the default
hook. This can only be called once.
Example:
```js
import { Accounts } from "meteor/accounts-base";
// Support for playing D&D: Roll 3d6 for dexterity.
Accounts.onCreateUser((options, user) => {
const customizedUser = Object.assign(
{
dexterity: _.random(1, 6) + _.random(1, 6) + _.random(1, 6),
},
user
);
// We still want the default hook's 'profile' behavior.
if (options.profile) {
customizedUser.profile = options.profile;
}
return customizedUser;
});
```
Call `validateLoginAttempt` with a callback to be called on login
attempts. It returns an object with a single method, `stop`. Calling
`stop()` unregisters the callback.
When a login attempt is made, the registered validate login callbacks
are called with a single argument, you can check the example:
```js
import { AccountsServer } from "meteor/accounts-base";
const options = {
//...
};
const accountsServer = new AccountsServer(options);
accountsServer.validateLoginAttempt(
({
type, // String
allowed, // Boolean
error, // Error
user, // Object
connection, // Object
collection, // Object
methodName, // String
methodArguments, // Array
}) => {
console.log(type);
// ˆˆˆˆˆˆ The service name, such as "password" or "twitter".
console.log(allowed);
// ˆˆˆˆˆˆ Whether this login is allowed and will be successful (if not aborted
// by any of the validateLoginAttempt callbacks). False if the login
// will not succeed (for example, an invalid password or the login was
// aborted by a previous validateLoginAttempt callback).
console.log(error);
// ˆˆˆˆˆˆ When `allowed` is false, the exception describing why the login
// failed. It will be a `Meteor.Error` for failures reported to the
// user (such as invalid password), and can be a another kind of
// exception for internal errors.
console.log(user);
// ˆˆˆˆˆˆ When it is known which user was attempting to login,
// the Meteor user object. This will always be present for successful logins.
console.log(connection);
// ˆˆˆˆˆˆ The `connection` object the request came in on. See
// [`Meteor.onConnection`](#meteor_onconnection) for details.
console.log(collection);
// ˆˆˆˆˆˆ The `collection` The name of the Mongo.Collection or the
// Mongo.Collection object to hold the users.
console.log(methodName);
// ˆˆˆˆˆˆ The name of the Meteor method being used to login.
// For example, "login", "loginWithPassword", or "loginWith".
console.log(methodArguments);
// ˆˆˆˆˆˆ An array of the arguments passed to the login method.
// For example, `["username", "password"]`
}
);
```
A validate login callback must return a truthy value for the login to
proceed. If the callback returns a falsy value or throws an
exception, the login is aborted. Throwing a `Meteor.Error` will
report the error reason to the user.
All registered validate login callbacks are called, even if one of the callbacks
aborts the login. The later callbacks will see the `allowed` field set to
`false` since the login will now not be successful. This allows later callbacks
to override an error from a previous callback; for example, you could override
the "Incorrect password" error with a different message.
Validate login callbacks that aren't explicitly trying to override a previous
error generally have no need to run if the attempt has already been determined
to fail, and should start with
```js
if (!attempt.allowed) {
return false;
}
```
Use this hook if you need to validate that user from an external service should
be allowed to login or create account.
```js
import { AccountsServer } from "meteor/accounts-base";
const options = {
//...
};
const accountsServer = new AccountsServer(options);
accountsServer.beforeExternalLogin(({ type, data, user }) => {
console.log(type);
// ˆˆˆˆˆˆ The service name, such as "google" or "twitter". Is a String
console.log(data);
// ˆˆˆˆˆˆ Data retrieved from the service (eg: email, name, etc)
// Is an Object.
console.log(user);
// ˆˆˆˆˆˆ If user was found in the database that matches the criteria from the service,
// their data will be provided here. Is an Object.
});
```
You should return a `Boolean` value, `true` if the login/registration should
proceed or `false` if it should terminate. In case of termination
the login attempt will throw an error `403`, with the message: `Login forbidden`.
When allowing your users to authenticate with an external service, the process will
eventually call `Accounts.updateOrCreateUserFromExternalService`. By default, this
will search for a user with the `service..id`, and if not found will
create a new user. As that is not always desirable, you can use this hook as an
escape hatch to look up a user with a different selector, probably by `emails.address` or `username`. Note the function will only be called if no user was found with the
`service..id` selector.
The function will be called with a single argument, the info object:
```js
import { AccountsServer } from "meteor/accounts-base";
const options = {
//...
};
const accountsServer = new AccountsServer(options);
accountsServer.setAdditionalFindUserOnExternalLogin(
({ serviceName, serviceData, options }) => {
// serviceName: String
// The external service name, such as "google" or "twitter".
// serviceData: Object
// The data returned by the service oauth request.
// options: Object
// An optional arugment passed down from the oauth service that may contain
// additional user profile information. As the data in `options` comes from an
// external source, make sure you validate any values you read from it.
}
);
```
The function should return either a user document or `undefined`. Returning a user
will result in the populating the `service.` in your user document,
while returning `undefined` will result in a new user account being created.
If you would prefer that a new account not be created, you could throw an error
instead of returning.
Example:
```js
// If a user has already been created, and used their Google email, this will
// allow them to sign in with the Meteor.loginWithGoogle method later, without
// creating a new user.
Accounts.setAdditionalFindUserOnExternalLogin(
({ serviceName, serviceData }) => {
if (serviceName === "google") {
// Note: Consider security implications. If someone other than the owner
// gains access to the account on the third-party service they could use
// the e-mail set there to access the account on your app.
// Most often this is not an issue, but as a developer you should be aware
// of how bad actors could play.
return Accounts.findUserByEmail(serviceData.email);
}
}
);
```
Use this to register your own custom authentication method. This is also used by all of the other inbuilt accounts packages to integrate with the accounts system.
There can be multiple login handlers that are registered. When a login request is made, it will go through all these handlers to find its own handler.
The registered handler callback is called with a single argument, the `options` object which comes from the login method. For example, if you want to login with a plaintext password, `options` could be `{ user: { username: }, password: }`,or `{ user: { email: }, password: }`.
The login handler should return `undefined` if it's not going to handle the login request or else the login result object.
Rate Limiting
By default, there are rules added to the [`DDPRateLimiter`](./DDPRateLimiter.md)
that rate limit logins, new user registration and password reset calls to a
limit of 5 requests per 10 seconds per session. These are a basic solution
to dictionary attacks where a malicious user attempts to guess the passwords
of legitimate users by attempting all possible passwords.
These rate limiting rules can be removed by calling
`Accounts.removeDefaultRateLimit()`. Please see the
[`DDPRateLimiter`](./DDPRateLimiter.md) docs for more information.
## Passwords {#passwords}
The `accounts-password` package contains a full system for password-based
authentication. In addition to the basic username and password-based
sign-in process, it also supports email-based sign-in including
address verification and password recovery emails.
### Password encryption and security
Starting from `accounts-passwords:4.0.0`, you can choose which algorithm is used by the Meteor server to store passwords : either [bcrypt](http://en.wikipedia.org/wiki/Bcrypt) or
[Argon2](http://en.wikipedia.org/wiki/Argon2) algorithm. Both are robust and contribute to
protect against embarrassing password leaks if the server's database is
compromised.
Before version 4.0.0, `bcrypt` was the only available option. argon2 has been introduced because it is considered the most secure option. This algorithm is specifically designed to resist GPU-based brute force attacks. For more details, see the [OWASP Password Storage Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html).
As of January 2025, **`bcrypt` is still the default option** to enable a smooth transition. In the future, `argon2` will replace `bcrypt` as default and `bcrypt` option will be deprecated.
Passwords are hashed on the client using **SHA-256** algorithm before being sent to the server. This ensures that sensitive data is never transmitted in plain text. Once received by the server, the hashed value is further encrypted and securely stored in the `Meteor.users` collection.
**About the migration process from `bcrypt` to `argon2`**
The transition from `bcrypt` to `argon2` happens automatically upon user login. If Argon2 encryption is enabled in an existing application, each user's password is re-encrypted during their next successful login.
- Step 1: The password is first validated against the existing `bcrypt` hash.
- Step 2: If authentication succeeds, the password is re-encrypted using `Argon2`.
- Step 3: The new `Argon2` hash replaces the old `bcrypt` hash in the database.
To monitor the migration progress, you can count users still using bcrypt:
```js
const bcryptUsers = await Meteor.users.find({ "services.password.bcrypt": { $exists: true } }).countAsync();
const totalUsers = await Meteor.users.find({ "services.password": { $exists: true } }).countAsync();
console.log("Remaining users to migrate:", bcryptUsers, "/", totalUsers);
```
Once `bcryptUsers` reaches 0, the migration is complete.
**Enabling Argon2 encryption**
To enable Argon2 encryption, you need a small configuration change on the server:
```js
Accounts.config({
argon2Enabled: true,
});
```
**Configuring `argon2` parameters**
One enabled, the `accounts-password` package allows customization of Argon2's parameters. The configurable options include:
- `type`: `argon2id` (provides a blend of resistance against GPU and side-channel attacks)
- `timeCost` (default: 2) – This controls the computational cost of the hashing process, affecting both the security level and performance.
- `memoryCost`: 19456 (19 MiB) - The amount of memory used by the algorithm in KiB per thread
- `parallelism`: 1 - The number of threads used by the algorithm
To update the values, use the following configuration:
```js
Accounts.config({
argon2Enabled: true,
argon2Type: "argon2id",
argon2TimeCost: 2,
argon2MemoryCost: 19456,
argon2Parallelism: 1,
});
```
Other Argon2 parameters, such as `hashLength`, are kept to default values:
- `hashLength`: 32 bytes - The length of the hash output in bytes
The default values are the minimum [OWASP recommendations for Argon2 parameters](https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html#introduction). When updating these values, consider the trade-offs between security and performance on the target infrastructure.
For more information about Argon2's parameters, refer to the [argon2 options documentation](https://github.com/ranisalt/node-argon2/wiki/Options).
### Using passwords
To add password support to your application, run this command in your terminal:
```bash
meteor add accounts-password
```
> In addition to configuring the [`email`](./email.md) package's `MAIL_URL`, it is critical that you set proper values (specifically the `from` address) in [`Accounts.emailTemplates`](#Accounts-emailTemplates) to ensure proper delivery of e-mails!
You can construct your own user interface using the
functions below, or use the [`accounts-ui` package](../packages/accounts-ui.md) to
include a turn-key user interface for password-based sign-in.
On the client, this function logs in as the newly created user on
successful completion. On the server, it returns the newly created user
id.
On the client, you must pass `password` and at least one of `username` or `email` — enough information for the user to be able to log in again later. If there are existing users with a username or email only differing in case, `createUser` will fail. The callback's `error.reason` will be `'Username already exists.'` or `'Email already exists.'` In the latter case, the user can then either [login](accounts.html#Meteor-loginWithPassword) or [reset their password](#Accounts-resetPassword).
On the server, you do not need to specify `password`, but the user will not be able to log in until it has a password (eg, set with [`Accounts.setPasswordAsync`](#Accounts-setPasswordAsync)). To create an account without a password on the server and still let the user pick their own password, call `createUser` with the `email` option and then call [`Accounts.sendEnrollmentEmail`](#Accounts-sendEnrollmentEmail). This will send the user an email with a link to set their initial password.
By default the `profile` option is added directly to the new user document. To
override this behavior, use [`Accounts.onCreateUser`](#Accounts-onCreateUser).
This function is only used for creating users with passwords. The external
service login flows do not use this function.
Instead of modifying documents in the [`Meteor.users`](#Meteor-users) collection
directly, use these convenience functions which correctly check for case
insensitive duplicates before updates.
By default, an email address is added with `{ verified: false }`. Use
[`Accounts.sendVerificationEmail`](#Accounts-sendVerificationEmail) to send an
email with a link the user can use to verify their email address.
If the user trying to verify the email has 2FA enabled, this error will be thrown:
- "Email verified, but user not logged in because 2FA is enabled [2fa-enabled]": No longer signing in the user automatically if the user has 2FA enabled.
This function accepts tokens passed into the callback registered with
[`Accounts.onEmailVerificationLink`](#Accounts-onEmailVerificationLink).
Use the below functions to initiate password changes or resets from the server
or the client.
This triggers a call
to [`Accounts.sendResetPasswordEmail`](#Accounts-sendResetPasswordEmail)
on the server. When the user visits the link in this email, the callback
registered with [`Accounts.onResetPasswordLink`](#Accounts-onResetPasswordLink)
will be called.
If you are using the [`accounts-ui` package](../packages/accounts-ui.md), this is handled
automatically. Otherwise, it is your responsibility to prompt the user for the
new password and call `resetPassword`.
This function accepts tokens passed into the callbacks registered with
[`AccountsClient#onResetPasswordLink`](#Accounts-onResetPasswordLink) and
[`Accounts.onEnrollmentLink`](#Accounts-onEnrollmentLink).
If the user trying to reset the password has 2FA enabled, this error will be thrown:
- "Changed password, but user not logged in because 2FA is enabled [2fa-enabled]": No longer signing in the user automatically if the user has 2FA enabled.
When the user visits the link in this email, the callback registered with
[`AccountsClient#onResetPasswordLink`](#Accounts-onResetPasswordLink) will be called.
To customize the contents of the email, see
[`Accounts.emailTemplates`](#Accounts-emailTemplates).
When the user visits the link in this email, the callback registered with
[`Accounts.onEnrollmentLink`](#Accounts-onEnrollmentLink) will be called.
To customize the contents of the email, see
[`Accounts.emailTemplates`](#Accounts-emailTemplates).
When the user visits the link in this email, the callback registered with
[`Accounts.onEmailVerificationLink`](#Accounts-onEmailVerificationLink) will
be called.
To customize the contents of the email, see
[`Accounts.emailTemplates`](#Accounts-emailTemplates).
This is an `Object` with several fields that are used to generate text/html
for the emails sent by `sendResetPasswordEmail`, `sendEnrollmentEmail`,
and `sendVerificationEmail`.
Set the fields of the object by assigning to them:
- `from`: (**required**) A `String` with an [RFC5322](http://tools.ietf.org/html/rfc5322) From
address. By default, the email is sent from `no-reply@example.com`. **If you
want e-mails to send correctly, this should be changed to your own domain
as most e-mail providers will reject mail sent from `example.com`.**
- `siteName`: The public name of your application. Defaults to the DNS name of
the application (eg: `awesome.meteor.com`).
- `headers`: An `Object` for custom email headers as described in
[`Email.send`](./email.md#Email-send).
- `resetPassword`: An `Object` with the fields:
- `from`: A `Function` used to override the `from` address defined
by the `emailTemplates.from` field.
- `subject`: A `Function` that takes a user object and returns
a `String` for the subject line of a reset password email.
- `text`: An optional `Function` that takes a user object and a url, and
returns the body text for a reset password email.
- `html`: An optional `Function` that takes a user object and a
url, and returns the body html for a reset password email.
- `enrollAccount`: Same as `resetPassword`, but for initial password setup for
new accounts.
- `verifyEmail`: Same as `resetPassword`, but for verifying the users email
address.
Example:
```js
import { Accounts } from "meteor/accounts-base";
Accounts.emailTemplates.siteName = "AwesomeSite";
Accounts.emailTemplates.from = "AwesomeSite Admin ";
Accounts.emailTemplates.enrollAccount.subject = (user) => {
return `Welcome to Awesome Town, ${user.profile.name}`;
};
Accounts.emailTemplates.enrollAccount.text = (user, url) => {
return (
"You have been selected to participate in building a better future!" +
" To activate your account, simply click the link below:\n\n" +
url
);
};
Accounts.emailTemplates.resetPassword.from = () => {
// Overrides the value set in `Accounts.emailTemplates.from` when resetting
// passwords.
return "AwesomeSite Password Reset ";
};
Accounts.emailTemplates.verifyEmail = {
subject() {
return "Activate your account now!";
},
text(user, url) {
return `Hey ${user}! Verify your e-mail by following this link: ${url}`;
},
};
```
Enable 2FA for this package
You can add 2FA to your login flow by
using the package [accounts-2fa](../packages/accounts-2fa.md).
You can find an example showing how this would look like [here](../packages/accounts-2fa.md#working-with-accounts-password).
---
---
url: /packages/accounts-2fa.md
---
# accounts-2fa
This package allows you to provide a way for your users to enable 2FA on their accounts, using an authenticator app such as Google Authenticator, or 1Password. When the user is logged in on your app, they will be able to generate a new QR code and read this code on the app they prefer. After that, they'll start receiving their codes. Then, they can finish enabling 2FA on your app, and every time they try to log in to your app, you can redirect them to a place where they can provide a code they received from the authenticator.
To provide codes that are exactly compatible with all other Authenticator apps and services that implements TOTP, this package uses [node-2fa](https://www.npmjs.com/package/node-2fa) which works on top of [notp](https://github.com/guyht/notp), **that** implements TOTP ([RFC 6238](https://www.ietf.org/rfc/rfc6238.txt)) (the Authenticator standard), which is based on HOTP ([RFC 4226](https://www.ietf.org/rfc/rfc4226.txt)).
> This package is meant to be used with [`accounts-password`](../api/accounts.md#passwords) or [`accounts-passwordless`](./accounts-passwordless.md), so if you don't have either of those in your project, you'll need to add one of them. In the future, we want to enable the use of this package with other login methods, our oauth methods (Google, GitHub, etc...).
## 2FA Activation Flow {#activating-2fa}
The first step, in order to enable 2FA, is to generate a QR code so that the user can scan it in an authenticator app and start receiving codes.
Receives an `appName` which is the name of your app that will show up when the user scans the QR code. Also, a callback called, on success, with a QR code in SVG format, a QR secret, and the URI that can be used to activate the 2FA in an authenticator app,
or a single `Error` argument on failure.
On success, this function will also add an object to the logged user's services object containing the QR secret:
```js
services: {
...
twoFactorAuthentication: {
secret: "***"
}
}
```
Here it's an example on how to call this function:
```js
import { Buffer } from "buffer";
import { Accounts } from 'meteor/accounts-base';
// component
const [qrCode, setQrCode] = useState(null);
```
This method can fail throwing the following error:
- "The 2FA is activated. You need to disable the 2FA first before trying to generate a new activation code [2fa-activated]" if trying to generate an activation when the user already have 2FA enabled.
At this point, the 2FA won't be activated just yet. Now that the user has access to the codes generated by their authenticator app, you can call the function `Accounts.enableUser2fa`:
It should be called with a code that the users will receive from the authenticator app once they read the QR code. The callback is called with a single `Error` argument on failure. If the code provided is correct, a `type` will be added to the user's `twoFactorAuthentication` object and now 2FA is considered enabled:
```js
services: {
...
twoFactorAuthentication: {
type: "otp",
secret: "***",
}
}
```
To verify whether or not a user has 2FA enabled, you can call the function `Accounts.has2faEnabled`:
This function must be called when the user is logged in.
## Disabling 2FA {#disabling-2fa}
To disable 2FA for a user use this method:
To call this function the user must be already logged in.
## Log in with 2FA {#log-in-with-2fa}
Now that you have a way to allow your users to enable 2FA on their accounts, you can create a login flow based on that.
As said at the beginning of this guide, this package is currently working with two other packages: `accounts-password` and `accounts-passwordless`. Below there is an explanation on how to use this package with them.
## Working with accounts-password {#working-with-accounts-password}
When calling the function `Meteor.loginWithPassword`, if the 2FA is enabled for the user, an error will be returned to the callback, so you can redirect the user to a place where they can provide a code.
As an example:
```js
```
If the 2FA is not enabled, the user will be logged in normally.
The function you will need to call now to allow the user to login is `Meteor.loginWithPasswordAnd2faCode`:
Now you will be able to receive a code from the user and this function will verify if the code is valid. If it is, the user will be logged in.
So the call of this function should look something like this:
```js
```
This method can fail throwing one of the following errors:
- "2FA code must be informed [no-2fa-code]" if a 2FA code was not provided.
- "Invalid 2FA code [invalid-2fa-code]" if the provided 2FA code is invalid.
## Working with accounts-passwordless {#working-with-accounts-passwordless}
Following the same logic from the previous package, if the 2FA is enabled, an error will be returned to the callback of the function
[`Meteor.passwordlessLoginWithToken`](./accounts-passwordless.md#Meteor-passwordlessLoginWithToken),
then you can redirect the user to a place where they can provide a code.
Here is an example:
```js
```
Now you can call the function `Meteor.passwordlessLoginWithTokenAnd2faCode` that will allow you to provide a selector, token, and 2FA code:
This method can fail throwing one of the following errors:
- "2FA code must be informed [no-2fa-code]" if a 2FA code was not provided.
- "Invalid 2FA code [invalid-2fa-code]" if the provided 2FA code is invalid.
## Integrating an Authentication Package with accounts-2fa {#integrating-auth-package}
To integrate this package with any other existing Login method, it's necessary following two steps:
1 - For the client, create a new method from your current login method. So for example, from the method `Meteor.loginWithPassword` we created a new one called `Meteor.loginWithPasswordAnd2faCode`, and the only difference between them is that the latest one receives one additional parameter, the 2FA code, but we call the same function on the server side.
2 - For the server, inside the function that will log the user in, you verify if the function `Accounts._check2faEnabled` exists, and if yes, you call it providing the user object you want to check if the 2FA is enabled, and if either of these statements are false, you proceed with the login flow. This function exists only when the package `accounts-2fa` is added to the project.
If both statements are true, and the login validation succeeds, you verify if a code was provided: if not, throw an error; if it was provided, verify if the code is valid by calling the function `Accounts._isTokenValid`. if `Accounts._isTokenValid` returns false, throw an error.
Here it's an example:
```js
const result = validateLogin();
if (!result.error && Accounts._check2faEnabled?.(user)) {
if (!code) {
Accounts._handleError("2FA code must be informed.");
}
if (
!Accounts._isTokenValid(user.services.twoFactorAuthentication.secret, code)
) {
Accounts._handleError("Invalid 2FA code.");
}
}
return result;
```
---
---
url: /packages/accounts-ui.md
---
# accounts-ui
A turn-key user interface for Meteor Accounts.
To add Accounts and a set of login controls to an application, add the
`accounts-ui` package and at least one login provider package:
`accounts-password`, `accounts-facebook`, `accounts-github`,
`accounts-google`, `accounts-twitter`, or `accounts-weibo`.
Then simply add the `{{> loginButtons}}` helper to an HTML file. This
will place a login widget on the page. If there is only one provider configured
and it is an external service, this will add a login/logout button. If you use
`accounts-password` or use multiple external login services, this will add
a "Sign in" link which opens a dropdown menu with login options. If you plan to
position the login dropdown in the right edge of the screen, use
`{{> loginButtons align="right"}}` in order to get the dropdown to lay
itself out without expanding off the edge of the screen.
To configure the behavior of `{{> loginButtons}}`, use
[`Accounts.ui.config`](../api/accounts.md#loggingIn).
`accounts-ui` also includes modal popup dialogs to handle links from
[`sendResetPasswordEmail`](../api/accounts.md#Accounts-sendResetPasswordEmail),
[`sendVerificationEmail`](../api/accounts.md#Accounts-sendVerificationEmail),
and [`sendEnrollmentEmail`](../api/accounts.md#Accounts-sendEnrollmentEmail). These
do not have to be manually placed in HTML: they are automatically activated
when the URLs are loaded.
If you want to control the look and feel of your accounts system a little more, we recommend reading the [useraccounts](http://guide.meteor.com/accounts.html#useraccounts) section of the Meteor Guide.
---
---
url: /packages/appcache.md
---
# AppCache
> This package has been deprecated since [applicationCache](https://developer.mozilla.org/en-US/docs/Web/API/Window/applicationCache), which this package relies on, has been deprecated and is not available on the latest browsers. Plaese consider using [Service Worker](https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API) as an replacement.
The `appcache` package stores the static parts of a Meteor application
(the client side Javascript, HTML, CSS, and images) in the browser's
[application cache](https://en.wikipedia.org/wiki/AppCache). To enable
caching simply add the `appcache` package to your project.
* Once a user has visited a Meteor application for the first time and
the application has been cached, on subsequent visits the web page
loads faster because the browser can load the application out of the
cache without contacting the server first.
* Hot code pushes are loaded by the browser in the background while the
app continues to run. Once the new code has been fully loaded the
browser is able to switch over to the new code quickly.
* The application cache allows the application to be loaded even when
the browser doesn't have an Internet connection, and so enables using
the app offline.
(Note however that the `appcache` package by itself doesn't make
*data* available offline: in an application loaded offline, a Meteor
Collection will appear to be empty in the client until the Internet
becomes available and the browser is able to establish a DDP
connection).
To turn AppCache off for specific browsers use:
```js
Meteor.AppCache.config({
chrome: false,
firefox: false
});
```
The supported browsers that can be enabled or disabled include, but are
not limited to, `android`, `chrome`, `chromium`, `chromeMobileIOS`,
`firefox`, `ie`, `mobileSafari` and `safari`.
Browsers limit the amount of data they will put in the application
cache, which can vary due to factors such as how much disk space is
free. Unfortunately if your application goes over the limit rather
than disabling the application cache altogether and running the
application online, the browser will instead fail that particular
*update* of the cache, leaving your users running old code.
Thus it's best to keep the size of the cache below 5MB. The
`appcache` package will print a warning on the Meteor server console
if the total size of the resources being cached is over 5MB.
Starting from `appcache@1.2.5`, if you need more advanced logic
to enable/disable the cache, you can use the `enableCallback` option
that is evaluated on a per-request basis. For example:
```js
// Enable offline mode using a value from database and certificate validation
Meteor.AppCache.config({
// This option is available starting from appcache@1.2.4
enableCallback: () => {
if (!getSettingsFromDb("public.appcache_enabled")) {
return false;
}
const validation = validateClientCert({
clientCertPayload: req.headers["x-client-cert"],
url: req.url.href,
});
return validation.passed;
},
});
```
If you have files too large to fit in the cache you can disable
caching by URL prefix. For example,
```js
Meteor.AppCache.config({ onlineOnly: ['/online/'] });
```
causes files in your `public/online` directory to not be cached, and
so they will only be available online. You can then move your large
files into that directory and refer to them at the new URL:
```html
```
If you'd prefer not to move your files, you can use the file names
themselves as the URL prefix:
```js
Meteor.AppCache.config({
onlineOnly: [
'/bigimage.jpg',
'/largedata.json'
]
});
```
though keep in mind that since the exclusion is by prefix (this is a
limitation of the application cache manifest), excluding
`/largedata.json` will also exclude such URLs as
`/largedata.json.orig` and `/largedata.json/file1`.
For more information about how Meteor interacts with the application
cache, see the
[AppCache page](https://github.com/meteor/meteor/wiki/AppCache)
in the Meteor wiki.
---
---
url: /tutorials/application-structure/index.md
---
# Application Structure
After reading this article, you'll know:
1. How a Meteor application compares to other types of applications in terms of file structure.
2. How to organize your application both for small and larger applications.
3. How to format your code and name the parts of your application in consistent and maintainable ways.
[[toc]]
## Universal JavaScript
Meteor is a *full-stack* framework for building JavaScript applications. This means Meteor applications differ from most applications in that they include code that runs on the client, inside a web browser or Cordova mobile app, code that runs on the server, inside a [Node.js](http://nodejs.org/) container, and _common_ code that runs in both environments. The [Meteor build tool](https://guide.meteor.com/build-tool) allows you to specify what JavaScript code, including any supporting UI templates, CSS rules, and static assets, to run in each environment using a combination of ES2015 `import` and `export` and the Meteor build system [default file load order](#default-file-load-order) rules.
### ES2015 modules
As of version 1.3, Meteor ships with full support for [ES2015 modules](https://developer.mozilla.org/en/docs/web/javascript/reference/statements/import). The ES2015 module standard is the replacement for [CommonJS](http://requirejs.org/docs/commonjs.html) and [AMD](https://github.com/amdjs/amdjs-api), which are commonly used JavaScript module format and loading systems.
In ES2015, you can make variables available outside a file using the `export` keyword. To use the variables somewhere else, you must `import` them using the path to the source. Files that export some variables are called "modules", because they represent a unit of reusable code. Explicitly importing the modules and packages you use helps you write your code in a modular way, avoiding the introduction of global symbols and "action at a distance".
You can read about the module system in detail in the [`modules` package README](https://docs.meteor.com/#/full/modules). This package is automatically included in every new Meteor app as part of the [`ecmascript` meta-package](https://docs.meteor.com/#/full/ecmascript), so most apps won't need to do anything to start using modules right away.
### Introduction to using `import` and `export`
Meteor allows you to `import` not only JavaScript in your application, but also CSS and HTML to control load order:
```js
import '../../api/lists/methods.js'; // import from relative path
import '/imports/startup/client'; // import module with index.js from absolute path
import './loading.html'; // import Blaze compiled HTML from relative path
import '/imports/ui/style.css'; // import CSS from absolute path
```
> For more ways to import styles, see the [Build System](https://guide.meteor.com/build-tool#css-importing) article.
Meteor also supports the standard ES2015 modules `export` syntax:
```js
export const listRenderHold = LaunchScreen.hold(); // named export
export { Todos }; // named export
export default Lists; // default export
export default new Collection('lists'); // default export
```
### Importing from packages
In Meteor, it is also simple and straightforward to use the `import` syntax to load npm packages on the client or server and access the package's exported symbols as you would with any other module. You can also import from Meteor Atmosphere packages, but the import path must be prefixed with `meteor/` to avoid conflict with the npm package namespace. For example, to import `moment` from npm and `HTTP` from Atmosphere:
```js
import moment from 'moment'; // default import from npm
import { HTTP } from 'meteor/http'; // named import from Atmosphere
```
For more details using `imports` with packages see [Using Packages](../../packages/#using-atmosphere-packages) tutorial.
### Using `require`
In Meteor, `import` statements compile to CommonJS `require` syntax. However, as a convention we encourage you to use `import`.
With that said, in some situations you may need to call out to `require` directly. One notable example is when requiring client or server-only code from a common file. As `import`s must be at the top-level scope, you may not place them within an `if` statement, so you'll need to write code like:
```js
if (Meteor.isClient) {
require('./client-only-file.js');
}
```
Note that dynamic calls to `require()` (where the name being required can change at runtime) cannot be analyzed correctly and may result in broken client bundles.
If you need to `require` from an ES2015 module with a `default` export, you can grab the export with `require("package").default`.
### Using CoffeeScript
See the Docs: [CoffeeScript](https://docs.meteor.com/packages/coffeescript.html#coffeescript)
```cs
// lists.coffee
export Lists = new Collection 'lists'
```
```cs
import { Lists } from './lists.coffee'
```
## File structure
To fully use the module system and ensure that our code only runs when we ask it to, we recommend that all of your application code should be placed inside the `imports/` directory. This means that the Meteor build system will only bundle and include that file if it is referenced from another file using an `import` (also called "lazy evaluation or loading").
Meteor will load all files outside of any directory named `imports/` in the application using the [default file load order](#default-file-load-order) rules (also called "eager evaluation or loading"). It is recommended that you create exactly two eagerly loaded files, `client/main.js` and `server/main.js`, in order to define explicit entry points for both the client and the server. Meteor ensures that any file in any directory named `server/` will only be available on the server, and likewise for files in any directory named `client/`. This also precludes trying to `import` a file to be used on the server from any directory named `client/` even if it is nested in an `imports/` directory and vice versa for importing client files from `server/`.
These `main.js` files won't do anything themselves, but they should import some _startup_ modules which will run immediately, on client and server respectively, when the app loads. These modules should do any configuration necessary for the packages you are using in your app, and import the rest of your app's code.
### Example directory layout
To start, one can have a look to the [example applications](https://github.com/meteor/examples) provided. They are great examples to follow when structuring your app.
Below is an overview of an exemple directory structure. You can generate a new app with this structure using the command `meteor create appName --full`. The default frontend is Blaze, but you can change it later. Or use [another create option](https://docs.meteor.com/cli/#meteorcreate)
```sh
imports/
startup/
both/
index.js # single entry point to import isomorphic modules for client and server
client/
index.js # import client startup through a single index entry point
routes.js # set up all routes in the app
server/
fixtures.js # fill the DB with example data on startup
index.js # import server startup through a single index entry point
register-api.js # dedicated file to import server code for api
api/
lists/ # a unit of domain logic
server/
publications.js # all list-related publications
publications.tests.js # tests for the list publications
lists.js # definition of the Lists collection
lists.tests.js # tests for the behavior of that collection
methods.js # methods related to lists
methods.tests.js # tests for those methods
ui/
components/ # all reusable components in the application
# can be split by domain if there are many
layouts/ # wrapper components for behaviour and visuals
pages/ # entry points for rendering used by the router
stylesheets/ # global stylesheets
private/ # to store private assets for the server
public/ # to store public assets (pictures)
client/
main.js # client entry point, imports all client code
server/
main.js # server entry point, imports all server code
```
### Structuring imports
Now that we have placed all files inside the `imports/` directory, let's think about how best to organize our code using modules. It makes sense to put all code that runs when your app starts in an `imports/startup` directory. Another good idea is splitting data and business logic from UI rendering code. We suggest using directories called `imports/api` and `imports/ui` for this logical split.
Within the `imports/api` directory, it's sensible to split the code into directories based on the domain that the code is providing an API for --- typically this corresponds to the collections you've defined in your app. For instance in the Todos example app, we have the `imports/api/lists` and `imports/api/todos` domains. Inside each directory we define the collections, publications and methods used to manipulate the relevant domain data. Each API folder typically has different files for isomorphic code and server-specific code. To ensure good isolation, server-specific code is put into a `server` folder.
> Note: in a larger application, given that the todos themselves are a part of a list, it might make sense to group both of these domains into a single larger "list" module. The Todos example is small enough that we need to separate these only to demonstrate modularity.
Within the `imports/ui` directory it typically makes sense to group files into directories based on the type of UI side code they define, i.e. top level `pages`, wrapping `layouts`, or reusable `components`.
For each module defined above, it makes sense to co-locate the various auxiliary files with the base JavaScript file. For instance, a Blaze UI component should have its template HTML, JavaScript logic, and CSS rules in the same directory. A JavaScript module with some business logic should be co-located with the unit tests for that module.
### Startup files
Some of your code isn't going to be a unit of business logic or UI, it's some setup or configuration code that needs to run in the context of the app when it starts up. In the above example, the `imports/startup/client/routes.js` configures all the routes and then imports *all* other code that is required on the client:
```js
import { FlowRouter } from 'meteor/ostrio:flow-router-extra';
// Import needed templates
import '../../ui/layouts/body/body.js';
import '../../ui/pages/home/home.js';
import '../../ui/pages/not-found/not-found.js';
```
We then import both of these files in `imports/startup/client/index.js`:
```js
import './routes.js';
```
This makes it easy to then import all the client startup code with a single import as a module from our main eagerly loaded client entry point `client/main.js`:
```js
import '/imports/startup/client';
```
On the server, we use the same technique of importing all the startup code in `imports/startup/server/index.js`:
```js
import './fixtures.js';
import './register-api.js';
```
Our main server entry point `server/main.js` then imports this startup module. You can see that here we don't actually import any variables from these files - we import them so that they execute in this order.
### Importing Meteor "pseudo-globals"
For backwards compatibility Meteor still provides Meteor's global namespacing for the Meteor core package as well as for other Meteor packages you include in your application. You can also still directly call functions such as [`Meteor.publish`](https://docs.meteor.com/api/Meteor#Meteor-publish), as in previous versions of Meteor, without first importing them. However, it is recommended best practice that you first load all the Meteor "pseudo-globals" using the `import { Name } from 'meteor/package'` syntax before using them. For instance:
```js
import { Meteor } from 'meteor/meteor';
import { EJSON } from 'meteor/ejson';
```
## Default file load order
Even though it is recommended that you write your application to use ES2015 modules and the `imports/` directory, Meteor continues to support eager evaluation of files, using these default load order rules, to provide backwards compatibility with applications written for Meteor 1.2 and earlier. For a description of the difference between eager evaluation, lazy evaluation, and lazy loading, please see this Stack Overflow [article](https://stackoverflow.com/a/51158735/219238).
You may combine both eager evaluation and lazy loading using `import` in a single app. Any import statements are evaluated in the order they are listed in a file when that file is loaded and evaluated using these rules.
There are several load order rules. They are *applied sequentially* to all applicable files in the application, in the priority given below:
1. HTML template files are **always** loaded before everything else
2. Files beginning with `main.` are loaded **last**
3. Files inside **any** `lib/` directory are loaded next
4. Files with deeper paths are loaded next
5. Files are then loaded in alphabetical order of the entire path
```js
nav.html
main.html
client/lib/methods.js
client/lib/styles.js
lib/feature/styles.js
lib/collections.js
client/feature-y.js
feature-x.js
client/main.js
```
For example, the files above are arranged in the correct load order. `main.html` is loaded second because HTML templates are always loaded first, even if it begins with `main.`, since rule 1 has priority over rule 2. However, it will be loaded after `nav.html` because rule 2 has priority over rule 5.
`client/lib/styles.js` and `lib/feature/styles.js` have identical load order up to rule 4; however, since `client` comes before `lib` alphabetically, it will be loaded first.
> You can also use [Meteor.startup](https://docs.meteor.com/api/Meteor#Meteor-startup) to control when run code is run on both the server and the client.
### Special directories
By default, any JavaScript files in your Meteor application folder are bundled and loaded on both the client and the server. However, the names of the files and directories inside your project can affect their load order, where they are loaded, and some other characteristics. Here is a list of file and directory names that are treated specially by Meteor:
- **imports**
Any directory named `imports/` is not loaded anywhere and files must be imported using `import`.
- **node_modules**
Any directory named `node_modules/` is not loaded anywhere. node.js packages installed into `node_modules` directories must be imported using `import` or by using `Npm.depends` in `package.js`.
- **client**
Any directory named `client/` is not loaded on the server. Similar to wrapping your code in `if (Meteor.isClient) { ... }`. All files loaded on the client are automatically concatenated and minified when in production mode. In development mode, JavaScript and CSS files are not minified, to make debugging easier. CSS files are still combined into a single file for consistency between production and development, because changing the CSS file's URL affects how URLs in it are processed.
> HTML files in a Meteor application are treated quite a bit differently from a server-side framework. Meteor scans all the HTML files in your directory for three top-level elements: ``, ``, and ``. The head and body sections are separately concatenated into a single head and body, which are transmitted to the client on initial page load.
- **server**
Any directory named `server/` is not loaded on the client. Similar to wrapping your code in `if (Meteor.isServer) { ... }`, except the client never even receives the code. Any sensitive code that you don't want served to the client, such as code containing passwords or authentication mechanisms, should be kept in the `server/` directory.
Meteor gathers all your JavaScript files, excluding anything under the `client`, `public`, and `private` subdirectories, and loads them into a Node.js server instance. In Meteor, your server code runs in a single thread per request, not in the asynchronous callback style typical of Node.
- **public**
All files inside a top-level directory called `public/` are served as-is to the client. When referencing these assets, do not include `public/` in the URL, write the URL as if they were all in the top level. For example, reference `public/bg.png` as ``. This is the best place for `favicon.ico`, `robots.txt`, and similar files.
- **private**
All files inside a top-level directory called `private/` are only accessible from server code and can be loaded via the [`Assets`](https://docs.meteor.com/api/Assets#Assets-getTextAsync) API. This can be used for private data files and any files that are in your project directory that you don't want to be accessible from the outside.
- **client/compatibility**
This folder is for compatibility with JavaScript libraries that rely on variables declared with var at the top level being exported as globals. Files in this directory are executed without being wrapped in a new variable scope. These files are executed before other client-side JavaScript files.
> It is recommended to use npm for 3rd party JavaScript libraries and use `import` to control when files are loaded.
- **tests**
Any directory named `tests/` is not loaded anywhere. Use this for any test code you want to run using a test runner outside of [Meteor's built-in test tools](https://guide.meteor.com/testing.html).
The following directories are also not loaded as part of your app code:
- Files/directories whose names start with a dot, like `.meteor` and `.git`
- `packages/`: Used for local packages
- `cordova-build-override/`: Used for [advanced mobile build customizations](https://guide.meteor.com/mobile.html#advanced-build)
- `programs`: For legacy reasons
### Files outside special directories
All JavaScript files outside special directories are loaded on both the client and the server. Meteor provides the variables [`Meteor.isClient`](https://docs.meteor.com/api/Meteor#Meteor-isClient) and [`Meteor.isServer`](https://docs.meteor.com/api/Meteor#Meteor-isServer) so that your code can alter its behavior depending on whether it's running on the client or the server.
CSS and HTML files outside special directories are loaded on the client only and cannot be used from server code.
## Splitting into multiple apps
If you are writing a sufficiently complex system, there can come a time where it makes sense to split your code up into multiple applications. For example you may want to create a separate application for the administration UI (rather than checking permissions all through the admin part of your site, you can check once), or separate the code for the mobile and desktop versions of your app.
Another very common use case is splitting a worker process away from your main application so that expensive jobs do not impact the user experience of your visitors by locking up a single web server.
There are some advantages of splitting your application in this way:
- Your client JavaScript bundle can be significantly smaller if you separate out code that a specific type of user will never use.
- You can deploy the different applications with different scaling setups and secure them differently (for instance you might restrict access to your admin application to users behind a firewall).
- You can allow different teams at your organization to work on the different applications independently.
However there are some challenges to splitting your code in this way that should be considered before jumping in.
### Sharing code
The primary challenge is properly sharing code between the different applications you are building. The simplest approach to deal with this issue is to deploy the *same* application on different web servers, controlling the behavior via different [settings](https://guide.meteor.com/deployment.html#environment). This approach allows you to deploy different versions with different scaling behavior but doesn't enjoy most of the other advantages stated above.
If you want to create Meteor applications with separate code, you'll have some modules that you'd like to share between them. If those modules are something the wider world could use, you should consider [publishing them to a package system](../../packages/#writing-atmosphere-packages), either npm or Atmosphere, depending on whether the code is Meteor-specific or otherwise.
If the code is private, or of no interest to others, it typically makes sense to include the same module in both applications (you *can* do this with [private npm modules](https://docs.npmjs.com/about-private-packages)). There are several ways to do this:
- a straightforward approach is to include the common code as a [git submodule](https://git-scm.com/book/en/v2/Git-Tools-Submodules) of both applications.
- alternatively, if you include both applications in a single repository, you can use symbolic links to include the common module inside both apps.
### Sharing data
Another important consideration is how you'll share the data between your different applications.
The simplest approach is to point both applications at the same `MONGO_URL` and allow both applications to read and write from the database directly. This works well thanks to Meteor's support for reactivity through the database. When one app changes some data in MongoDB, users of any other app connected to the database will see the changes immediately thanks to Meteor's livequery.
However, in some cases it's better to allow one application to be the master and control access to the data for other applications via an API. This can help if you want to deploy the different applications on different schedules and need to be conservative about how the data changes.
The simplest way to provide a server-server API is to use Meteor's built-in DDP protocol directly. This is the same way your Meteor client gets data from your server, but you can also use it to communicate between different applications. You can use [`DDP.connect()`](https://docs.meteor.com/api/meteor#DDP-connect) to connect from a "client" server to the master server, and then use the connection object returned to make method calls and read from publications.
If you need a more traditional API, you can use the bundled `express` available in Meteor. See the [documentation of WebApp](https://docs.meteor.com/packages/webapp#webapp)
```js
import { Meteor } from "meteor/meteor";
import { WebApp } from "meteor/webapp";
import bodyParser from "body-parser";
const app = WebApp.handlers;
app.use(bodyParser.json());
app.use("/hello", (req, res, next) => {
res.writeHead(200);
res.end(`Hello world from: ${Meteor.release}`);
});
```
### Sharing accounts
If you have two servers that access the same database and you want authenticated users to make DDP calls across the both of them, you can use the *resume token* set on one connection to login on the other.
If your user has connected to server A, then you can use `DDP.connect()` to open a connection to server B, and pass in server A's resume token to authenticate on server B. As both servers are using the same DB, the same server token will work in both cases. The code to authenticate looks like this:
```js
// This is server A's token as the default `Accounts` points at our server
const token = Accounts._storedLoginToken();
// We create a *second* accounts client pointing at server B
const app2 = DDP.connect('url://of.server.b');
const accounts2 = new AccountsClient({ connection: app2 });
// Now we can login with the token. Further calls to `accounts2` will be authenticated
accounts2.loginWithToken(token);
```
You can see a proof of concept of this architecture in an [example repository](https://github.com/tmeasday/multi-app-accounts).
Another pattern is to have another app which acts as identity provider for your apps. The [leaonline:oauth2-server](https://atmospherejs.com/leaonline/oauth2-server) package can be used to create an OAuth2 server in one Meteor app, and then other apps can use the standard `accounts-oauth` packages to authenticate users against it.
---
---
url: /community-packages/archive.md
---
# Archive
- `Who maintains the package` – [Jam](https://github.com/jamauro)
[[toc]]
## What is this package?
Archive is an easy way to add an archive mechanism to your Meteor app. When a document is archived, it's removed from its original collection and placed in an archive collection so that it can be restored if needed. Its key features are:
* Zero config needed (though you can customize)
* Isomorphic so that it works with Optimistic UI
* Automatically overrides `removeAsync` to perform an archive (can be turned off)
* Explicitly archive with `archiveAsync` collection method (optional)
* Restore archived docs with `restoreAsync` collection method
* Optionally exclude specific collections
* Compatible with Meteor `3.0.2+`
> **Note:** Alternative to archive is soft deletion. You can use [`jam:soft-delete`](./soft-delete.md) package for that. Be sure to compare those two approaches to pick the solution best suited for your application.
## How to download it?
Add the package to your app
```bash
meteor add jam:archive
```
### Sources
* [GitHub repository](https://github.com/jamauro/archive)
## How to use it?
### Create your Archives collection
Create an Archives collection in your app just as you would any other collection.
```js
const Archives = new Mongo.Collection('archives');
```
Documents in the Archives collection will have this shape:
```js
{
_id, // auto-generated by Meteor as with other collection _ids
_collection, // the name of the collection, e.g. 'todos', that the doc belonged to originally
archivedAt, // the timestamp when the document was removed from its original collection and inserted into the archive
id, // the original doc _id renamed to prevent conflict with the auto-generated one above. when restored, it will be renamed back to _id automatically by this package
/*
...rest of original doc
*/
}
```
### Deleting permanently
By default, this package overrides the `removeAsync` collection method so that it archives the document(s) rather that removing them from the database. To delete permanently, pass in the option `forever: true`, e.g.:
```js
Collection.removeAsync(/* your filter */, { forever: true })
```
If you prefer, you can prevent overriding the `removeAsync` by setting `overrideRemove: false`. See [Configuring](#configuring-optional) for more details.
### Explicitly archiving
If you prefer, you can explicity use `archiveAsync`, e.g.:
```js
Collection.archiveAsync(/* your filter */)
```
### Restoring a document
To restore an archived document, use `restoreAsync`, e.g.:
```js
Collection.restoreAsync(/* your filter */)
```
## Configuring (optional)
If you like the defaults, then you won't need to configure anything. But there is some flexibility in how you use this package.
Here are the global defaults:
```js
const config = {
name: 'archives', // if your Archives collection uses a different name, you'll want to change this
overrideRemove: true, // overrides the Collection.removeAsync method to make it an archive instead
exclude: ['roles', 'role-assignment'] // exclude specific collections from using archive so that when they are removed, the are permanently removed from the db. defaults to excluding the collections created by the meteor roles package
};
```
To change the global defaults, use:
```js
// put this in a file that's imported on both the client and server
import { Archive } from 'meteor/jam:archive';
Archive.configure({
// ... change the defaults here ... //
});
```
---
---
url: /api/assets.md
---
# Assets
> Currently, it is not possible to import `Assets` as an ES6 module. Any of the `Assets` methods below can simply be called directly in any Meteor server code.
`Assets` allows server code in a Meteor application to access static server
assets, which are located in the `private` subdirectory of an application's
tree. Assets are not processed as source files and are copied directly
into your application's bundle.
Static server assets are included by placing them in the application's `private`
subdirectory. For example, if an application's `private` subdirectory includes a
directory called `nested` with a file called `data.txt` inside it, then server
code can read `data.txt` by running:
```js
const data = await Assets.getTextAsync('nested/data.txt');
```
Note: Packages can only access their own assets. If you need to read the assets of a different package, or of the enclosing app, you need to get a reference to that package's `Assets` object.
---
---
url: /packages/audit-argument-checks.md
---
# Audit Argument Checks
This package causes Meteor to require that all arguments passed to methods and
publish functions are [checked](../api/check.md). Any method that does not pass each
one of its arguments to `check` will throw an error, which will be logged on the
server and which will appear to the client as a
`500 Internal server error`. This is a simple way to help ensure that your
app has complete check coverage.
Methods and publish functions that do not need to validate their arguments can
simply run `check(arguments, [Match.Any])` to satisfy the
`audit-argument-checks` coverage checker.
---
---
url: /packages/autoupdate.md
---
# Autoupdate
This is the Meteor package that provides hot code push (HCP) functionality.
Every Meteor application that wasn't created with the `--minimal` option
has this package already through `meteor-base` and HCP should work out of the
box. For those running `--minimal` applications and want to benefit from this
package, just add it with `meteor add autoupdate`.
> `autoupdate` adds up to 30KB on your client's production bundle.
With this package Meteor will use DDP to publish a collection called
_'meteor_autoupdate_clientVersions'_. This collection will be subscribed by the
user's client and every time the client identifies a change in the published
version it will refresh itself.
## Browser Client
The refresh will happen in the browser in two different ways: a _soft update_,
and a _hard update_. If Meteor identifies that only stylesheets were changed, then it
will verify if the user's browser is capable of reloading CSS on the fly, and a
soft update will take place. The soft update will replace the old stylesheet
with the new stylesheet without triggering a full page reload.
In cases where a change in a server's or client's compiled file happens, the hard
update will take place: Meteor will force a complete browser reload using the
`reload` package.
> Among other things, the `reload` package tries do reload the application
> preserving some unchanged cached files.
## Cordova Client
There is no soft update with Cordova apps, the client is always fully refreshed
once a change is detected.
### `usesCleartextTraffic`
Starting with Android 9 (API level 28), [cleartext support is disabled](https://developer.android.com/training/articles/security-config) by default.
During development `autoupdate` uses cleartext to publish new client versions.
If your app targets Android 9 or greater, it will be necessary to create a
`mobile-config.js` file enabling the use of cleartext in order to have HCP working:
```js
App.appendToConfig(`
`);
```
### `--mobile-server`
Additionally, for the HCP functionality to work it is also mandatory to provide
the address for the application server with `--mobile-server` option. If you're
testing your app on an emulator you should run it with `meteor run android --mobile-server 10.0.2.2:3000`.
If you're running it on a real device, the application server and the device
should be on the same network, and you should run your app with `meteor run android --mobile-server XXX.XXX.XXX.XXX`
where *XXX.XXX.XXX.XXX* is your local development address, _e.g. 192.168.1.4_.
> To have a better understanding of how HCP works for mobile apps already
> published to production refer to [Hot code push on mobile](https://guide.meteor.com/cordova.html#hot-code-push)
---
---
url: /api/blaze.md
---
# Blaze
How to use Blaze, Meteor's reactive rendering engine.
This documentation has moved to the [Blaze Community Site](http://blazejs.org/api/templates).
---
---
url: /packages/browser-policy.md
---
# Browser Policy
The `browser-policy` family of packages, part of
[Webapp](https://github.com/meteor/meteor/tree/master/packages/webapp), lets you
set security-related policies that will be enforced by newer browsers. These
policies help you prevent and mitigate common attacks like cross-site scripting
and clickjacking.
## Details
When you add `browser-policy` to your app, you get default configurations for
the HTTP headers X-Frame-Options and Content-Security-Policy. X-Frame-Options
tells the browser which websites are allowed to frame your app. You should only
let trusted websites frame your app, because malicious sites could harm your
users with [clickjacking attacks](https://www.owasp.org/index.php/Clickjacking).
[Content-Security-Policy](https://developer.mozilla.org/en-US/docs/Security/CSP/Introducing_Content_Security_Policy)
tells the browser where your app can load content from, which encourages safe
practices and mitigates the damage of a cross-site-scripting attack.
`browser-policy` also provides functions for you to configure these policies if
the defaults are not suitable.
If you only want to use Content-Security-Policy or X-Frame-Options but not both,
you can add the individual packages `browser-policy-content` or
`browser-policy-framing` instead of `browser-policy`.
For most apps, we recommend that you take the following steps:
- Add `browser-policy` to your app to enable a starter policy. With this starter
policy, your app's client code will be able to load content (images, scripts,
fonts, etc.) only from its own origin, except that XMLHttpRequests and WebSocket
connections can go to any origin. Further, your app's client code will not be
able to use functions such as `eval()` that convert strings to code. Users'
browsers will only let your app be framed by web pages on the same origin as
your app.
- You can use the functions described below to customize the policies. If your
app does not need any inline Javascript such as inline `
{{ task.text }}
```
:::
Since the `Task` component will be part of a list, it returns a `li` element.
For now, we won’t connect to our database, so define some sample data in the `App.vue` file to display a list of tasks. Create an array and a function to return this array.
::: code-group
```vue [imports/ui/App.vue]
Hello Meteor
```
:::
### 1.5: Rendering Tasks
Now let's add some simple rendering logic with Vue to display our list items using the `Task` component.
Update the template of the `App` component to include the list of tasks:
::: code-group
```vue [imports/ui/App.vue]
Todo List
```
:::
For more information on Vue iterations, you can read [here](https://vuejs.org/api/built-in-directives.html#v-for).
In the next step, we will connect to the MongoDB database to store our tasks.
## 2: Collections
Meteor already sets up MongoDB for you. In order to use our database we need to create a *collection*, which is where we will store our *documents*, in our case our `tasks`.
You can read more about collections [here](http://guide.meteor.com/collections.html).
In this step we will implement all the necessary code to have a basic collection for our tasks up and running.
### 2.1: Create Tasks Collection
Before creating our collection, let's remove the `links.js` file from the `imports/api` folder because we won't use it. Now, you can create a new collection to store our tasks by creating a new file named `tasksCollection.js` inside the `imports/api` folder.
::: code-group
```javascript [imports/api/tasksCollection.js]
import { Mongo } from 'meteor/mongo';
export const TasksCollection = new Mongo.Collection('tasks');
```
:::
The code above instantiates a new MongoDB collection and exports it. You can read more about app structure and imports/exports [here](https://guide.meteor.com/structure.html).
### 2.2: Initialize Tasks Collection
To make our collection work, you need to import it on the server to set things up.
You can use import `'./imports/api/tasksCollection'` or `import { TasksCollection } from './imports/api/tasksCollection'` if you plan to use `TasksCollection` in the same file. Just make sure it's imported.
Now, it’s easy to check if there is data in our collection, or we can easily add some sample data.
Replace the old content in `server/main.js` with the code below.
::: code-group
```javascript [server/main.js]
import { Meteor } from 'meteor/meteor';
import { TasksCollection } from '../imports/api/tasksCollection';
const insertTask = async text => await TasksCollection.insertAsync({text});
Meteor.startup(async () => {
const tasksCount = await TasksCollection.find().countAsync();
if (tasksCount === 0) {
await insertTask('First Task');
await insertTask('Second Task');
await insertTask('Third Task');
await insertTask('Fourth Task');
await insertTask('Fifth Task');
await insertTask('Sixth Task');
await insertTask('Seventh Task');
}
});
```
:::
So you are importing the `TasksCollection` and adding a few tasks on it calling a function to insert this string as our `text` field in our `task` document.
### 2.3: Render Tasks Collection
Now comes the fun part, you will render the tasks using a “data container” to feed Meteor’s reactive data into Vue’s component hierarchy. We will use the [vue-meteor-tracker](https://www.npmjs.com/package/vue-meteor-tracker) package for this.
::: info
Meteor works with Meteor packages and NPM packages, usually Meteor packages are using Meteor internals or other Meteor packages.
:::
The `vue-meteor-tracker` package is already included in the Vue skeleton, so you don’t need to add it.
When importing code from a Meteor package the only difference from NPM modules is that you need to prepend `meteor/` in the from part of your import.
First we need to implement a subscription at the `App` component to get the tasks updated from the server. It can be done simply by using the `subscribe` and `autorun` functions from `vue-meteor-tracker`.
::: info
The `vue-meteor-tracker` package doesn't support async calls yet, so we need to use sync functions. This is not an issue, but it's important to know.
:::
::: code-group
```vue [imports/ui/App.vue]
Todo List
```
:::
To be able to fetch data in the client, you need to publish it in the server. To do it, create a file called `tasksPublications.js` and add the following code:
::: code-group
```javascript [imports/api/tasksPublications.js]
import { Meteor } from 'meteor/meteor';
import { TasksCollection } from './tasksCollection';
Meteor.publish('tasks', function publishTasks() {
return TasksCollection.find();
});
```
:::
Now, import it on the server:
::: code-group
```javascript [server/main.js]
import '../imports/api/tasksPublications';
```
:::
> If you want to learn more about how publications works, you can read [here](/api/meteor.html#pubsub).
Now, your app should look like this:

You can change your data on MongoDB in the server and your app will react and re-render for you.
You can connect to your MongoDB running `meteor mongo` in the terminal from your app folder or using a MongoDB UI client, like [NoSQLBooster](https://nosqlbooster.com/downloads) or [MongoDB Compass](https://www.mongodb.com/products/tools/compass). Your embedded MongoDB is running in the port `3001`.
See how to connect:

See your database:

You can double-click your collection to see the documents stored on it:

## 3: Forms and Events
Now, we need to let users interact with the stored data. In our case, the first interaction is to add new tasks. One of the main ways in which a user can insert or edit data in a website is through forms, using the `