Customizing the platform

We recommend starting with the Bit Symphony platform as a foundation. It provides a robust set of pre-built APIs and functionalities that you can customize to fit your specific needs. This approach can significantly accelerate your development process and reduce boilerplate code.

App layout

To customize UI app layout and routing, register your custom component to the Symphony app layout slot:

// acme-platform.browser.runtime
import { AppLayout } from '@acme/acme.layouts.app-layout';

export class AcmePlatformBrowser {
  static dependencies = [SymphonyPlatformAspect];
  static async provider([symphonyPlatform]: [SymphonyPlatformBrowser]) {
    const acmePlatform = new AcmePlatformNode();

    symphonyPlatform.registerLayoutComponent(() => {
      return <AppLayout />;
    });

    return acmePlatform;
  }
}
CopiedCopy

For building composable UI, start with the AppLayout component and the registerLayoutEntry API. This encourages consistency and reusability within your applications. For layout customization within a Symphony platform, refer to the create platform aspect documentation.

API gateway

Symphony's API gateway supports Express and GraphQL by default. You can override this default gateway by implementing a custom gateway and registering it with the Symphony platform instance. This allows you to tailor the gateway logic to your specific needs:

export class AcmePlatformNode {
  static dependencies = [SymphonyPlatformAspect];
  static async provider([symphonyPlatform]: [SymphonyPlatformNode]) {
    const acmePlatform = new AcmePlatformNode();

    symphonyPlatform.registerGateway(
      new MyGateway()
    );

    return acmePlatform;
  }
}
CopiedCopy

When implementing your API gateway, consider the features and structure of the Symphony default gateway as a starting point. It demonstrates how to handle common gateway tasks

Backend services

This is often useful to expose a slot API for Aspects to plugin new backend servers and route them using an API gateway. The default Platform aspect is using Apollo GraphQL and ExpressJS to allow for other aspect to introduce a GraphQL and RESTful APIs the registerBackendServer API method:

export class PeopleNode {
  static dependencies = [SymphonyPlatformAspect];
  static async provider([symphonyPlatform]: [SymphonyPlatformNode]) {
    symphonyPlatform.registerBackendServer([
      {
        routes: [],
        gql: gqlSchema,
      },
    ]);
  }
}
CopiedCopy

You can replace the default backend service implementation with your own by implementing the BackendServer interface. Use the Symphony default backend service implementation as an example to create your own.

Platform aspect from scratch

Alternatively, you can create your own custom platform aspect and implement the platform API including DOM mounting anc backend infrastructure from scratch.

If you are looking for a fully custom stack, or greater level of control over the [platform] than what is available in Symphony's APIs create your own by running the following command:

bit create platform-aspect wayne-platform
CopiedCopy

To replace the platform aspect and remove Symphony from your stack, add your custom Platform Aspect to the shell app's platform property.

import { WaynePlatformAspect } from '@wayne/wayne.wayne-platform';
import { PeopleAspect } from '@wayne/people.people';

export const WaynePlatform = HarmonyPlatform.from({
  name: 'wayne-platform',

  // your fully implemented platform
  platform: WaynePlatformAspect,

  aspects: [
    PeopleAspect
  ]
});

export default WaynePlatform;
CopiedCopy

DOM mounting

Use the Browser runtime to render UI for the web in SSR and CSR:

import { hydrateRoot } from 'react-dom/client';

export class WaynePlatformBrowser {

  get apiGatewayUrl() {
    // Backend API endpoint is wired as an env variable. 
    return process.env.API_GATEWAY;
  }

  // render the UI in the browser.
  render() {
    // CSR rendering logic. 
  }

  renderSsr() {
    // SSR rendering logic.    
  }

  static async provider() {
    return new WaynePlatformBrowser();
  }
}
CopiedCopy

You can create new runtimes for Harmony by implementing a Runtime. Learn more on implementing Harmony runtimes.

Run the server API

Use the NodeJS runtime to run your servers and return the port and URL to be wired to your other runtimes.

export class WaynePlatformNode {
  run() {
    console.log('hello my platform!');

    // return the server information to be wired to other runtimes.
    return {
      appName: 'wayne-server',
      port: 5001,
      url: 'http://localhost:5001'
    };
  }

  static async provider() {
    return new WaynePlatformNode();
  }
}
CopiedCopy

It is recommended to expose a slot API for registering backend services and orchestrating a micro service architecture. See Wayne Platform example to learn how to use a micro service architecture in Harmony.

Routing

The default Platform aspect template uses React Router for routing, and allows for other aspects to plugin a route using the registerRoute method.

Testing platform aspects

Platform Aspects are tested just like every other Aspect. Learn more on testing Aspects.

Fork Symphony

You can fork Symphony as a jump start to building your own platform. Run the following command to fork your own platform:

bit fork bitdev.symphony/symphony-platform acme-platform
CopiedCopy