1. Home
  2. Docs
  3. Docs
  4. Writing plugins

Writing plugins

Plugins are the strength of Phenomic and what make it so flexible and reusable. Phenomic allows you to interact with it at several state of the process depending on what you need.

Learn more about Phenomic lifecycle

To know how to use a plugin see the configuration plugins option.

Creating your plugin

A plugin can take the form of a node_modules or directly a function in the configuration. It must be a function that returns object.

module.exports = (/* options */) => {
  return {
    // plugin
    name: phenomic-plugin-name,
    // fake method name
    method1: () => {},
    method2: () => {}

Note that you can also export using ES2015 export

const yourPlugin = (/* options */) => {
  return {
    // plugin
    // …
export default yourPlugin;

If your plugin accepts options, you can use the first parameter of the function. This parameter will receive the option that you can inject via the configuration plugins option.


The best source of examples will be phenomic plugins included in our repository.

Plugins interesting part are usually located at phenomic/packages/plugin-*/src/index.js.

Lifecycle methods

Here are the list of methods that allows you to interact with Phenomic lifecycle.


The method collect is useful if you plan to use Content API. It allows you to collect your data before rendering and to inject it into the database.

collect: ({ db, transformers }) => Promise;

It receive the database and all transformers plugin as arguments

Used in

supportedFileTypes + transform

The method transform is useful if you plan to use Content API. It allows you to transform files (that match supportedFileTypes – array of files extensions) as something ready for Phenomic database.


Array of files extensions.


supportedFileTypes: [md, markdown]; // will match *.md and *.markdown

Used in


Function that accepts an object and must return an result ready for Phenomic database:

transform: ({
  // you will only receive file that match `supportedFileTypes`
  file: { name: string, fullpath: string },
  contents: Buffer
}) {
  // do your thing to parse `contents`
  // …
  // then return a database entry
  return {
    data: Object,
    partial: Object

Learn more about database entries in Content API documentation.

Used in


Allows you to do a JavaScript bundle for client side rendering (CSR). Should return an object (map) of files (js and css) generated by the bundler.

build: () => assets,

Used in


Allows you to do a JavaScript bundle for static side rendering (SSR).

The result will be passed to the getRoutes() method. Your can return a promise.

buildForPrerendering: () => Promise<result that will be passed to `getRoutes`>,

Used in


getRoutes: (resultOf_buildForPrerendering) => routes,

Used in


Allows to resolve all possibles URLS for static side rendering (SSR). Receive an object with the routes returned by getRoutes.

resolveURLs: ({
}) => Promise<Array<url>>,

Used in


Allows to statically generated some files. Receive an object that contains the result of buildForPrerenderingbuild and the url to render. Should return an array of files (a file is a path + its contents). Promise are accepted.

renderStatic: ({|
  app /* result of `buildForPrerendering` */,
  assets /* result of `build` */,
  location /* url to prerender */
|}) => Promise<Array<{ path, contents }>>,

Used in


Allows to generated the HTML for the entry point for development. Receive an object that contains the result of build and the url to render.

Should return some HTML.

renderDevServer: ({
  assets  /* result of `build` */,
  location /* url to prerender */
}) => htmlString,

Used in


Allows you to inject some express middleware for development server. Should return an array of express middlewares. Promise are accepted.

addDevServerMiddlewares: () =>
  | Array<express$Middleware>
  | Promise<Array<express$Middleware>>,

Used in


Allows you to do anything before the build. Can return a promise.

beforeBuild: () => void | Promise<void>,

Used in


Allows you to do anything after the build. Can return a promise.

afterBuild: () => void | Promise<void>


Allows to extend the API with new endpoints. Handy for custom queries to the database. Accept an object with API (express server) and Phenomic databse to hit directly on it.


extendAPI: ({
  apiServer /* express api server */,
  db /* phenomic databse */
}) => {
  apiServer.get(/your-custom-path/:path/:id.json, async function(
  ) {
    try {
      // get an item from its id
      const entry = db.get(req.params.path, req.params.id);
      // some business logic
      // …
      res.json(/* your json */);
    } catch (error) {

Learn more about database Content API documentation.

Used in

Was this article helpful to you? Yes No