Building Composable Platforms with Harmony
In today’s fast-paced digital landscape, the need for adaptive, scalable, and maintainable software systems is greater than ever.
Traditional monolithic architectures often fall short in meeting these demands due to their rigidity and complexity. Enter Harmony, a framework designed to enable composable platforms with high efficiency and flexibility.
In this article, we'll explore how Harmony, powered by Bit, transforms the way we build and maintain modern applications.
What is Harmony?
Harmony is a minimalistic yet powerful dependency-injection framework tailored for creating composable architectures. By enabling developers to stitch together independently developed Bit components, Harmony allows teams to build applications that are not only modular but also adaptable to evolving business needs. Harmony supports full-stack composability, making it ideal for integrating frontend and backend functionalities into cohesive platforms.
Key Features of Harmony
Pluggable Aspects: Modular business features, called aspects, can be easily integrated into platforms.
Runtime Flexibility: Official support for Node.js and browser environments ensures compatibility across diverse use cases.
Why Composability Matters
Composability empowers organizations to:
Adapt Quickly: New features can be added or updated independently without disrupting the existing system.
Promote Reusability: Shared components can be leveraged across multiple projects, reducing duplication and increasing consistency.
Foster Collaboration: Teams can work on isolated aspects or components without stepping on each other’s toes.
Building a Composable System with Harmony
As mentioned, the building blocks of a Harmony system are Bit components. However, since Bit components are containers for any unit of software, not every Bit component will do.
Harmony uses components with a specific design to allow them to consume and provide "services" to and from other aspects. These can be frontend-only, backend-only, or full-stack features.
An aspect represents a single business capability that can be plugged into a larger system to form a full solution, a new application.
Aspects extend other aspects by registering to their ‘slot’ API. This inversion of control allows teams to compose features or business capabilities with minimal overhead since the aspect is responsible for the integration, not the system that composes it.
For example, the following Harmony app is an online shop for surfer clothing.
The team responsible for that online store decided to add a blog to their site. After searching for a suitable Aspects on the Bit platform, they came across this Blog aspect. Deciding they wanted to use it, they added it to their Hamrony application:
/** * @coponentId: learnbit.apparel-waves/apparel-waves * @filename: apparel-waves.bit-app.ts */ // imports... import { SymphonyPlatformAspect } from '@bitdev/symphony.symphony-platform'; import { ApparelWavesPlatformAspect } from '@learnbit/apparel-waves.apparel-waves-platform'; import { BlogAspect } from '@learnbit/blog-pbc.blog'; export const ApparelWaves = HarmonyPlatform.from({ name: 'apparel-waves', platform: [ /** * ascpects register themsevles to the 'platform' aspect which * is the entry point for this application */ SymphonyPlatformAspect, { name: 'Apparel Waves', slogan: 'Making waves in fashion', domain: 'apparel-waves.com', }, ], /** * aspects can run in multiple runtime environments. here, aspects * provide functionalitis to the NodeJS services and to the web frontend apps */ runtimes: [new BrowserRuntime(), new NodeJSRuntime()], aspects: [ /* 'apperal waves' aspect extends the system with its * own unique functionalities. this aspect is maintained by * a team that composes the apsects for their own solution. */ ApparelWavesPlatformAspect, /** * the blog aspect extends the system with content * management capabilities. it is maintained by the blog PBC team. */ [ BlogAspect, { /** * the blog aspect also provide a config api for this app to use * in this case, since the the blog uses the Contenful platform, * the fusion team need to provide it with their own Contentful space ID */ spaceId: 'contentful-spaceId', }, ], ], }); export default ApparelWaves;
The Blog aspect registers itself to the platform in several ways:
It extends the system’s GraphQL schema with a node for content retrieval. This is done in the NodeJS Runtime.
It extends the system’s routing with the /blog route. This is done in the Browser Runtime.
It extends the header with an additional item a ‘Blog’ link to /blog. This is done in the Browser Runtime.
NodeJS Runtime
/** * @coponentId: learnbit.blog-pbc/blog * @filename: blog.node.runtime.ts */ export class BlogNode { constructor(private config: BlogConfig) {} async getBlogPosts() { const blogData = new BlogData(this.config); return blogData.getBlogPosts(); } static dependencies = [SymphonyPlatformAspect]; static async provider( [symphonyPlatform]: [SymphonyPlatformNode], config: BlogConfig ) { const blog = new BlogNode(config); const gqlSchema = blogGqlSchema(blog); symphonyPlatform.registerBackendServer([ { gql: gqlSchema, }, ]); return blog; } } export default BlogNode;
Browser Runtime
** * @coponentId: learnbit.blog-pbc/blog * @filename: blog.browser.runtime.ts */ export class BlogBrowser { constructor(private config: BlogConfig) {} static dependencies = [SymphonyPlatformAspect, HeaderAspect]; static async provider( [symphonyPlatform, header]: [SymphonyPlatformBrowser, HeaderBrowser], config: BlogConfig ) { const blog = new BlogBrowser(config); symphonyPlatform.registerRoute([ { path: '/blog', component: () => { return ( <apolloblogprovider spaceid="{config.spaceId}"> <bloglobby></bloglobby> </apolloblogprovider> ); }, }, ]); header.registerLink([{ label: 'Blog', href: '/blog' }]); return blog; } } export default BlogBrowser;
The blog aspect in this example uses the Contentful content management system. It offers a coherent “language” for bought services within the company’s aspect ecosystem, ensuring they can communicate effectively and function seamlessly together.
/** * @coponentId: learnbit.blog-pbc/blog * @filename: blog-data.ts */ import { ApolloClient, InMemoryCache, HttpLink, gql } from '@apollo/client'; import type { BlogConfig } from './blog-config.js'; export class BlogData { constructor(private readonly config: BlogConfig) {} private contentfulClient = new ApolloClient({ link: new HttpLink({ uri: `https://graphql.contentful.com/content/v1/spaces/${this.config.spaceId}`, headers: { Authorization: `Bearer ${process.env.CONTENTFUL_ACCESS_TOKEN}`, }, fetch, }), cache: new InMemoryCache(), }); getBlogPosts = async () => { const { data } = await this.contentfulClient.query({ query: gql` query GetBlogs { pageBlogPostCollection { items { title slug author { name } } } } `, }); return data.pageBlogPostCollection.items.map((item) => ({ title: item.title, slug: item.slug, author: { name: item.author ? item.author.name : null, }, })); }; }
Next steps
Explore the "Blog" scope (with the blog aspect)
Visit these Bit scopes to explore demo aspects and fork (copy) them to your Bit workspace to get started quickly.
Visit the Blog scope
Explore the "Apparel Waves" scope (with a Harmony platform)
Visit the Apparel Waves scope
Visit Bit's official documentation

