{"id":19894544,"url":"https://github.com/stepzen-dev/stepzen-redwood","last_synced_at":"2025-07-29T15:09:59.406Z","repository":{"id":109989376,"uuid":"348085844","full_name":"stepzen-dev/stepzen-redwood","owner":"stepzen-dev","description":"A StepZen application with RedwoodJS and Shopify","archived":false,"fork":false,"pushed_at":"2021-05-10T21:36:40.000Z","size":460,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-07-08T08:09:07.167Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://stepzen-redwood.netlify.app/","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/stepzen-dev.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-03-15T18:45:22.000Z","updated_at":"2021-05-10T21:36:42.000Z","dependencies_parsed_at":"2023-03-13T13:59:34.380Z","dependency_job_id":null,"html_url":"https://github.com/stepzen-dev/stepzen-redwood","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/stepzen-dev/stepzen-redwood","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stepzen-dev%2Fstepzen-redwood","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stepzen-dev%2Fstepzen-redwood/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stepzen-dev%2Fstepzen-redwood/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stepzen-dev%2Fstepzen-redwood/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/stepzen-dev","download_url":"https://codeload.github.com/stepzen-dev/stepzen-redwood/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stepzen-dev%2Fstepzen-redwood/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":267705876,"owners_count":24131001,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-07-29T02:00:12.549Z","response_time":2574,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-12T18:33:50.052Z","updated_at":"2025-07-29T15:09:59.351Z","avatar_url":"https://github.com/stepzen-dev.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Redwood+StepZen and Shopify\n\n![stepzen-redwood-cover](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4gmoeed12g8imj1oz4dd.png)\n\n[RedwoodJS](http://redwoodjs.com/) is a fullstack, serverless web application framework for building and deploying Jamstack applications. Imagine a React frontend, statically delivered from a CDN, talking via GraphQL to a backend running on AWS Lambdas, all deployable with `git push`.\n\nThis example project creates a GraphQL API for a Shopify backend connected to a React frontend and deployed on a static hosting provider. Redwood's `api` side is auto-configured with a GraphQL handler that can be deployed with serverless functions, enabling [secure API routes](https://stepzen.com/blog/how-to-secure-api-routes-for-jamstack-sites).\n\n## Project Structure\n\n```\n├── api\n│   ├── src\n│   │   ├── functions\n│   │   │   └── graphql.js\n│   │   ├── graphql\n│   │   │   └── products.sdl.js\n│   │   ├── lib\n│   │   │   └── client.js\n│   │   └── services\n│   │       └── products\n│   │           └── products.js\n│   └── stepzen\n│       ├── shopify\n│       │   └── products.graphql\n│       └── index.graphql\n└── web\n    ├── public\n    │   ├── README.md\n    │   ├── favicon.png\n    │   └── robots.txt\n    └── src\n        ├── components\n        │   └── ProductsCell\n        │       ├── ProductsCell.js\n        │       ├── ProductsCell.mock.js\n        │       ├── ProductsCell.stories.js\n        │       └── ProductsCell.test.js\n        ├── layouts\n        ├── pages\n        │   ├── FatalErrorPage\n        │   │   └── FatalErrorPage.js\n        │   ├── HomePage\n        │   │   └── HomePage.js\n        │   └── NotFoundPage\n        │       └── NotFoundPage.js\n        ├── App.js\n        ├── Routes.js\n        ├── index.css\n        └── index.html\n```\n\n## Setup\n\n### Clone repo\n\n```bash\ngit clone https://github.com/stepzen-samples/stepzen-redwood.git\ncd stepzen-redwood\n```\n\n### Install dependencies\n\nWe'll use [yarn](https://classic.yarnpkg.com/en/docs/install) (which is a requirement) to install our dependencies.\n\n```bash\nyarn\n```\n\n### Fire it up\n\nStart the development server with `yarn rw dev`.\n\n```bash\nyarn rw dev\n```\n\nYour browser should open automatically to `http://localhost:8910` to see the web app.\n\n![01-empty-products](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/c1bzc8dkbxmtpwo1uv5m.png)\n\n### `config.yaml`\n\nWe don't have any products because we haven't connected to Shopify yet. `config.yaml` contains the keys and other credential information that StepZen needs to access your backend data sources. Leave your development server running and open a new terminal.\n\n```bash\ntouch api/stepzen/config.yaml\n```\n\nTo connect your Shopify account, enter your `api_key`, `api_password`, and `store_name`.\n\n```yaml\nconfigurationset:\n  - configuration:\n      name: shopify_config\n      api_key: \u003cYOUR_API_KEY\u003e\n      api_password: \u003cYOUR_API_PASSWORD\u003e\n      store_name: \u003cYOUR_STORE_NAME\u003e\n```\n\n### Deploy endpoint\n\nDeploy your endpoint with `stepzen start`.\n\n```bash\nstepzen start\n```\n\nIn addition to deploying your endpoint, it will also be running on `localhost:5000`.\n\n```bash\nWatching ~/stepzen-redwood/api/stepzen for GraphQL changes\n\nhttp://localhost:5000/stepzen-redwood/products\n```\n\nThe terminal will output the link to a deployed endpoint you can query. Your own account name will replace `biggs`.\n\n```bash\nDeploying to StepZen...... done\n\nSuccessfully deployed stepzen-redwood/products at 2:33:27 PM\n\nYour endpoint is available at https://biggs.stepzen.net/stepzen-redwood/products/__graphql\n```\n\n### Query endpoint\n\n`getProducts` returns an array of `Product` objects with the `title`, `id`, and `handle` for each. Open the GraphQL explorer and enter the following query.\n\n```graphql\nquery getProducts {\n  products {\n    title\n    id\n    handle\n  }\n}\n```\n\n![03-stepzen-graphiql-editor](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qhbqznno6y5x9kghzy55.png)\n\n### Create `.env` file\n\nGo back to your original terminal and turn off the development server (⌃C). We need to restart the server because we are going to create a `.env` file to hold our environment variables.\n\n```bash\ntouch .env\n```\n\nThe server does not detect this change and will result in an error message if you do not restart it after creating the `.env` file.\n\n```bash\nAPI_ENDPOINT=\u003cYOUR_API_ENDPOINT\u003e\nAPI_KEY=\u003cYOUR_API_KEY\u003e\n```\n\nEnter the endpoint generated by `stepzen start` and include your `API_KEY` which can be found in your StepZen account dashboard.\n\n### Start the development server again\n\n```bash\nyarn rw dev\n```\n\nThe `web` side will be running again on `localhost:8910` and now will return products.\n\n![05-home-page-localhost](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gj4pvqmrlil8wwsewlqr.png)\n\nThe `api` side can be accessed through a GraphiQL explorer running on `localhost:8911/graphql`.\n\n![04-redwood-api-graphiql-editor](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nw0tmstq7r5wl4xx41dy.png)\n\n## StepZen Side\n\n`products.graphql` has a `Product` type and a `products` query that returns an array of `Product` objects. The `@rest` directive accepts the `endpoint` from Shopify and the `@supplies` directive provides the query.\n\n```graphql\n# api/stepzen/shopify/products.graphql\n\ntype Product {\n  id: ID!\n  handle: String\n  title: String\n}\n\ntype Query {\n  products: [Product]\n    @rest(\n      resultroot: \"products[]\"\n      endpoint: \"https://$api_key:$api_password@$store_name.myshopify.com/admin/api/2020-01/products.json\"\n      configuration: \"shopify_config\"\n    )\n}\n```\n\n### index.graphql\n\nOur `schema` in `index.graphql` ties together all of our other schemas. For this example we just have the `products.graphql` file included in our `@sdl` directive.\n\n```graphql\n# api/stepzen/index.graphql\n\nschema\n  @sdl(\n    files: [ \"schema/products.graphql\" ]\n  ) {\n  query: Query\n}\n```\n\nThis file tells StepZen how to assemble the various type definition files into a complete GraphQL schema. The `@sdl` directive is a StepZen directive that specifies the list of files to assemble.\n\n## Redwood API Side\n\nThe `functions` directory contains a `graphql.js` file that defines our GraphQL handler for serverless deployment to AWS Lambda or platforms that offer Lambda support such as Netlify and Vercel.\n\n```javascript\n// api/src/functions/graphql.js\n\nimport {\n  createGraphQLHandler,\n  makeMergedSchema,\n  makeServices,\n} from '@redwoodjs/api'\n\nimport schemas from 'src/graphql/**/*.{js,ts}'\nimport services from 'src/services/**/*.{js,ts}'\n\nexport const handler = createGraphQLHandler({\n  schema: makeMergedSchema({\n    schemas,\n    services: makeServices({ services }),\n  }),\n})\n```\n\n### Products Schema\n\nThe `graphql` directory contains `products.sdl.js` with your GraphQL schema written in a Schema Definition Language. This ensures that our Redwood API will have a `schema` that matches our `schema` in `products.graphql`.\n\n```javascript\n// api/src/graphql/products.sdl.js\n\nexport const schema = gql`\n  type Product {\n    id: ID\n    handle: String\n    title: String\n  }\n\n  type Query {\n    products: [Product]\n  }\n`\n```\n\nThe schema includes a `Product` type, and each `Product` has an `id`, `handle`, and `title`. The `products` query returns an array of `Product` objects.\n\n### GraphQL Client\n\nWhile Redwood's `web` side includes Apollo Client by default, its `api` side does not include any built in mechanism for making HTTP requests.\n\n```javascript\n// api/src/lib/client.js\n\nimport { GraphQLClient } from 'graphql-request'\n\nexport const request = async (query = {}) =\u003e {\n  const endpoint = process.env.API_ENDPOINT\n\n  const graphQLClient = new GraphQLClient(endpoint, {\n    headers: {\n      authorization: 'apikey ' + process.env.API_KEY\n    },\n  })\n  try {\n    return await graphQLClient.request(query)\n  } catch (err) {\n    console.log(err)\n    return err\n  }\n}\n```\n\nThis project uses `graphql-request` but `node-fetch` could be used instead.\n* `endpoint` is set to the url generated by `stepzen start`\n* `authorization` includes your StepZen API key appended to `apikey `\n\n### Products Service\n\nIn the `services` directory we have a `products` directory with a `products.js` service.\n\n```javascript\n// api/src/services/products/products.js\n\nimport { request } from 'src/lib/client'\nimport { gql } from 'graphql-request'\n\nexport const products = async () =\u003e {\n  const GET_PRODUCTS_QUERY = gql`\n    query getProducts {\n      products {\n        title\n        id\n        handle\n      }\n    }\n  `\n\n  const data = await request(GET_PRODUCTS_QUERY)\n\n  return data['products']\n}\n```\n\nThe query is asking for the list of `products` and their `title`, `id`, and `handle`. The `GraphQLClient` is imported from `src/lib/client`.\n\n## Redwood Web Side\n\nThe `web` side contains our `ProductsCell` for fetching `products` and a `HomePage` for rendering the cell.\n\n### ProductsCell\n\n`getProducts` returns the `id`, `title`, and `handle` of each `Product`. This will send the query to our `api` side, which in turn sends a query to our StepZen API.\n\n```jsx\n// web/src/components/ProductsCell/ProductsCell.js\n\nexport const QUERY = gql`\n  query getProducts {\n    products {\n      id\n      title\n      handle\n    }\n  }\n`\n\nexport const Loading = () =\u003e \u003cdiv\u003eAlmost there...\u003c/div\u003e\nexport const Empty = () =\u003e \u003cdiv\u003eWE NEED PRODUCTS\u003c/div\u003e\nexport const Failure = ({ error }) =\u003e \u003cdiv\u003e{error.message}\u003c/div\u003e\n\nexport const Success = ({ products }) =\u003e {\n  return (\n    \u003cul\u003e\n      {products.map(product =\u003e (\n        \u003cli\u003e{product.title}\u003c/li\u003e\n      ))}\n    \u003c/ul\u003e\n  )\n}\n```\n\n### HomePage\n\n`ProductsCell` is imported onto `HomePage` to display the information fetched by the cell's query.\n\n```jsx\n// web/src/pages/HomePage/HomePage.js\n\nimport ProductsCell from 'src/components/ProductsCell'\n\nconst HomePage = () =\u003e {\n  return (\n    \u003c\u003e\n      \u003ch1\u003eStepZen+Redwood and Shopify\u003c/h1\u003e\n      \u003ch2\u003eProducts\u003c/h2\u003e\n\n      \u003cProductsCell /\u003e\n    \u003c/\u003e\n  )\n}\n\nexport default HomePage\n```\n\n## Deploy to Netlify\n\nRedwood provides helpful setup commands to deploy to various hosting providers. Our project is already configured to deploy to [Netlify](https://redwoodjs.com/docs/deploy#netlify-deploy) with our `netlify.toml` file.\n\n```toml\n[build]\n  command = \"yarn rw deploy netlify\"\n  publish = \"web/dist\"\n  functions = \"api/dist/functions\"\n\n[dev]\n  command = \"yarn rw dev\"\n\n[[redirects]]\n  from = \"/*\"\n  to = \"/index.html\"\n  status = 200\n```\n\nThe `netlify.toml` file lets Netlify know that:\n* Your `build` command is `yarn rw deploy netlify`\n* The `publish` directory for your assets is `web/dist`\n* Your `functions` will be in `api/dist/functions`\n\n![06-home-page-hosted-on-netlify](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/054g4nmv18e9vbqte86a.png)\n\nOpen your browser's developer tools and look at the response in your Network tab.\n\n![07-console-log-response-data](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kkobxqb731w0j7k3nw01.png)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstepzen-dev%2Fstepzen-redwood","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fstepzen-dev%2Fstepzen-redwood","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstepzen-dev%2Fstepzen-redwood/lists"}