Quickstart • Website • Docs • Examples • Blog
WunderGraph is a Backend for Frontend (BFF) Framework designed to optimize Developer Workflows through API Composition.
At its core, WunderGraph combines two patterns, API Gateway and BFF with the concept of a package manager, making API composition as simple as npm install. Our mantra is: Compose, don't integrate.
API Composition is a new pattern that allows you to interact with a heterogeneous set of APIs as if they were a single unified API. This not just eliminates a lot of glue code, but also allows you to reason about the API Dependencies of an application. Do you actually know what APIs and Services your application depends on? WunderGraph can easily answer this question for you, and even gives you analytics and observability into what APIs and Endpoints are used by your application and what the quality of service your API dependencies provide.
Here's how WunderGraph works:
- Compose your APIs
// .wundergraph/wundergraph.config.ts
import { NextJsTemplate } from '@wundergraph/nextjs/dist/template';
// introspect a PostgreSQL database
const pg = introspect.postgresql({
apiNamespace: 'pg',
databaseURL: new EnvironmentVariable('PG_DATABASE_URL'),
});
// introspect the Stripe API using OpenAPI
const stripe = introspect.openApiV2({
apiNamespace: 'stripe',
source: {
kind: 'file',
filePath: './stripe.yaml',
},
headers: (builder) => builder.addClientRequestHeader('Authorization', `Bearer ${process.env.STRIPE_SECRET_KEY}`),
});
// introspect the Shopify Storefront API using GraphQL
const shopify = introspect.graphql({
apiNamespace: 'shopify',
url: 'https://my-shop.myshopify.com/api/2021-07/graphql.json',
headers: (builder) =>
builder.addStaticHeader('X-Shopify-Storefront-Access-Token', new EnvironmentVariable('SHOPIFY_STOREFRONT_TOKEN')),
});
configureWunderGraphApplication({
// compose the APIs into a unified WunderGraph API
apis: [pg, stripe, shopify],
// generate type-safe clients for your Frontend
codeGenerators: [
{
templates: [...templates.typescript.all],
},
{
templates: [new NextJsTemplate()],
path: '../web/components/generated',
},
],
});
WunderGraph allows you to create a code pipeline to introspect and compose multiple APIs into a unified API. This makes it easy to update an API dependency without a single click.
- Define an Operation
By combining the introspected APIs, WunderGraph generates a unified GraphQL Schema across all APIs. All we have to do is define an Operation and call it from our Frontend.
GraphQL
# .wundergraph/operations/users/ByID.graphql
query ($id: String!) {
user: pg_findFirstUser(where: { id: { equals: $id } }) {
id
email
name
bio
}
}
TypeScript
// .wundergraph/operations/users/CustomByID.ts
import { createOperation, z } from '../../generated/wundergraph.factory';
export default createOperation.query({
// Input validation
input: z.object({
id: z.string(),
}),
handler: async ({ input }) => {
// Call into your virtual graph, type-safe
const { errors, data } = await operations.query({
operationName: 'users/ByID',
input: {
id: input.id,
},
});
return {
...data,
};
},
});
- Call the Operation from your Frontend
As you define Operations, WunderGraph automatically generates a type-safe client for your Frontend, supporting all major Frontend Frameworks like React, NextJS, Remix, Astro, Svelte, Expo, Vue, etc...
// web/pages/profile.ts
import { useQuery } from '../../components/generated/nextjs';
export default async function ProfilePage(props) {
const { data } = await useQuery({
operationName: 'users/CustomByID', // or 'users/ByID'
input: {
id: props.params.id,
},
});
return (
<div>
<h1>{data.user.id}</h1>
<p>{data.user.name}</p>
</div>
);
}
In the same vein, you could now add Authentication, Authorization, file uploads, etc...
The easiest way to get started from scratch is to use the following command:
npx create-wundergraph-app my-project --example nextjs
If you already have an existing project, you can add WunderGraph to it by running:
npx create-wundergraph-app --init
Want to chat about WunderGraph with the team and other enthusiastic developers like yourself? We're very active on our Discord server, Discourse and on our GitHub, where issues and PRs are very welcome (but please read our contribution readme first).
Now, the only thing our community is missing is you!
Questions? 🙋
- We're happy to help you with queries on our Discord server & Discourse.
Bugs? 🪳
- Tell us about them on Discord, create a GitHub issue, or even open a GitHub Pull Request.
Need more help or interested in enterprise support? 🤔
- Let's chat, and we'll get you exactly what you need.