gRPC Playground gives engineers a simple way to explore and call gRPC services from the browser. It is a GUI client that lives inside Backstage. Point it at your protobuf files, see the service methods, craft requests, then send them. You can try unary calls, stream requests, or stream responses. You can view docs generated from your protos too. The backend handles requests and supports TLS, so you can test real services in a safe way.
The Backstage plugin adds this workflow to your service catalog. Teams keep proto files next to the code that owns them. The plugin reads those definitions and turns them into an interactive client and a readable reference. Use it to verify a new API before building a client. Use it during development to debug message shapes. Use it to share a repeatable request with a teammate or with another team.
If you run a self hosted Backstage and you ship gRPC, this plugin helps you test calls faster, keep docs close, and reduce tool switching.
Installation Instructions
These instructions apply to self-hosted Backstage only.
Install the frontend package
Run this from your Backstage project root
yarn --cwd packages/app add backstage-grpc-playground
Add the gRPC widget to ApiDocs
This replaces the default ApiDocs widget for entities with type grpc
// packages/app/src/apis.ts
import { AnyApiFactory, createApiFactory } from '@backstage/core-plugin-api';
import { apiDocsConfigRef, defaultDefinitionWidgets } from '@backstage/plugin-api-docs';
import { ApiEntity } from '@backstage/catalog-model';
import { GrpcPlaygroundComponent } from 'backstage-grpc-playground';
// keep your other imports
export const apis: AnyApiFactory[] = [
// keep your existing api factories
createApiFactory({
api: apiDocsConfigRef,
deps: {},
factory: () => {
const definitionWidgets = defaultDefinitionWidgets();
return {
getApiDefinitionWidget: (apiEntity: ApiEntity) => {
if (apiEntity.spec.type === 'grpc') {
return {
type: 'grpc',
title: 'gRPC Playground',
component: GrpcPlaygroundComponent,
};
}
return definitionWidgets.find(d => d.type === apiEntity.spec.type);
},
};
},
}),
];
Add a standalone page
This gives you a page at path /grpc-playground
// packages/app/src/App.tsx
import React from 'react';
import { FlatRoutes } from '@backstage/core-app-api';
import { Route } from 'react-router-dom';
import { GrpcPlaygroundPage } from 'backstage-grpc-playground';
// keep your other imports
export default function App() {
return (
<FlatRoutes>
{/* keep your existing routes */}
<Route path="/grpc-playground" element={<GrpcPlaygroundPage />} />
</FlatRoutes>
);
}
Install the backend package for the legacy backend system
The backend plugin handles proto files and request execution
yarn --cwd packages/backend add backstage-grpc-playground-backend
Create a backend plugin module that exposes the router
// packages/backend/src/plugins/grpcPlayground.ts
import { Router } from 'express';
import { Logger } from 'winston';
import { PluginEnvironment } from '../types';
import { createRouter } from 'backstage-grpc-playground-backend';
// add imports your backend already uses such as Config if needed
export default async function createPlugin(
env: PluginEnvironment,
): Promise<Router> {
// Many Backstage backend routers only need logger and config
// Add other env fields if your TypeScript compiler requests them
return await createRouter({
logger: env.logger as Logger,
config: env.config,
});
}
Wire it into the backend HTTP router
// packages/backend/src/index.ts
import grpcPlayground from './plugins/grpcPlayground';
// keep your existing imports and bootstrap code
async function main() {
// keep your existing env creation
const grpcEnv = useHotMemoize(module, () => createEnv('grpc-playground'));
// keep your existing apiRouter
apiRouter.use(
'/grpc-playground',
await grpcPlayground(grpcEnv),
);
// keep your existing server start
}
Your backend routes will be served under /api/grpc-playground
if you mount apiRouter under /api
in your app server
Install the backend package for the new backend system
At the time of writing the backend package targets the legacy backend system. If your app uses the new backend system you can still mount the Express router. Create a small module that calls createRouter from the backend package and mounts it on the http router at /grpc-playground
. Use the same logger and config services you already pass to other routers in your new backend. Keep the mount path consistent with the legacy example
Provide proto files to the backend
The backend plugin looks for proto files on the backend side. The default location is the proto folder in packages/backend
. Add your proto files here
packages
backend
proto
your files go here
You can also keep common google proto files under a subfolder if your protos import them
Define a gRPC API entity
Add an API entity with type grpc. Put the YAML below in a catalog file that your Backstage catalog loads
This example shows the structure supported by the plugin. Replace the file names and URLs with your own. You can also use file paths relative to your repo if you serve them from source
apiVersion: backstage.io/v1alpha1
kind: API
metadata:
name: my-grpc-service
description: Example gRPC API
spec:
type: grpc
lifecycle: experimental
owner: team-a
definition: |
files:
- file_name: hello.proto
url: https://raw.githubusercontent.com/org/repo/main/protos/hello.proto
imports:
- file_name: common.proto
url: https://raw.githubusercontent.com/org/repo/main/protos/common.proto
imports:
- file_name: timestamp.proto
url: https://raw.githubusercontent.com/protocolbuffers/protobuf/main/src/google/protobuf/timestamp.proto
libraries:
- name: google-apis
path: packages/backend/proto/google
Notes
- files is a list of proto files used by this API
- Each file can list its own imports if it depends on other protos
- imports at the root are common imports shared across files
- libraries lets you point to a local folder with pre collected proto definitions such as google APIs
Use the plugin in Backstage
- Open an API entity with type grpc in the ApiDocs page. The page shows the gRPC Playground widget
- Or go to
/grpc-playground
to use the standalone page
You can upload missing imports from the UI if the plugin asks for them. TLS for requests is supported from the UI
Tips when calls fail due to missing imports
- If a proto imports another local file upload the folder that contains both files
- If a proto imports google APIs add a google folder with the needed protos under packages
/backend/proto
then reference it using the libraries field as shown above
Changelog
The GRPC Playground plugin has not seen any significant changes since a year ago.
Set up Backstage in minutes with Roadie
Focus on using Backstage, rather than building and maintaining it.