{"id":19972686,"url":"https://github.com/jpb06/graphql-shop","last_synced_at":"2025-08-26T01:17:23.477Z","repository":{"id":57945185,"uuid":"527924446","full_name":"jpb06/graphql-shop","owner":"jpb06","description":null,"archived":false,"fork":false,"pushed_at":"2025-07-05T18:20:31.000Z","size":5524,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-08-11T18:42:41.681Z","etag":null,"topics":["graphql","monorepo","nestjs","nextjs","nx","prisma","react"],"latest_commit_sha":null,"homepage":"https://graphql-shop-seven.vercel.app","language":"TypeScript","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/jpb06.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,"zenodo":null}},"created_at":"2022-08-23T09:42:00.000Z","updated_at":"2025-07-05T18:21:52.000Z","dependencies_parsed_at":"2025-08-11T18:38:23.370Z","dependency_job_id":null,"html_url":"https://github.com/jpb06/graphql-shop","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/jpb06/graphql-shop","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jpb06%2Fgraphql-shop","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jpb06%2Fgraphql-shop/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jpb06%2Fgraphql-shop/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jpb06%2Fgraphql-shop/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jpb06","download_url":"https://codeload.github.com/jpb06/graphql-shop/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jpb06%2Fgraphql-shop/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":272156041,"owners_count":24883159,"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-08-25T02:00:12.092Z","response_time":1107,"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":["graphql","monorepo","nestjs","nextjs","nx","prisma","react"],"created_at":"2024-11-13T03:08:56.123Z","updated_at":"2025-08-26T01:17:23.463Z","avatar_url":"https://github.com/jpb06.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# graphql-shop\n\nToying with graphql by coding a simple webshop app.\n\n\u003c!-- readme-package-icons start --\u003e\n\n\u003cp align=\"left\"\u003e\u003ca href=\"https://docs.github.com/en/actions\" target=\"_blank\"\u003e\u003cimg height=\"50\" width=\"50\" src=\"https://raw.githubusercontent.com/jpb06/jpb06/master/icons/GithubActions-Dark.svg\" /\u003e\u003c/a\u003e\u0026nbsp;\u003ca href=\"https://www.typescriptlang.org/docs/\" target=\"_blank\"\u003e\u003cimg height=\"50\" width=\"50\" src=\"https://raw.githubusercontent.com/jpb06/jpb06/master/icons/TypeScript.svg\" /\u003e\u003c/a\u003e\u0026nbsp;\u003ca href=\"https://nodejs.org/en/docs/\" target=\"_blank\"\u003e\u003cimg height=\"50\" width=\"50\" src=\"https://raw.githubusercontent.com/jpb06/jpb06/master/icons/NodeJS-Dark.svg\" /\u003e\u003c/a\u003e\u0026nbsp;\u003ca href=\"https://pnpm.io/motivation\" target=\"_blank\"\u003e\u003cimg height=\"50\" width=\"50\" src=\"https://raw.githubusercontent.com/jpb06/jpb06/master/icons/Pnpm-Dark.svg\" /\u003e\u003c/a\u003e\u0026nbsp;\u003ca href=\"https://fly.io/docs/\" target=\"_blank\"\u003e\u003cimg height=\"50\" width=\"50\" src=\"https://raw.githubusercontent.com/jpb06/jpb06/master/icons/FlyIo-Dark.svg\" /\u003e\u003c/a\u003e\u0026nbsp;\u003ca href=\"https://docs.docker.com\" target=\"_blank\"\u003e\u003cimg height=\"50\" width=\"50\" src=\"https://raw.githubusercontent.com/jpb06/jpb06/master/icons/Docker.svg\" /\u003e\u003c/a\u003e\u0026nbsp;\u003ca href=\"https://www.postgresql.org/docs/\" target=\"_blank\"\u003e\u003cimg height=\"50\" width=\"50\" src=\"https://raw.githubusercontent.com/jpb06/jpb06/master/icons/PostgreSQL-Dark.svg\" /\u003e\u003c/a\u003e\u0026nbsp;\u003ca href=\"https://www.apollographql.com/docs/react/\" target=\"_blank\"\u003e\u003cimg height=\"50\" width=\"50\" src=\"https://raw.githubusercontent.com/jpb06/jpb06/master/icons/Apollo.svg\" /\u003e\u003c/a\u003e\u0026nbsp;\u003ca href=\"https://babeljs.io/docs/en/\" target=\"_blank\"\u003e\u003cimg height=\"50\" width=\"50\" src=\"https://raw.githubusercontent.com/jpb06/jpb06/master/icons/Babel-Dark.svg\" /\u003e\u003c/a\u003e\u0026nbsp;\u003ca href=\"https://docs.cypress.io/guides/overview/why-cypress\" target=\"_blank\"\u003e\u003cimg height=\"50\" width=\"50\" src=\"https://raw.githubusercontent.com/jpb06/jpb06/master/icons/Cypress-Dark.svg\" /\u003e\u003c/a\u003e\u0026nbsp;\u003ca href=\"https://github.com/motdotla/dotenv#readme\" target=\"_blank\"\u003e\u003cimg height=\"50\" width=\"50\" src=\"https://raw.githubusercontent.com/jpb06/jpb06/master/icons/Dotenv-Dark.svg\" /\u003e\u003c/a\u003e\u0026nbsp;\u003ca href=\"https://eslint.org/docs/latest/\" target=\"_blank\"\u003e\u003cimg height=\"50\" width=\"50\" src=\"https://raw.githubusercontent.com/jpb06/jpb06/master/icons/Eslint-Dark.svg\" /\u003e\u003c/a\u003e\u0026nbsp;\u003ca href=\"https://expressjs.com/en/starter/installing.html\" target=\"_blank\"\u003e\u003cimg height=\"50\" width=\"50\" src=\"https://raw.githubusercontent.com/jpb06/jpb06/master/icons/ExpressJS-Dark.svg\" /\u003e\u003c/a\u003e\u0026nbsp;\u003ca href=\"https://fakerjs.dev/guide/\" target=\"_blank\"\u003e\u003cimg height=\"50\" width=\"50\" src=\"https://raw.githubusercontent.com/jpb06/jpb06/master/icons/Faker-Dark.svg\" /\u003e\u003c/a\u003e\u0026nbsp;\u003ca href=\"https://graphql.org/learn/\" target=\"_blank\"\u003e\u003cimg height=\"50\" width=\"50\" src=\"https://raw.githubusercontent.com/jpb06/jpb06/master/icons/GraphQL-Dark.svg\" /\u003e\u003c/a\u003e\u0026nbsp;\u003ca href=\"https://www.i18next.com/overview/getting-started\" target=\"_blank\"\u003e\u003cimg height=\"50\" width=\"50\" src=\"https://raw.githubusercontent.com/jpb06/jpb06/master/icons/I18next-Dark.svg\" /\u003e\u003c/a\u003e\u0026nbsp;\u003ca href=\"https://jestjs.io/docs/getting-started\" target=\"_blank\"\u003e\u003cimg height=\"50\" width=\"50\" src=\"https://raw.githubusercontent.com/jpb06/jpb06/master/icons/Jest.svg\" /\u003e\u003c/a\u003e\u0026nbsp;\u003ca href=\"https://jotai.org/docs/introduction\" target=\"_blank\"\u003e\u003cimg height=\"50\" width=\"50\" src=\"https://raw.githubusercontent.com/jpb06/jpb06/master/icons/Jotai-Dark.svg\" /\u003e\u003c/a\u003e\u0026nbsp;\u003ca href=\"https://jwt.io\" target=\"_blank\"\u003e\u003cimg height=\"50\" width=\"50\" src=\"https://raw.githubusercontent.com/jpb06/jpb06/master/icons/Jwt-Dark.svg\" /\u003e\u003c/a\u003e\u0026nbsp;\u003ca href=\"https://docs.nestjs.com\" target=\"_blank\"\u003e\u003cimg height=\"50\" width=\"50\" src=\"https://raw.githubusercontent.com/jpb06/jpb06/master/icons/NestJS-Dark.svg\" /\u003e\u003c/a\u003e\u0026nbsp;\u003ca href=\"https://nextjs.org/docs/getting-started\" target=\"_blank\"\u003e\u003cimg height=\"50\" width=\"50\" src=\"https://raw.githubusercontent.com/jpb06/jpb06/master/icons/NextJS-Dark.svg\" /\u003e\u003c/a\u003e\u0026nbsp;\u003ca href=\"https://nx.dev/getting-started/intro\" target=\"_blank\"\u003e\u003cimg height=\"50\" width=\"50\" src=\"https://raw.githubusercontent.com/jpb06/jpb06/master/icons/Nx-Dark.svg\" /\u003e\u003c/a\u003e\u0026nbsp;\u003ca href=\"https://www.passportjs.org/docs/\" target=\"_blank\"\u003e\u003cimg height=\"50\" width=\"50\" src=\"https://raw.githubusercontent.com/jpb06/jpb06/master/icons/Passport-Dark.svg\" /\u003e\u003c/a\u003e\u0026nbsp;\u003ca href=\"https://prettier.io/docs/en/index.html\" target=\"_blank\"\u003e\u003cimg height=\"50\" width=\"50\" src=\"https://raw.githubusercontent.com/jpb06/jpb06/master/icons/Prettier-Dark.svg\" /\u003e\u003c/a\u003e\u0026nbsp;\u003ca href=\"https://www.prisma.io/docs/\" target=\"_blank\"\u003e\u003cimg height=\"50\" width=\"50\" src=\"https://raw.githubusercontent.com/jpb06/jpb06/master/icons/Prisma.svg\" /\u003e\u003c/a\u003e\u0026nbsp;\u003ca href=\"https://reactjs.org/docs/getting-started.html\" target=\"_blank\"\u003e\u003cimg height=\"50\" width=\"50\" src=\"https://raw.githubusercontent.com/jpb06/jpb06/master/icons/React-Dark.svg\" /\u003e\u003c/a\u003e\u0026nbsp;\u003ca href=\"https://react-hook-form.com/get-started\" target=\"_blank\"\u003e\u003cimg height=\"50\" width=\"50\" src=\"https://raw.githubusercontent.com/jpb06/jpb06/master/icons/ReactHookForm-Dark.svg\" /\u003e\u003c/a\u003e\u0026nbsp;\u003ca href=\"https://tanstack.com/query/v4/docs/overview\" target=\"_blank\"\u003e\u003cimg height=\"50\" width=\"50\" src=\"https://raw.githubusercontent.com/jpb06/jpb06/master/icons/ReactQuery-Dark.svg\" /\u003e\u003c/a\u003e\u0026nbsp;\u003ca href=\"https://rxjs.dev/guide/overview\" target=\"_blank\"\u003e\u003cimg height=\"50\" width=\"50\" src=\"https://raw.githubusercontent.com/jpb06/jpb06/master/icons/Rxjs-Dark.svg\" /\u003e\u003c/a\u003e\u0026nbsp;\u003ca href=\"https://tailwindcss.com/docs/installation\" target=\"_blank\"\u003e\u003cimg height=\"50\" width=\"50\" src=\"https://raw.githubusercontent.com/jpb06/jpb06/master/icons/TailwindCSS-Dark.svg\" /\u003e\u003c/a\u003e\u0026nbsp;\u003ca href=\"https://testing-library.com/docs/\" target=\"_blank\"\u003e\u003cimg height=\"50\" width=\"50\" src=\"https://raw.githubusercontent.com/jpb06/jpb06/master/icons/TestingLibrary-Dark.svg\" /\u003e\u003c/a\u003e\u0026nbsp;\u003ca href=\"https://github.com/typestack\" target=\"_blank\"\u003e\u003cimg height=\"50\" width=\"50\" src=\"https://raw.githubusercontent.com/jpb06/jpb06/master/icons/TypeStack-Dark.svg\" /\u003e\u003c/a\u003e\u0026nbsp;\u003ca href=\"https://webpack.js.org/concepts/\" target=\"_blank\"\u003e\u003cimg height=\"50\" width=\"50\" src=\"https://raw.githubusercontent.com/jpb06/jpb06/master/icons/Webpack-Dark.svg\" /\u003e\u003c/a\u003e\u0026nbsp;\u003ca href=\"https://github.com/colinhacks/zod#introduction\" target=\"_blank\"\u003e\u003cimg height=\"50\" width=\"50\" src=\"https://raw.githubusercontent.com/jpb06/jpb06/master/icons/Zod-Dark.svg\" /\u003e\u003c/a\u003e\u003c/p\u003e\n\n\u003c!-- readme-package-icons end --\u003e\n\n## ⚡ Quickstart\n\n### 🔶 Launching database instance\n\n```bash\npnpm docker-db\n```\n\n### 🔶 Seeding database\n\n```bash\npnpm docker-db-seed\n```\n\n### 🔶 Launching frontend and backend services\n\n```bash\npnpm dev\n```\n\n### 🔶 Launching tests\n\n```bash\npnpm nx run-many --target=test --all\n```\n\n## ⚡ Subject\n\nThe purpose of our app will be to sell products to customers by allowing them to place orders. This gives us several features to address, typical for an online webapp store:\n\n- Products display, filtering and actions\n- Shopping cart\n- Login / Signup\n- Shipping options\n- Payment mockup\n- Orders history\n\n## ⚡ Stack\n\n### 🔶 Tooling - [pnpm](https://pnpm.io) | [nx](https://nx.dev/getting-started/intro) | [graphql-codegen](https://github.com/dotansimha/graphql-code-generator)\n\n#### 🧿 nx\n\nnx is a great tool for monorepos. It will allow us to define both our backend and our frontend in the same repo. We will also split up the codebase further with the use of nx libraries.\n\n![nx graph](./docs/nx-graph.png)\n\n#### 🧿 Graphql Codegen\n\nWe are using [a tool](https://the-guild.dev/graphql/codegen) to generate code based on react-query from the backend graphql schema and graphql code defined in our frontend. Here is a little schema:\n\n![codegen](./docs/graphql-codegen.png)\n\n- On the backend, our graphql schema is an autogenerated file from nest graphql module, which based on apollo server.\n- On the frontend, we start by defining atomic queries/mutation in graphql; these files are pulled by the codegen tool to autogenerate react-query queries/mutations, along with their related types.\n\nGeneration is as simple as executing this command:\n\n```bash\npnpm nx fetch lib-graphql-codegen\n```\n\n### 🔶 Backend - [nest](https://docs.nestjs.com) | [prisma](https://www.prisma.io/docs/getting-started)\n\nWe are using nest graphql module to define what will be exposed on the graphql schema. Nest module is very similar to [typegraphql](https://typegraphql.com): we define resolvers that will contain functions annotated with decorators defined in `@nestjs/graphql` to define our queries, mutations and fields resolution.\n\nThese resolvers rely on a service layer that is responsible for the interaction with our database, using prisma ORM.\n\n### 🔶 Frontend - [next](https://nextjs.org/docs/getting-started) | [jotai](https://jotai.org/docs/introduction) | [react-query](https://tanstack.com/query/v4/docs/overview) | [tailwind](https://tailwindcss.com/docs/installation)\n\nAs for frontend, the api layer is already resolved for us thanks to the codegen mentioned earlier. We do need some transient state however. I chose jotai for this, which is very flexible, simple and elegant.\n\nAll we have to do is to define atomic state that can then be consumed anywhere in the components tree.\n\n### 🔶 Deployment - [docker](https://docs.docker.com) | [vercel](https://vercel.com/docs) | [fly.io](https://fly.io/docs/)\n\nFrontend deployment is really easy thans to vercel. However, when it comes to backend, we have several choices, some more onerous than others. I personally chose fly.io as a replacement for heroku free dynos.\n\n## ⚡ Database\n\n![Diagram](./docs/dbase-model.png)\n\n### 🔶 Creating a new migration\n\n```bash\npnpm prisma-migrate \u003cmigration_name\u003e\n```\n\n### 🔶 Seeding database manually\n\n```bash\npnpm prisma-seed\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjpb06%2Fgraphql-shop","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjpb06%2Fgraphql-shop","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjpb06%2Fgraphql-shop/lists"}