-
Notifications
You must be signed in to change notification settings - Fork 1.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Home Page Plugin API #2562
Home Page Plugin API #2562
Conversation
My thoughts on plugin deployment. Copied from Discord: I'm gonna try to come up with a game plan for deploying these plugins.
So plugins can define scripts and stylesheets to load on a per hook basis.
The plugins table would have the following fields:
It'll get the manifest url using the name of the plugin and the commonly known plugin-manifest.json file. |
next step is to figure out the deployment process. @robertlong please link the relevant issue. |
We'll revisit this in the future with a new effort. |
This PR marks the start of the Hubs Client SDK. Building out a SDK for Hubs is a huge task, so we're starting small and focusing on the ability to customize the home page.
The primary goal of the Hubs Client SDK is to enable customizing the client while still being able to receive automatic updates to your Hubs Cloud server. In order to accomplish this, we are looking into a plugin API. Plugins can be loaded at runtime and do not require rebuilding the client. A webpack compile can take a while and can be extremely resource intensive so we don't want to build on upgrade because that could result in unnecessary downtime. We could add a CI service for rebuilding the client, but we felt that that would be overly complex for what we are trying to accomplish. So instead of rebuilding the client, plugins are built at deploy time and are written against a versioned API.
When experimenting with this idea we quickly came across Project Gutenberg, the new Wordpress editor written in React. Gutenberg has a plugin API with very similar requirements and an elegant solution. Gutenberg uses a series of npm packages that plugins can require and these dependencies are dynamically loaded at runtime. This means that plugins can pull in just the code they need and these dependencies can be shared across plugins. The core of this solution is the @wordpress/dependency-extraction-webpack-plugin package. This package collects all of the dependencies of a specific package or plugin that start with
@wordpress/
or are common libraries (react, react-dom, etc.). At package/plugin build time it marks these packages as externals before bundling. Externals are exposed and imported as global variables. Soimport React from "react";
actually ends up importing fromwindow.React
.For the Hubs Client SDK this solution would work quite well. We have dependencies that should only be loaded when they are needed. If you want to override the home page completely, why should you require all the original home page code? And most importantly, these plugins can be installed with zero downtime and can be upgraded automatically.
Here's what has been done so far:
There are three packages that have been created
@hubs/core
,@hubs/react
, and@hubs/home-page
. Right now these are not actually separate packages, they are just aliases in the webpack config. However, you can start to see how they could be broken up into separate packages.@hubs/core
The core package contains the
Hubs
singleton. This is an object that contains thestore
(our interface into localStorage where we store the session and user configuration),config
(what features are enabled and other configuration options for your Hubs Cloud server), and the Reticulum API.There are methods for authentication:
Hubs.signin(email: string): Promise<void>
Hubs.verify(params: { topic: string, token: string, payload: string }): Promise<void>
Hubs.signOut(): Promise<void>
Hubs.store.isAuthenticated(): boolean
Hubs.store.isAdmin(): boolean
Hubs.store.getEmail(): string
Hubs.store.getAccountId(): string
Hubs.store.getAuthToken(): string
And for fetching/creating rooms:
Hubs.createRoom(params?: {}): Promise<RoomResponse>
Hubs.getPublicRooms(cursor: number): Promise<RoomsResponse>
Hubs.getFavoriteRooms(cursor: number): Promise<RoomsResponse>
For fetching configuration variables:
Hubs.config.feature(key: string): any
Hubs.config.image(key: string, cssUrl?: boolean): string
Hubs.config.link(key: string, defaultValue?: string): string
And finally for registering plugins themselves:
Hubs.registerPlugin(hook: string, exports: {})
@hubs/react
The React package is mostly a React utility wrapper around the @hubs/core API. There are hooks and higher order components for working with these APIs in a react context and a few core components for inheriting the base styling for the navigation and page.
useStore(): { store: Store }
lets your UI react to changes in the Hubs store. For example when logging in you may want to rerender the email. Note that store itself doesn't change, but the wrapping object will when the store updates so you can use it as a dependency to another hook.usePublicRooms(): { isLoading: boolean, hasMore: boolean, results: Room[], error?: Error, cursor: number, nextCursor?: number, loadMore: () => void }
Loads all of the public rooms.useFavoriteRooms(): { isLoading: boolean, hasMore: boolean, results: Room[], error?: Error, cursor: number, nextCursor?: number, loadMore: () => void }
Loads all of the user's favorite rooms if they are signed in.useInstallPWA(): { supported: boolean, installed: boolean, installPWA: () => void }
Install the Hubs PWAuseCreateAndRedirectToRoom(): { creatingRoom: boolean, error?: Error, createRoom: (roomParams: {}) => void
@hubs/home-page
The home page package holds all of the custom react components needed to create the default home page. If you want to completely restyle the homepage you probably would avoid importing this to reduce the page size. However, if you want to use some of the component's we've already created for the default Hubs homepage, you can import them from this package.
<HomePage />
The default HomePage component. If you wanted to wrap the HomePage component in a higher order component you could do that. For now you can't pass any additional props to HomePage.<CreateRoomButton />
A styled button that creates a new room using thecreateAndRedirectToRoom
hook from the React package.<PWAButton />
A styled button for installing the Hubs Progressive Web App (PWA). Doesn't render if it's already installed or if the browser doesn't support PWAs.<RoomTile room={room} />
Renders a tile for the provided room with the room name, thumbnail, last visited, favorite status, and current occupancy. Clicking on the tile navigates to that room.<MediaGrid>{children}</MediaGrid>
A responsive CSS grid wrapper component for RoomTiles.styles
A CSS Module for the home page. Includes styles specific to just the home page.discordLogoUrl
The url for the small Discord logo icon that we use on the homepage.Next Steps
This small API should suffice for a wide variety of home page customizations, but there's still likely more that developers want to do on their home page. We want to ship an early version of this API to developers and get feedback from all of you, but first there is some remaining work to be done.
@hubs/core
,@hubs/react
and@hubs/home-page
packages should be loaded at runtime to minimize code when these dependencies aren't needed. We also need to make sure the latency introduced by this system is acceptable.