
Architecting Jamstack Applications with GraphQL - Jamstack Boston
Anthony shows how to use StepZen to stitch together a Shopify backend with a Redwood application, enabling easy querying of products from the frontend
Episode Description
Anthony Campolo demonstrates building a full-stack app with RedwoodJS and StepZen, connecting a Shopify backend through a unified GraphQL API gateway.
Episode Summary
Anthony Campolo walks through the fundamentals of GraphQL starting from the graphql.org homepage, then moves into a live coding demonstration showing how RedwoodJS and StepZen work together to build a full-stack application. He explains RedwoodJS's architecture — a React frontend paired with a serverless GraphQL API backend — and shows how StepZen acts as a middleware layer that stitches together external backends like Shopify into a single GraphQL endpoint. The demo covers generating pages with Redwood's CLI, setting up a product schema, managing API keys securely on the server side, and querying Shopify product data through the StepZen-to-Redwood pipeline. Along the way, he introduces Redwood's "cell" pattern for declarative data fetching with built-in loading, empty, failure, and success states. A Q&A session explores key management in serverless environments, AWS Lambda basics, the challenges of adapting Redwood to other providers like Cloudflare and Azure, the tension between serverless and serverful deployment, and how StepZen connects to custom APIs. The talk offers a practical look at modern Jamstack architecture and the tradeoffs developers face when choosing deployment strategies.
Chapters
00:00:00 - GraphQL Basics and the RedwoodJS Architecture
Anthony opens by breaking down what GraphQL is at its core using the graphql.org homepage, walking through a minimal schema with project and user types and a simple query that returns a tagline. He emphasizes that despite the sprawling ecosystem of tools and companies around GraphQL, the specification itself is straightforward — a query language for APIs. From there he transitions into RedwoodJS, the framework that served as his entry point into both GraphQL and open source.
He explains Redwood's architecture: a React frontend served on a CDN, a GraphQL serverless function handler on the backend, and Prisma as the ORM layer. He compares this structure to Next.js API routes but notes that Redwood provides significantly more backend scaffolding out of the box. He also introduces StepZen as the API gateway that will sit between Redwood's frontend and backend, stitching together external services like Shopify into a unified GraphQL endpoint, and briefly mentions his habit of comparing similar frameworks like Blitz, Bison, and WASP on his podcast.
00:05:09 - Setting Up the Redwood Project and StepZen Backend
Anthony begins the hands-on portion by spinning up a new Redwood project, generating a home page and an about page using Redwood's CLI commands, and showing how routes are automatically configured. He then shifts to the StepZen side, explaining the index.graphql file that stitches together backend schemas and creating a simple product schema with ID, handle, and title fields — directly paralleling the GraphQL basics from the opening segment.
He demonstrates how StepZen's @rest directive connects to a Shopify backend by mapping an endpoint that includes API credentials stored in a config YAML file. This leads into a discussion about the persistent challenge of managing environment variables and API keys across projects, and how StepZen centralizes these into a single manageable endpoint. After running the StepZen start command, he shows the resulting GraphQL explorer where product data from Shopify can be queried directly.
00:11:47 - Building the Redwood API and Querying Products
Anthony turns to wiring up the Redwood API backend, explaining the GraphQL handler that exports and stitches together the server-side schema. He creates a product schema on the Redwood side mirroring the StepZen schema, then builds a service that makes a GraphQL request from the backend to the StepZen endpoint using the graphql-request library. He highlights why this backend-to-backend call matters: API keys must stay on the server to avoid exposing them in client-side source maps.
After troubleshooting a small naming issue with the client import, he successfully queries the Redwood backend and retrieves Shopify product data. He then introduces Redwood's cell pattern, which provides declarative data fetching states — loading, empty, failure, and success — and shows the products rendering on the frontend. The network tab in developer tools confirms the GraphQL request flowing from the React frontend through Redwood's API to StepZen and back.
00:16:42 - Q&A: Key Management, Serverless, and Lambda
An audience member asks how API keys are managed across the stack. Anthony explains the layered approach: Shopify keys live inside the StepZen configuration, while StepZen API keys are stored in environment variables locally and injected through platform dashboards on Netlify or Vercel during deployment. This leads to a broader discussion about Redwood's serverless architecture, where Anthony explains that the entire backend deploys as a serverless function on AWS Lambda.
He provides a beginner-friendly explanation of AWS Lambda as Functions-as-a-Service, describing how it lets developers run backend code without maintaining always-on servers, paying only per invocation. The questioner confirms that Redwood's Lambda functions are Node-based, and Anthony affirms this, noting the tight integration with Node libraries like Prisma. This segment grounds the earlier demo in practical deployment concepts that help newcomers understand where the code actually runs.
00:22:59 - Q&A: Adapters, Cloudflare, Deployment Strategies, and Wrap-Up
The final segment covers deeper architectural questions. Asked about adapters for providers like Cloudflare and Azure, Anthony explains that Lambda and Azure functions differ significantly in their context and event objects, creating an impedance mismatch that Redwood hasn't yet resolved. He notes that Cloudflare presents an even bigger challenge because it runs on V8 directly rather than Node, meaning many Node libraries simply don't work there.
He discusses the "Lambda lift" anti-pattern of deploying everything as one large function, the cold start issues it causes, and Redwood's future plans to break the backend into smaller functions. He also mentions that many production users run Redwood as a traditional server using Render and PM2, blurring the serverless-serverful line. The session closes with a question about StepZen's ability to connect custom REST, GraphQL, or database endpoints, which Anthony confirms, and he wraps up by thanking the host and promoting related resources like his FSJam podcast.
Transcript
00:00:01 - Anthony Campolo
This is the graphql.org homepage. And this is a great place to start people off when it comes to GraphQL because a lot of people have heard of GraphQL. It's a big thing, it's a big talking point. There's lots of companies, there's lots of open source projects, there's a lot of stuff happening around GraphQL. It'd be hard to wrap your mind around all of it and get a handle on what it is. I think it's good to break it down to the thing itself, which is just a very simple specification for querying APIs. It's a query language for your API, as it says here on the GraphQL homepage.
This is the simplest kind of hello world GraphQL example you could imagine, where we're first creating a schema. Right here. This is a project type schema. And that project has a name, and the name is a string, so it's some text. And then the project also has a tagline, which is also a string. And then the project has a list of contributors, and that list of contributors are each individual user objects. And that's what this right here is — it's like an array of user objects.
00:01:16 - Anthony Campolo
So we're not seeing the whole schema right here. We need also a user object. But the simple kind of query that we could do right now is we could ask for a specific project. So we're asking for the name of that project, which is GraphQL, and we're asking for the tagline. The tagline is "a query language for APIs." So this is kind of the simplest GraphQL query you could possibly do. That's the query and that's the result.
Now, once you go beyond kind of the very basics of GraphQL, you get all this stuff around: how do you connect a front end to a back end with GraphQL? And what's nice is that you can get into that without having to necessarily figure out how to do it yourself, with certain frameworks and projects that have done it for you. So this is RedwoodJS, which is how I really got my entrance into this whole open source world and GraphQL especially. I was learning Redwood before I really knew what GraphQL was.
00:02:28 - Anthony Campolo
I had kind of a vague idea of it because I had been listening to podcasts about GraphQL. I've listened to many, many podcasts and have now hosted and guested on many, many podcasts. But what's really cool about Redwood is that it does this whole data integration front to back for you — a React front end, then a GraphQL middle layer, with Prisma as an ORM talking to your database. And there's this kind of high-level architectural diagram explaining how it all works.
This could be a little overwhelming the first time you look at it, but the really important stuff is here on the left, because this is your actual Redwood project structure and you have a front end and a back end. If you've ever used something like Next.js API routes — a serverless functions kind of thing — that's fairly similar to what's going on here, except it's giving you a lot more of that API backend already built out for you with an entire GraphQL serverless function handler, which we'll get into once we actually start building out the project. But the front end is very familiar to anyone who's ever worked with a React front end, whether that's Create React App or Gatsby or Next — anything that's a folder that has things like pages and components and layouts, and you have your styling CSS.
00:03:53 - Anthony Campolo
All that is in your front end and that's being served on a static CDN host like Netlify or Vercel. And then your back end is this whole API serverless GraphQL function handler. This is where StepZen is going to come in. We're going to essentially insert a StepZen API gateway in between these two pieces. That's where StepZen comes in, which is a GraphQL API that stitches together all of your backends. This will be very similar to the TakeShape [mesh setup?] that we were looking at, which is cool because I'm someone who actually really enjoys seeing similar projects and comparing them to each other.
On my podcast, one of the main things we do is compare Redwood to Blitz and to Bison, and now there are things like WASP and there are all these other frameworks that are all kind of spinning around the same ideas and the same technology. And it's really useful to actually compare them to each other and wrap your mind around how they work, because you can start to ask more pointed questions about what each of them offer and what they don't, what they hook into and what they don't, what's the interface into them and all this kind of stuff.
00:05:09 - Anthony Campolo
We're going to be using a Shopify back end. And all this is going to be contained in this repo here. The StepZen-Redwood repo — we have these StepZen samples here, which is a lot of just example projects that we're building out to show how you work with this stuff and how you can stitch it all together in different ways with different frameworks. There's a large variety of tools and ways of doing this. I think it's really useful to be able to compare them to each other.
But right now we are going to kick open a Redwood project. So yarn rw dev is going to start our Redwood development server. And right now we have nothing. This is just a blank Redwood homepage. And if we wanted to start building out this project, we do yarn rw generate page home and this is going to create a home page for us and set it to our home route. And so this will then set our home page to this. So we look at our code over here. As I was talking about, we have this web side and then we have this API side.
00:06:29 - Anthony Campolo
So right now let's just mess around in the web side for a little bit because this is the part that is, I think, fairly intuitive to anyone who's ever worked with a React front end. So we have components, pages, and this App.js. This is our root component. The root component will have all the other child components within it. And we have the Redwood Apollo provider, and you can actually swap this out for a React Query provider. That's one of the things that we're getting deeper and deeper into — decoupling out the different pieces of Redwood to make them swappable. And the server is going to do that fairly soon.
But this is the real meat of your project: your routes. So right now we have this route that we created, which is our home page. So we could create another one. If we wanted to create an about page, we can do yarn rw generate — all your commands start with that. You can also type out yarn redwood generate. Now we're going to generate a page, and we're going to generate an about page, but we're not going to set a path because we want the path to be /about.
00:07:49 - Anthony Campolo
We want the path to be about, we want the page to be the about page. And so that's going to create another page right here. And then if we go to /about, we'll see our about page, and we can see all the places where about appears. That's pretty cool.
Now we're going to look at the back end and we're going to build out our StepZen backend. With StepZen, you're going to have an index.graphql, and this is what essentially stitches together all of your backend schemas. So if you wanted to have, say, a user schema and a product schema and an orders schema, you can have all those and stitch them all together into this one unified backend. Now, just for simplicity sake, we're only going to have one, but that's why you have this file here, to stitch all of your schemas together.
We're just going to have this one product schema and it's very simple — it's a product type. So this is what we were looking at on our GraphQL homepage. We had a project type, right? This is very, very similar. We have a product type and it's going to have an ID, handle, and title, just like how that one had a name, tagline, and contributors.
00:09:13 - Anthony Campolo
And then we're going to have this query here. So this is where the StepZen magic comes in. Because what we're doing here is we're using this @rest directive. That's why my project is like, what is this? I don't know what this is. It says "unknown directive @rest." This is what we're doing to connect into our Shopify backend. We have this endpoint which is being fed the API key, the API password, and the store name, which is all contained in this config YAML, which I can't show. So it has my keys and you don't want to show your keys on the internet.
This is what I have in that config YAML file — you have a configuration set and you pass in your key. This is similar to what you saw in the previous presentation, where you had that graphical user interface that allowed you to put in your keys and stitch all that together. This is a very similar thing. And we're also building out GUIs to manage a lot of this as well. I like doing this in code, so that's why I'm showing it this way. But it's a similar idea, which is just: how do you manage all these environment variables and all these keys?
00:10:27 - Anthony Campolo
It's such a pain because it's a huge headache, especially if you have projects that have a lot of these. We're centralizing all these and putting them into this one endpoint that you can then run this simple StepZen start command to get going. I think this is going to be all good to go. Now this is going to kick open an endpoint for us over here. And this is another graphical kind of editor, which is really cool. On the left you can see that we can actually use this to create our queries. But let's say we don't have that — we could look at our docs and go to our queries. So we know that we have products and our products have handle, ID, and title, just like the kind of schema that we created before. If we run that query, we're going to get back these titles which are contained in our Shopify back end. This is from our previous Jamstack Toronto Talk — shout out to Henri. Now we have our StepZen backend set. We also have this endpoint here that we can query from our Redwood project.
00:11:47 - Anthony Campolo
To do that, we're going to start building out our Redwood API. In the Redwood API we have all of this stuff. This is that handler that I was talking about that stitches your whole backend together. We're exporting this handler. We're using createGraphQLHandler. This is coming from the Redwood API package. And this is stitching together your back end so that you can do anything you want with a serverless GraphQL handler. Which is really nice because it is what allows you to mask your keys, which we'll get into in a second.
Okay, so our Redwood API side is going to have a schema, just like our StepZen API had a schema, which is going to be: product has the same stuff that we had — the ID, handle, and title. And then we're going to create this query which will be the products. Save that. To do this, we're going to basically make a GraphQL call from the back end. And there's a lot of ways you can do this. You could do it with node-fetch or with graphql-request.
00:13:14 - Anthony Campolo
That's how I'm going. So it's just a common, simple client that allows you to make GraphQL requests. And this goes back to what you need to do with your keys. Because when you do this kind of stuff, you can't do it from the client, because if you do it from the client, you're sending your key that you get from StepZen, and that's a private key. You don't want to expose that to the world. So if you put that in your front end, your website is being shipped to the client, then you could see that in your source maps — open up your developer tools and you can go into the code and actually find that endpoint.
So this is what makes the whole Redwood architecture great — it's already set up to do this for you, already has an entire backend, allows you to make GraphQL calls, and lets you deploy it very simply to something like Netlify or Vercel. And so it's really sweet. We already have our keys set up, and then the last thing we have to do is just create our services. We're just going to have a single service which is going to make a query into our backend asking for the products, much like we did with the regular StepZen editor.
00:14:35 - Anthony Campolo
So now that we have that, let's go to our products. And if we go to localhost:8911, we see our back end and we have this GraphQL editor here and we can do the same thing — we can ask for our products. So we're going to do a query. This is the query we wanted. Bam. Let me restart the server here. Okay, I know what I missed. I forgot to rename. So I had one step here where we renamed db to client, and that is just because it's not really a database anymore — it's the GraphQL client that's calling it. So it should be good to go now. Okay, let me just stop sharing for one second because I'm going to check my keys to make sure those are all set up correctly. Are there any questions so far from what I've shown?
00:16:42 - Audience questioner
This might be a really newbie question. Obviously you're saying when you're connecting to something like StepZen, you don't want to expose your keys in the client. And you're storing this in like a serverless — how are the keys actually being managed? Where are they stored and how do they interact?
00:17:02 - Anthony Campolo
So there's the schema, there are the keys from StepZen itself. So you're hosting your Shopify keys in the StepZen API, and then you're hosting the API keys that access StepZen on something like Netlify or Vercel. Right now I'm just putting those in a .env file on my computer, which is how we're going to actually access it from here. Then when you host it on something like Netlify or Vercel, you're able to just plug them into the Dashboard.
00:17:50 - Audience questioner
Gotcha. And then they're only used on like the build process. Is that right? So when you build, the Dashboard exposes those keys and then it accesses the StepZen endpoint. Okay.
00:17:59 - Anthony Campolo
Yeah. Okay, are there any more questions? I'm going to do something real quick to kind of reset myself to get us back on track here.
00:18:21 - Audience questioner
I guess I'd like to ask a general Redwood question, but I don't want to detract you too much while you're using your [unclear].
00:18:27 - Anthony Campolo
Keep going.
00:18:28 - Audience questioner
Yeah.
00:18:28 - Anthony Campolo
Yes. No, please ask me questions. Yeah.
00:18:33 - Audience questioner
Okay, so you have the serverless — or actually, I think it's the functions folder, right? So does Redwood have some serverless backend stuff happening? And so instead of managing your own software stack and a whole monolith or something like that, it's doing some serverless function calling. Is that how Redwood works, or can you explain a little bit about that?
00:18:58 - Anthony Campolo
Yeah, that's where the API stitches together everything for you. Because it's deploying it onto Lambda via different services. There are different commands — you can deploy it from Netlify or Vercel, or you could deploy it directly to Lambda. What's your experience with AWS Lambda? Should I explain what that is?
00:19:27 - Audience questioner
Yeah, that'd be great.
00:19:29 - Anthony Campolo
AWS Lambda is what's called a Functions-as-a-Service type of thing. What it does is it allows you to run code that you would run on a server — like a Node server — but without having to have an always-on server to do that. This is really nice. It allows you to have a whole back end set up, like an API, without necessarily having to set that up and have it always running. So you're paying based on just your specific function invocations. That's really nice and convenient.
00:20:16 - Audience questioner
Then I assume with Redwood, the Lambdas are usually like Node functions. They're not written in some other language or something, right?
00:20:23 - Anthony Campolo
Yeah, exactly. So it's because we're using a lot of Node libraries. We're using things like Prisma, the Prisma client, and that's all baked in with the Node stuff. You need it to make it work. Okay, sweet. We are back in business. All right, let me hop back in here. Okay, so share my screen.
Okay, so now we have our whole back end set up and we want to do a query for our products: title, ID, and handle. And when we do that, we get our "hello Jamstack" over here. And then the only other thing that's going on is our homepage, which has our products cell. And the products cell is what's going to query our backend and then display it on our front end. So we have our StepZen API, and our StepZen API connects to our Redwood API — which we just did the query from — and then our Redwood web side, where we were creating the pages and whatnot, can do a GraphQL query. This is what's happening here: the same query we were doing on our back end.
00:21:57 - Anthony Campolo
And that query then has different states it can be in. So this is why we say a cell makes your data fetching declarative — you can basically tell it whether it's loading, empty, failure, or success. So if it's loading, we'll have a little loading message here. If it's empty, it'll say we need products. And if it's failure, it gives you the error message. Or we just want to render our products on the screen. So we're going to map over our products because we're getting an array of products, and that is happening right here. And then we can see that query happening if we look at our dev tools in the network tab — you can see the actual GraphQL request and the data we get back. Cool. All right, we made it. Okay, any questions?
00:22:59 - Audience questioner
That's awesome. Thanks so much, Anthony. That was a really great presentation. Tristan had a question over here in the chat. I can read it to you. Does Redwood have adapters to other serverless providers such as Cloudflare or Microsoft?
00:23:12 - Anthony Campolo
It's a great question. I have been working with some people at Microsoft and Cloudflare to make this happen. In terms of getting these types of adapters built, we're not there yet and they will likely become a larger priority post v1. The problem is that Azure functions and Lambda functions are not really that similar. They pass in different objects in terms of context objects and event objects. And there's this very weird impedance mismatch between the two.
So you have to essentially decouple out the current Redwood API setup, which is the Apollo Server Lambda library, because that's tightly coupled to Lambda specifically. Or we may get to a point very soon where we're going to have a swappable server — like we have a swappable client — and then that will make it easier to support Lambda and then Cloudflare. Cloudflare is a whole different story. Because you were asking, Jim, about the Node back end, and that's the problem with Cloudflare — Cloudflare doesn't actually give you Node at all. It's running on V8. And so some people get kind of confused by this because they're like, okay, Cloudflare runs on V8 and Node runs on V8, so you can run Node on Cloudflare.
00:24:29 - Anthony Campolo
That's not how it works at all. You can't run Node on Cloudflare. It's a whole different thing. There are a lot of libraries that you don't have access to. But what you can do is start to break off different pieces of your API. Because right now we're doing this thing called the Lambda lift. When we were looking at the whole GraphQL handler created in the backend — this is actually considered an anti-pattern in serverless, to have your entire project be one giant Lambda that you shove online and just hit as a single endpoint, because you get cold start issues and all this stuff spins out from that.
So you want to break it off into smaller individual functions. At a certain point, this is where the Cloudflare stuff will start to come in handy. But this is all future stuff at this point. But it's very interesting.
00:25:22 - Audience questioner
So that is interesting. So right now, Redwood kind of like puts the back end as an app that gets deployed as one function. Is that what it is? But in the future, the idea is to break it into many functions for different tasks.
00:25:33 - Anthony Campolo
Yeah. So right now it is deployed as a single giant GraphQL handler on Lambda. So you can do that via something like Netlify or Vercel, or straight to Lambda itself. But that is what is built for now. You can run it as a container. And this is something that actually a lot of people are doing, and it's become a lot easier to do with something like Render.
So now you can actually just serve the backend as a serverful backend, which is kind of hilarious because Redwood was architected from the beginning to be this whole serverless thing, and then people hacked it to make it serverful. And so now you can run it on Render as just an always-on API server running Redwood, using PM2, which is a Node process manager. So you can do that if you want to, and if you're actually at production scale, that's what you'll likely end up doing. You find this middle ground between serverful and serverless, containers and Lambda — and now you can run containers on Lambda and Lambda on containers. So all these things are getting weirdly mishmashed between each other, and it's just going to depend on your application, what it needs, what you know personally, what you're comfortable setting up, what services you already know.
00:26:52 - Anthony Campolo
There's a lot of contextual stuff baked into when you need to make that switch from serverless to serverful.
00:27:00 - Audience questioner
Awesome. Do folks have other questions? Anthony, I have one last question. Obviously there was some setup, I'm sure, for the demo. I'm curious — the Shopify backend stuff in StepZen, what does that look like to actually connect to it through StepZen? Is it all stuff that you're doing through your project, or is there something in the StepZen interface that you're doing ahead of time to connect those things?
00:27:37 - Anthony Campolo
Yeah, so the code I showed you was all a little strange and fumbly because of the key management, but when I showed you the product type and then that query where you plug in the endpoint, that's the entire thing. And then you just run the command and you're hooked up to the back end. What I showed you is all it took to get connected to the backend. And the reason why is because there are built-in schemas and templates for different backends. So there's a whole repository of those which includes things like Shopify and Mailchimp and a lot of these common Jamstack backends that have already figured out how to map your keys. And then you just give it that YAML which feeds in your keys and that stitches together your whole backend for you.
Then when you run the StepZen start command, it spins up your API and it's running locally. And also it gives you an endpoint — like an actual deployed endpoint that's online, that's managed — that you then plug into your Redwood backend. And this is something — it's unfortunate.
00:28:38 - Anthony Campolo
It's really hard to show exactly how you do it because you have to show your keys to do it. So figuring out these demo flows is always a bit of a challenge, but that's all you're doing. Once you figure out the workflow, getting it spun up and connected is a matter of minutes. It's really, really cool.
00:28:58 - Audience questioner
That's awesome. And then I assume if there was a custom API you're trying to interact with that StepZen hasn't created a template for — is there a way to hit a custom endpoint?
00:29:08 - Anthony Campolo
Yeah, you can feed in any endpoint you want. You could feed it a REST endpoint, another GraphQL endpoint, a database URL. That's the whole point — it stitches together whatever backend you want into this one unified GraphQL endpoint that you can then hit from your front end or from your API backend.
Great. Awesome. Thanks so much, Jim. It was a real pleasure to be here. Jim and I go back from many Jamstack and Svelte meetups — both big Svelte fanboys. But it was very cool to present this for your audience. And I know that a lot of people here are very into APIs and Jamstack-y stuff, and that's what we're really aiming for here with StepZen, so feel free to hit us up. We're at stepzen.com or StepZen_dev on Twitter. Awesome. Sounds like I introduced someone to Plenty, which is very cool. We did a Plenty episode on fsjam, so check that out as well. I'll go ahead and drop that in the chat.
00:30:24 - Audience questioner
Yeah, I appreciate you doing the [unclear] marketing, Anthony. That's great.
00:30:31 - Anthony Campolo
Anytime.
00:30:34 - Audience questioner
Great. Well, thanks everyone for coming by and hanging out with us. Oh, so Anthony dropped fsjam.org — that's a podcast that he runs — in the chat. Check out that Plenty episode if you want to hear about that. But there's a ton of good episodes on there — Anthony talks with the founder of Redwood and a bunch of other folks, the Blitz.js founder, and yeah, it's really a great podcast. Okay, with that I'm going to stop the recording and I'll get these posted hopefully today or tomorrow so people can check these out on YouTube for anyone who missed the meetup.