GraphiQL is a browser IDE for GraphQL. It lets you explore a schema. You can write queries with autocomplete. You can add variables. You can see results fast. It is a simple way to learn an API and to debug it.
The GraphiQL Backstage plugin brings that experience into your portal. You get a page in Backstage where engineers can switch between approved endpoints. Queries run with the same auth that your portal already uses. You can supply custom headers. You can plug in your own fetchers. The plugin can host GraphiQL plugins too, so teams can extend the editor with tools they rely on.
This is handy for day to day work. You can inspect internal schemas without leaving your portal. You can prove changes before wiring a client. You can share a query with a teammate next to the docs of the service. You can keep a stable way for support and SRE to reproduce issues against a live graph. The plugin also includes a helper for the GitHub GraphQL API, which makes it easy to test against that graph if your org uses it.
If you already run Backstage, this plugin gives you a safe home for GraphQL exploration inside the same place your teams use for docs and APIs.
Installation steps
These instructions apply to self-hosted Backsgage only. To use this plugin on Roadie, visit the docs.
Install the frontend package
yarn --cwd packages/app add @backstage-community/plugin-graphiql
Add the GraphiQL page to your app
Add the route so the page renders.
// packages/app/src/App.tsx
import React from 'react';
import { FlatRoutes, Route } from '@backstage/core-app-api';
import { GraphiQLPage } from '@backstage-community/plugin-graphiql';
export const routes = (
<FlatRoutes>
<Route path="/graphiql" element={<GraphiQLPage />} />
</FlatRoutes>
);
Provide GraphQL endpoints to the plugin
The plugin reads endpoints from the GraphQLBrowse API. Implement it in your app APIs.
This example shows two endpoints. One static GitLab endpoint. One custom internal endpoint that uses fetch.
// packages/app/src/apis.ts
import {
createApiFactory,
errorApiRef,
githubAuthApiRef,
} from '@backstage/core-plugin-api';
import {
graphQlBrowseApiRef,
GraphQLEndpoints,
} from '@backstage-community/plugin-graphiql';
// add this factory to your exported apis array
export const apis = [
createApiFactory({
api: graphQlBrowseApiRef,
deps: { errorApi: errorApiRef, githubAuthApi: githubAuthApiRef },
factory: ({ errorApi, githubAuthApi }) =>
GraphQLEndpoints.from([
// static endpoint with optional extra headers
GraphQLEndpoints.create({
id: 'gitlab',
title: 'GitLab',
url: 'https://gitlab.com/api/graphql',
headers: { Extra: 'Header' },
}),
// custom endpoint using your own fetcher
{
id: 'hooli-search',
title: 'Hooli Search',
fetcher: async (params: any) => {
return fetch('https://internal.hooli.com/search', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(params),
}).then(res => res.json());
},
plugins: [],
},
]),
}),
];
You can also add a GitHub endpoint that uses the GitHub auth API.
// packages/app/src/apis.ts
import {
createApiFactory,
errorApiRef,
githubAuthApiRef,
} from '@backstage/core-plugin-api';
import {
graphQlBrowseApiRef,
GraphQLEndpoints,
} from '@backstage-community/plugin-graphiql';
export const apis = [
createApiFactory({
api: graphQlBrowseApiRef,
deps: { errorApi: errorApiRef, githubAuthApi: githubAuthApiRef },
factory: ({ errorApi, githubAuthApi }) =>
GraphQLEndpoints.from([
GraphQLEndpoints.github({
id: 'github',
title: 'GitHub',
githubAuthApi,
errorApi,
}),
]),
}),
];
Add a sidebar link
Add a nav item so users can open the page.
// packages/app/src/components/Root/Root.tsx
import React from 'react';
import { Sidebar, SidebarItem } from '@backstage/core-components';
import { GraphiQLIcon } from '@backstage-community/plugin-graphiql';
export const Root = ({ children }: { children?: React.ReactNode }) => (
<>
<Sidebar>
<SidebarItem icon={GraphiQLIcon} to="/graphiql" text="GraphiQL" />
</Sidebar>
{children}
</>
);
Notes on CORS and headers
The browser must be allowed to call your endpoint. If the endpoint does not allow cross origin requests, use a proxy or serve a backend that forwards requests. Add any auth headers in your endpoint setup as shown above.
Using the new frontend system
You can expose the page and a nav item with the alpha exports. Keep the same apis.ts setup shown earlier.
Export the page and nav item from your extensions file.
// packages/app/src/extensions.ts
export { graphiqlPage, graphiqlNavItem } from '@backstage-community/plugin-graphiql/alpha';
Add path config for the page in your app config if your app expects it.
# app-config.yaml
app:
extensions:
- id: page:graphiql
config:
path: /graphiql
Keep your sidebar link pointing to the same path.
Things to know
Adding multiple GraphQL APIs
Multiple APIs can be connected to the GraphiQL page. Each GraphQLEndpoint
added to the API factory in apis.ts
is rendered as a seperate tab. For example, let’s add a second API:
createApiFactory({
api: graphQlBrowseApiRef,
deps: { },
factory: () =>
GraphQLEndpoints.from([
GraphQLEndpoints.create({
id: 'gitlab',
title: 'GitLab',
url: 'https://gitlab.com/api/graphql',
headers: { 'Some-Key': 'Some-Value' }
}),
// add a second API endpoint...
{
id: 'spacex',
title: 'SpaceX',
fetcher: async (params: any) => {
return fetch('https://api.spacex.land/graphql/', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(params)
}).then(res => res.json());
}
}
])
})
Rather than using the GraphQLEndpoints.create
function to create the GraphQLEndpoint
, we creating an an object with a custom fetcher
fucntion. This approach allows for more control over constructing the HTTP request to the API. This may be necessary in special cases where the GraphQL endpoint as unique requirements.
The end result is the same though, a new tab for the ‘SpaceX’ API:
Connecting to an authenticated API with GitHub authentication
A special github
function is available on the GraphQLEndpoints
class. This function allows you to connect to a GitHub-authenticated GraphQL endpoint using the built-in GitHub auth provider. This assumes that you are using the GitHub auth provider in your Backstage implementation.
Adding a GitHub-authenticated API is quite simple. For example, this is how you would setup a connection to the official GitHub GraphQL API:
import {
AnyApiFactory,
createApiFactory,
errorApiRef,
githubAuthApiRef
} from '@backstage/core';
import {
graphQlBrowseApiRef,
GraphQLEndpoints
} from '@backstage/plugin-graphiql'
export const apis: AnyApiFactory[] = [
createApiFactory({
api: graphQlBrowseApiRef,
deps: { errorApi: errorApiRef, githubAuthApi: githubAuthApiRef },
factory: ({ errorApi, githubAuthApi }) =>
GraphQLEndpoints.github({
id: 'github',
title: 'GitHub',
url: 'https://api.github.com/graphql',
errorApi: errorApi,
githubAuthApi: githubAuthApi
})
])
})
];
The current user logged into Backstage can now access information that is only available to authenticated GitHub users. For example, the user could query for their private repositories:
The github
function even attempts to request additional API scopes if the current user’s authentication token doesn’t have the scopes required to execute the GraphQL query or mutation.
Set up Backstage in minutes with Roadie
Focus on using Backstage, rather than building and maintaining it.