https://github.com/paul-borisov/nextjs-graphql-countries-with-details-in-dynamic-right-hand-panel
This is an educational project in Next.js 15 RC + React 19 for my colleagues, which highlights concepts of using GraphQL with Appollo client.
https://github.com/paul-borisov/nextjs-graphql-countries-with-details-in-dynamic-right-hand-panel
apollo-client educational-project graphql nextjs radix-ui tanstack-virtual
Last synced: 6 months ago
JSON representation
This is an educational project in Next.js 15 RC + React 19 for my colleagues, which highlights concepts of using GraphQL with Appollo client.
- Host: GitHub
- URL: https://github.com/paul-borisov/nextjs-graphql-countries-with-details-in-dynamic-right-hand-panel
- Owner: Paul-Borisov
- License: mit
- Created: 2024-10-04T18:42:12.000Z (about 1 year ago)
- Default Branch: main
- Last Pushed: 2024-10-19T05:23:57.000Z (12 months ago)
- Last Synced: 2025-04-23T02:18:54.011Z (6 months ago)
- Topics: apollo-client, educational-project, graphql, nextjs, radix-ui, tanstack-virtual
- Language: TypeScript
- Homepage:
- Size: 593 KB
- Stars: 2
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Overview
This is an educational **Next.js 15 RC + React 19** project for my colleagues, which highlights concepts of using GraphQL with Appollo client.
- Technical stack: Next.js 15, React 19, TypeScript, GraphQL with Apollo Client and public server endpoint, Tailwind, Radix UI, TanStask Virtual.
- Homepage queries a public GraphQL service, which returns a list of countries with desired attributes.

- Data is presented in a tabular view with multiple attributes including country codes shaped as links.
- I also added a navigation item to virtual grid with effects of dynamic **infinite scroll**.

- Click on a country code opens a country page using the standard feature of Next.js dynamic routes like [app/\[countrycode\]/page.tsx](app/[countrycode]/page.tsx)
- The country page queries the same GraphQL service but this time using the filter by "code" like
query {
countries(filter: {code: {eq: "countrycode"}}) {
...
}
}
- If data does not have country name in returned attributes, the logic additionally queries a public REST service supplying the country code to get the name.



# Simple steps to add support of GraphQL to Next.js environments
Use Appollo Client. More details: https://www.apollographql.com/docs/react/get-started
1. Add two packages
npm install @apollo/client graphql2. Add the following code to your component
```typescript
import {
ApolloClient,
InMemoryCache,
ApolloProvider,
gql,
} from "@apollo/client";const client = new ApolloClient({
uri: "https://countries.trevorblades.com/", // Put here URL of your GraphQL endpoint (server)
cache: new InMemoryCache(),
});const queryFilter = '(filter: {currency: {eq: "EUR"}})';
client
.query({
query: gql`
query {
countries${queryFilter} {
name: awsRegion
capital
code
continent {
code
name
}
currencies
currency
languages {
code
name
native
}
phone
phones
states {
code
country {
name
}
name
}
}
}
`,
})
.then((result) => console.log(result));
```3. You can also test simple GraphQL queries locally in the browser's console. For instance:
- Open the site https://flyby-router-demo.herokuapp.com/ to be compliant with their Content Security Policy directives.
- While staying on the same page, open Dev Tools (by pressing F12 in Chrome) and enter the following code into the console.
```javascript
fetch("https://flyby-router-demo.herokuapp.com/", {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify({
query: `query GetLocations {
locations {
id
name
description
photo
}
}`,
}),
})
.then((r) => r.json())
.then((data) => console.log(data));
```# User interface
- The UI adjusts automatically to using a current system theme of user's environment, dark or light.
- A combination of loading.tsx + Suspense + fallback Shimmer control highlights usage of lazy server-side data loading.
- Also, the server component [components/server/ContentHomeCountry.tsx](components/server/ContentHomeCountry.tsx) loads dynamically a client side component with disabled SSR.
- This technique demonstrates how to solve classic SSR problems with using window and other client side only objects ported from old codebases.
- Country page demonstrates usage of Radix UI Themes controls from the package @radix-ui/themes.
- **Details** button visible on the page opens a right-hand side panel, which is made of slightly tweaked Radix UI Dialog.
- All page elements support dynamic detection of a system theme change and correctly reflect this change with no page reloading.
- For instance, open the right-hand side panel and change system theme from light to dark. The panel should correctly reflect this change.
- The logic uses **window.matchMedia("(prefers-color-scheme: dark)")** with **change** event listener. Please refer to [shared/hooks/useSystemDarkMode.ts](shared/hooks/useSystemDarkMode.ts).
- The codebase includes a few useful tailor-made features managed by settings in .env file.
- pagecachetimeout=15: demostrates how to persist cache data on all pages for 15 seconds in production builds.
- To show this, the first row in the home page table gets a test value with dynamic [Phone](docs/images/2_homepage-loaded-in-dark-system-theme.png) property. This data persists for 15 seconds and then gets updated.
- showVerticalScrollbar=true: demostrates correct settings of Radix Dialog to suppress undesired UI-layout shifts on opening the right-hand side panel in the browser window with a visible vertical scrollbar.
- disableSidePanelLightClosing=true: demostrates how to prevent accidental closing of the right-hand side panel on "mouse click outside" and "ESC key press" events.
- CSS styling uses a combination of global.css, Tailwind, and modules to highlight different ways of using styles.
# Getting Started
Clone this project.
Review / adjust default settings found in .env
```bash
endpointCountryByCode=https://restcountries.com/v3.1/alpha/{countryCode}
endpointGraphqlCountries=https://countries.trevorblades.com/
apiKeyGql="for instance, an api key for your GQL endpoint"
pagetitlehome="Next.js 15 with GraphQL/Apollo"
pagedescriptionhome="Example of Next.js 15 app with GraphQL queries via Appollo Client"
pageheader="Next.js 15 app with GraphQL queries via Appollo Client"
pagecachetimeout=15 # seconds, for production builds
showVerticalScrollbar=true
disableSidePanelLightClosing=true
```Install modules
```bash
npm i
```Start the dev server
```bash
npm run dev
```Open [http://localhost:3000](http://localhost:3000) and load the home page.