Bit. Composable software.
Bit is build system for development of composable software.
The above is the detailed content of Building Composable Platforms with Harmony. For more information, please follow other related articles on the PHP Chinese website!

Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

Video Face Swap
Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Hot Tools

Notepad++7.3.1
Easy-to-use and free code editor

SublimeText3 Chinese version
Chinese version, very easy to use

Zend Studio 13.0.1
Powerful PHP integrated development environment

Dreamweaver CS6
Visual web development tools

SublimeText3 Mac version
God-level code editing software (SublimeText3)

Hot Topics

Frequently Asked Questions and Solutions for Front-end Thermal Paper Ticket Printing In Front-end Development, Ticket Printing is a common requirement. However, many developers are implementing...

JavaScript is the cornerstone of modern web development, and its main functions include event-driven programming, dynamic content generation and asynchronous programming. 1) Event-driven programming allows web pages to change dynamically according to user operations. 2) Dynamic content generation allows page content to be adjusted according to conditions. 3) Asynchronous programming ensures that the user interface is not blocked. JavaScript is widely used in web interaction, single-page application and server-side development, greatly improving the flexibility of user experience and cross-platform development.

There is no absolute salary for Python and JavaScript developers, depending on skills and industry needs. 1. Python may be paid more in data science and machine learning. 2. JavaScript has great demand in front-end and full-stack development, and its salary is also considerable. 3. Influencing factors include experience, geographical location, company size and specific skills.

Learning JavaScript is not difficult, but it is challenging. 1) Understand basic concepts such as variables, data types, functions, etc. 2) Master asynchronous programming and implement it through event loops. 3) Use DOM operations and Promise to handle asynchronous requests. 4) Avoid common mistakes and use debugging techniques. 5) Optimize performance and follow best practices.

The latest trends in JavaScript include the rise of TypeScript, the popularity of modern frameworks and libraries, and the application of WebAssembly. Future prospects cover more powerful type systems, the development of server-side JavaScript, the expansion of artificial intelligence and machine learning, and the potential of IoT and edge computing.

How to merge array elements with the same ID into one object in JavaScript? When processing data, we often encounter the need to have the same ID...

Discussion on the realization of parallax scrolling and element animation effects in this article will explore how to achieve similar to Shiseido official website (https://www.shiseido.co.jp/sb/wonderland/)...

In-depth discussion of the root causes of the difference in console.log output. This article will analyze the differences in the output results of console.log function in a piece of code and explain the reasons behind it. �...
