---
schema_version: "1"
id: 0c98ab24513c3256cf97a735345bd1d7b6b5e486d2aabf553f14dcc913fd0455
title: Controllers
collection: developer
version: current
locale: en-us
portal_url: https://docs.salesforce.com/developer/current/en-us/commerce-cloud/b2c-commerce/guides/site-development/b2c-working-with-controllers.md
canonical_url: https://developer.salesforce.com/docs/commerce/pwa-kit-managed-runtime/guide/b2c-working-with-controllers.html
source_site: developer.salesforce.com
content_type: documentation
content_hash: 21e4eed13ed42ba7f93063e97434c6a40682e6cda5c3bdabf83f78314b9dc09c
products:
  - Composable Storefront
  - Salesforce APIs
---
# Controllers

Controllers are server-side scripts that handle storefront requests. Controllers manage the flow of data in your application, and create `ViewModels` to process each storefront request as a `route` and generate an appropriate response. For example, in a storefront application, clicking a category menu item or entering a search term triggers a controller that renders a page.

Controllers are written in JavaScript and Salesforce B2C Commerce script. They must conform to the CommonJS module standard.

A controller's file extension can be either .ds or .js. Controllers must be located in the `controllers` folder at the top level of the cartridge. Exported methods for controllers must be explicitly made public to be available to handle storefront requests.

Example: SFRA Base Cartridge Controller Hello.Js

```javascript
"use strict";

var server = require("server");
var cache = require("*/cartridge/scripts/middleware/cache");

server.get("World", cache.applyDefaultCache, function (req, res, next) {
  res.render("helloworld", {
    Message: "Hello World! Again.",
  });
  next();
});

module.exports = server.exports();
```

Controllers can use `require` to:

- Import script modules. Any B2C Commerce script can be made into a CommonJS module and required by a controller.
- Import B2C Commerce packages, instead of using the `importPackages` method. This approach is the recommended way to reference functionality from a controller. Use the require method to import a single B2C Commerce class. For example:

  ```js
  var rootFolder = require("dw/content/ContentMgr").getSiteLibrary().root;
  ```

While it isn't best practice, controllers can also:

- Call other controllers. We don't recommend that controllers call each other, because controller functionality is self-contained to avoid circular dependencies. Sometimes, however, such as calling non-public controllers during the checkout process, it's unavoidable.
- Call pipelets. We strongly discourage calling pipelets from within a controller. However, it's allowed while there are still pipelets that don't have equivalent B2C Commerce script methods.
- Import packages. We discourage this approach because it doesn't use standard JavaScript patterns. This approach is Rhino-specific.
- Call pipelines that don't end in interaction continue nodes. This technique is only intended for use with existing link cartridges and is highly discouraged for general development.

  **note:** It isn't currently possible to call pipelines that end in interaction continue nodes.

## Request URLs

A request URL for a controller has the format `controller-function`. For example, the request URL for the Hello.js controller World function looks like:

```
https://localhost/on/demandware.store/Sites-RefArch-Site/default/Hello-World
```

For more information, see [B2C Commerce URL Syntax Without SEO](https://help.salesforce.com/s/articleView?id=cc.b2c_digital_url_syntax_without_seo.htm).

## Reserved Names for Controllers

B2C Commerce has several system names that are reserved and can't be used for custom controllers and their functions. For a full list, see System Pipelines and Controllers in our [Legacy Developer Documentation](https://salesforcecommercecloud.github.io/b2c-dev-doc/docs/current/LegacyDeveloperDocumentation.pdf).

## Global Variables, Request Parameters, and Page Meta Data

SFRA uses the `server.req`and `server.res` objects for request and response data. While global variables are still available, we don't recommend that you use them.

## Debugging

Almost any JavaScript-related error gets logged in the `customerror_* log` files, including errors from B2C Commerce scripts and controllers. The `error_*` log files contain Java-related errors on B2C Commerce, and are probably less useful to non-B2C Commerce employees

The `Error.js` controller services uncaught errors. By default, B2C Commerce returns a 410 error, which indicates that the resource is no longer available. If you prefer 404, it's fine to use as long as the related ISML template doesn't include `<isslot>`, `<iscomponent>`, or `<isinclude>` tags. When you want to handle these errors explicitly, use `try/catch` statements.

## Best Practices

Only require modules when you need them, not at the top of a module.

## Using with OCAPI

Build a mobile or native app in addition to your storefront. If you want to create modules that work both for a desktop storefront and a mobile app, use hooks.
