This is the legacy documentation of Project-level Custom Applications, which is in maintenance mode. Visit the new documentation for Org-level Custom Applications.
Example Deployment with Vercel
This deployment example refers to the Vercel serverless deployment, formerly ZEIT Now.
Prerequisites
Before you get started, you need to have:
A commercetools account and a project.
In this example we are going to use the commercetools platform running on the Europe cloud region on Google Cloud.
A Vercel account
The Vercel CLI
We're going to deploy the application under the domain mc-examples-starter.vercel.app
.
The mc-examples-starter.vercel.app
domain is already in use. Pick a different one if you choose to deploy using Vercel.
Configuration
To start, we need to update the custom-application-config.json
file with the production URL:
{"name": "mc-examples-starter","entryPointUriPath": "examples-starter","cloudIdentifier": "gcp-eu","env": {"production": {"url": "http://mc-examples-starter.vercel.app"}}}
To configure Vercel (formerly Zeit Now) deployments, we can use a vercel.json
file. It looks something like this:
{"version": 2,"public": true,"name": "mc-examples-starter.vercel.app","alias": "mc-examples-starter.vercel.app","regions": ["bru"],"builds": [{"src": "public/**","use": "@vercel/static"}],"routes": [{"src": "/(.*).(js.map|js|css|txt|html|png)","dest": "/public/$1.$2","headers": {"cache-control": "s-maxage=31536000,immutable"}},{"src": "/(.*)","dest": "/public/index.html","headers": {"Cache-Control": "no-cache"}}]}
Some fields may vary based on your setup and requirements, for example public
, regions
, etc.
However, that won't work just yet as the Custom Application does not have an index.html
after building the production bundles.
To make it work, we need to compile the application first.
Compile the application
To be able to deploy the Custom Application to the Vercel platform, the Custom Application needs to be compiled.
mc-scripts compile-html
The command above does what we need: it compiles the index.html
using the JavaScript bundle references (after running mc-scripts build
) and the runtime configuration. At this point the index.html
file is ready for production usage.
However, the Custom Application needs to instruct the User-Agent (the browser) to enforce certain security measures, using HTTP headers (done automatically by the application config).
Because of that, the vercel.json
file cannot be defined statically. Instead, it needs to be generated programmatically when the Custom Application is built and compiled.
To achieve that, we need to implement a transformer function.
Generate vercel.json
using a transformer function
The compile-html
command accepts an option transformer
which we can use to pass the filesystem path to our transformer function.
We assume that the transformer function is defined at the following location: ./config/transformer-vercel.js
.
mc-scripts compile-html \--transformer ./config/transformer-vercel.js
The purpose of the transformer function is to generate the final vercel.json
given the compiled values passed to the function.
// Function signature using TypeScripttype TransformerFunctionOptions = {// The runtime environment specified within the application config.env: Json;// The compiled HTTP headers, including the Content-Security-Policy headers.headers: Json;// The final HTML content of the `index.html`.indexHtmlContent: string;}type TransformerFunction = (options: TransformerFunctionOptions) => void;
The main export of the file should be the transformer function.
module.exports = function transformer(options) {// ...}
With that in mind, we can implement the transformer function and write the vercel.json
config into the filesystem.
const fs = require('fs');const path = require('path');const rootPath = path.join(__dirname, '..');module.exports = function transformer({ headers }) {const config = {version: 2,public: true,name: 'mc-examples-starter.vercel.app',alias: 'mc-examples-starter.vercel.app',regions: ['bru'],builds: [{ src: 'public/**', use: '@vercel/static' },],routes: [{src: '/(.*).(js.map|js|css|txt|html|png)',dest: '/public/$1.$2',headers: { 'Cache-Control': 's-maxage=31536000,immutable' },},{src: '/(.*)',dest: '/public/index.html',headers: { 'Cache-Control': 'no-cache', ...headers },},],};fs.writeFileSync(path.join(rootPath, 'vercel.json'),JSON.stringify(config, null, 2),{ encoding: 'utf8' });};
Adding fallback routes
This step is optional and does not prevent the application to be used within the Merchant Center. However, it's recommended to do so to avoid unexpected behaviors in case the URL, where the Custom Application is hosted, is accessed directly.
Accessing the Custom Application directly at https://mc-examples-starter.vercel.app
won't work, as the application requires the user to log in and thus tries to redirect to the /login
route at the same domain.
To prevent that, we can add a dummy fallback route for the login|logout
routes. This is only meant to inform the user that the Custom Application cannot be used standalone.
module.exports = function fallbackRoute(request, response) {response.end('This is not a real route. If you are seeing this, you most likely are accessing the custom application\n' +'directly from the hosted domain. Instead, you need to access the custom application from within the Merchant Center\n' +'domain, as custom applications are served behind a proxy router.\n' +'To do so, you need to first register the custom application in Merchant Center > Settings > Custom Applications.');};
This route will be used as a serverless function:
const fs = require('fs');const path = require('path');const rootPath = path.join(__dirname, '..');module.exports = function transformer({ headers }) {const config = {version: 2,public: true,name: 'mc-examples-starter.vercel.app',alias: 'mc-examples-starter.vercel.app',regions: ['bru'],builds: [{ src: 'public/**', use: '@vercel/static' },{ src: 'config/fallback-route.js', use: '@vercel/node' },],routes: [{src: '/(.*).(js.map|js|css|txt|html|png)',dest: '/public/$1.$2',headers: { 'Cache-Control': 's-maxage=31536000,immutable' },},{ src: '/(login|logout)', dest: '/config/fallback-route.js' },{src: '/(.*)',dest: '/public/index.html',headers: { 'Cache-Control': 'no-cache', ...headers },},],};fs.writeFileSync(path.join(rootPath, 'vercel.json'),JSON.stringify(config, null, 2),{ encoding: 'utf8' });};
Deployment
Finally, we can trigger the deployment using the Vercel CLI:
yarn buildmc-scripts compile-html \--transformer ./config/transformer-vercel.jsvercel
Now you're ready to Register your Custom Application and start using it!