Platform aspect is the bedrock of how your composable features are unified for the shell app. It provides layout, routing and other APIs for Aspects to integrate with the platform.
Symphony provides a ready-to-use platform foundation built with React, GraphQL and Express. You can use Symphony and customize it for your needs by replacing its capabilities with your own tools.
To learn how to use platform aspects and integrate with them, start by creating an aspect:
bit create aspect pied-platform
Now you can use the Symphony platform APIs. Later you will customize Symphony.
Harmony brings an API first approach to platform engineering, enabling to provide a clear, programmatic API for feature integration. This platform's layout and operations, promotes consistency, and streamlines collaboration between feature teams:
// people.browser.runtime.tsx import type { Route } from '@bitdev/symphony.frontends.route'; import { SymphonyPlatformAspect, SymphonyPlatformBrowser } from '@bitdev/symphony.symphony-platform'; export class PiedPlatformBrowser { constructor( private config: PiedPlatformConfig, private symphonyPlatform: SymphonyPlatformBrowser, ) {} // Define your platform APIs. registerRoute(routes: Route[]) { this.symphonyPlatform.registerRoute(routes); return this; } static dependencies = [SymphonyPlatformAspect]; static async provider([symphonyPlatform]: [SymphonyPlatformBrowser], config: PiedPlatformConfig, ) { const piedPlatform = new PiedPlatformBrowser(config, panelSlot); // integrate the application layout and further components as needed. symphonyPlatform.registerLayoutEntry([ { position: 'top', component: () => { return <Header />; } } ]); return piedPlatform; } } export default PiedPlatformBrowser;
The basic above example demonstrates a simple platform aspect exposing the registerRoute
API allowing other aspects to register new routes and integrating the Header component into the platform.
To customize the theme, use the registerTheme
API method provided by the Symphony API.
export class PiedPlatformBrowser { static dependencies = [SymphonyPlatformAspect]; static async provider( [symphonyPlatform]: [SymphonyPlatformBrowser], ) { const piedPlatform = new PiedPlatformBrowser(config, panelSlot); // register your custom theme to the Symphony platform. symphonyPlatform.registerTheme((props) => { return <PiedTheme {...props} />; }); return piedPlatform; } } export default PiedPlatformBrowser;
The example above replaces the default Sparks Theme provided by Symphony with a custom theme. You can checkout the full component examples in the Pied Piper demo.
By default, Symphony uses React Router. Use the Platform aspect's API to register routes and integrate components into specific slots within the unified app:
export class PiedPlatformBrowser { static dependencies = [SymphonyPlatformAspect]; static async provider( [symphonyPlatform]: [SymphonyPlatformBrowser], ) { const piedPlatform = new PiedPlatformBrowser(config, panelSlot); // register a new route to the app. symphonyPlatform.registerRoute([ { path: '/', component: () => { return <Homepage /> } }, ]); // register a page not found. symphonyPlatform.registerPageNotFound(() => <PageNotFound />); return piedPlatform; } }
You can use also render React Router <Routes>
in route components for internal or nested routing.Within your route components, you can also use React Router components (e.g., <Route>
, <Switch>
, etc.) for nested or internal routing.
To provide global context for features (such as theming or internationalization), create a React context in your aspect. Then, use a provider component from your aspect to wrap the root of your application. This makes the context accessible to all components in the application.
To wrap the root of your app, register a top level component and ensure to accept and render the component children:
export class PiedPlatformBrowser { static dependencies = [SymphonyPlatformAspect]; static async provider( [symphonyPlatform]: [SymphonyPlatformBrowser], ) { const piedPlatform = new PiedPlatformBrowser(config, panelSlot); // register a global authentication provider. symphonyPlatform.registerTopLevel([ component: ({ children }) => { return <AuthProvider>{children}</AuthProvider> } ]); return piedPlatform; } }
The Hud API allows you to register components that render above the main content area, without needing to wrap the existing content. This is particularly helpful for displaying overlays, notifications, or other UI elements that shouldn't interfere with the underlying page structure. For example, this is how you display notices.
export class PiedPlatformBrowser { static dependencies = [SymphonyPlatformAspect]; static async provider( [symphonyPlatform]: [SymphonyPlatformBrowser], ) { const piedPlatform = new PiedPlatformBrowser(config, panelSlot); symphonyPlatform.registerHud([ () => { return <Notice /> } ]); return piedPlatform; } }
Symphony provides a simple and flexible app layout component and APIs for registering components to different sections of the layout:
export class PiedPlatformBrowser { static dependencies = [SymphonyPlatformAspect]; static async provider( [symphonyPlatform]: [SymphonyPlatformBrowser], ) { const piedPlatform = new PiedPlatformBrowser(config, panelSlot); symphonyPlatform.registerLayoutEntry([ { position: 'top', component: () => { return <Header />; } }, { position: 'left', component: () => { return <SidebarNav />; } }, ]); return piedPlatform; } }
The Sparks App Layout component is used by default, but you can replace it using registerLayoutComponent.
Symphony supports data fetching using both GraphQL and RESTful APIs. By default, it sets up @apollo/client to use the API gateway. Here's an example for a React hook component utilizing Apollo Client to fetch data from the aspect GraphQL API.
For RESTful data fetching, consider building a dedicated hook that leverages environment variables to interact with the Symphony API gateway. This approach promotes better code organization and maintainability.
To effectively manage state throughout the platform, we recommend leveraging React's state management capabilities with Hooks. By encapsulating Context providers within custom Hooks, you can enhance code organization, improve reusability, and promote a more maintainable codebase.
If a particular piece of state needs to be accessible across multiple parts of your application, consider using the provided global context APIs. However, use global state sparingly to avoid potential complexity and unexpected side effects.
The Symphony platform provides the following default environment variables:
NODE_RUNTIME_PORT
. The port the API gateway to set to.NODE_RUNTIME_URL
. The full URL the API gateway.
To enhance privacy and security for your platform, avoid storing or processing sensitive data (secrets) directly within the browser's runtime environment. Instead, leverage the Node.js runtime for managing and handling secrets, ensuring they remain protected and secure
You can reuse your 100% of your existing code by following our gradual migration guide. To learn more, head to the Gradual migration documentation.