You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This repository contains the source code of my personal mini-website.
4
4
It represents a simple instance of a Next.js app with server components, API routes and domain-based internationalization.
5
-
Feel free to use this codebase to learn something new or to reuse some of its bits in your own projects.
5
+
Feel free to use this codebase to learn something new or to reuse various bits in your own projects.
6
6
7
7
## Key ingredients
8
8
9
-
-[Next.js](https://nextjs.org) (with `/app` directory) as the architecture framework
10
-
-[React](https://reactjs.org) to define the UI (server and client components)
11
-
-[Tailwind CSS](https://tailwindcss.com) to style the UI
12
-
-[FormatJS](https://formatjs.io) to handle internationalization ([ICU](https://formatjs.io/docs/core-concepts/icu-syntax/) plurals etc.)
13
-
-[Playwright](https://playwright.dev), [Zod](https://zod.dev) and [Axios](https://axios-http.com) to update profile infos in API handlers
14
-
-[ESLint](https://eslint.org), [Markdownlint](https://github.com/DavidAnson/markdownlint), [Prettier](https://prettier.io) and [TypeScript](https://www.typescriptlang.org) to statically check and autocorrect source files
15
-
-[pnpm](https://pnpm.io) to manage dependencies
16
-
-[Docker](https://www.docker.com) to generate deployable production artifacts
17
-
-[Kubernetes](https://kubernetes.io) to run the app in production
18
-
-[GitHub Actions](https://github.com/features/actions) to run CI/CD pipelines
9
+
-**[Next.js](https://nextjs.org)** (with `/app` directory) as the architecture framework
10
+
-**[React](https://reactjs.org)** to define the UI (server and client components)
11
+
-**[Tailwind CSS](https://tailwindcss.com)** to style the UI (including dark/light themes)
12
+
-**[FormatJS](https://formatjs.io)** to handle internationalization ([ICU](https://formatjs.io/docs/core-concepts/icu-syntax/) plurals etc.)
13
+
-**[Google Analytics](https://analytics.google.com)** to track website usage
14
+
-**[Axios](https://axios-http.com)**, **[Zod](https://zod.dev)** and **[Playwright](https://playwright.dev)** to update profile infos in API handlers
15
+
-**[ESLint](https://eslint.org)**, **[Markdownlint](https://github.com/DavidAnson/markdownlint)**, **[Prettier](https://prettier.io)** and **[TypeScript](https://www.typescriptlang.org)** to statically check and autocorrect source files
16
+
-**[pnpm](https://pnpm.io)** to manage dependencies
17
+
-**[Docker](https://www.docker.com)** to generate a deployable production artifact
18
+
-**[Kubernetes](https://kubernetes.io)** to run the app in production
19
+
-**[GitHub Actions](https://github.com/features/actions)** to run [CI/CD](https://en.wikipedia.org/wiki/CI/CD) pipelines
19
20
20
-
## Short-term plans
21
+
## Project structure
21
22
22
-
-[ ] finish README
23
-
-[ ] improve locale animation (use framer-motion)
23
+
The codebase is inspired by these Next.js examples:
The main web page renders a list of profiles and shows relevant stats.
30
+
The numbers are taken from a few [YAML](https://en.wikipedia.org/wiki/YAML) files that are stored locally.
31
+
Thanks to React server components, these files can be read directly by the Node.js process and there is no need to introduce any React state to re-hydrate profile infos on the client.
32
+
This simplifies the app architecture and reduces the amount of the JavaScript to download.
33
+
34
+
Profile infos are updated inside Next.js API routes.
35
+
A GET request to `/update-profiles/[profile-id]?[security-token]` scrapes a third-party service (e.g. GitHub, OpenStreetMap, etc.) and updates a corresponding YAML file.
36
+
Some profile infos are generated by making lightweight requests to JSON endpoints using [Axios](https://axios-http.com) and [Zod](https://zod.dev), but the most common approach involves using [Playwright](https://playwright.dev), a browser automation library.
37
+
Profiles are updated on a schedule (see [Deployment](#deployment) section).
38
+
Because API routes are public, a security token is introduced to prevent server abuse.
28
39
29
40
## Known issues
30
41
31
-
-**Components inside i18n strings**, e.g. `Hello <a>world</a>!`
32
-
This is possible with [`<Trans />` component](https://react.i18next.com/latest/trans-component) in `react-i18next` (pending a version that supports `/app` directory and server components).
My go-to solution for internationalising Next.js pages is [`next-i18next`](https://www.npmjs.com/package/next-i18next).
44
+
Because this package is incompatible with the `/app` directory (at least as of early March 2023), I have used a rather bare-bones approach inspired by the [app-dir-i18n-routing](https://github.com/vercel/next.js/tree/canary/examples/app-dir-i18n-routing) example.
45
+
The current solution is not as polished as `next-i18next` when it comes to propagating translations to components, but it works well enough for my needs.
46
+
I might consider following [i18next/next-13-app-dir-i18next-example](https://github.com/i18next/next-13-app-dir-i18next-example) in the future but I am generally waiting for this space to mature.
47
+
48
+
In the meantime, I use [`@formatjs/intl`](https://www.npmjs.com/package/@formatjs/intl) to handle plurals, which is somewhat low-level and should not be done in Next.js apps.
49
+
Ideally, I would like to have i18n resources available as React context and use components inside i18n strings (e.g. `Hello <a>world</a>!`).
50
+
The latter is possible with [`<Trans />` component](https://react.i18next.com/latest/trans-component) in `react-i18next`, which I hope to use at some point.
51
+
52
+
-**Custom 404 page is implemented via `middleware.ts`**
53
+
As of early March 2023, Next.js [does not support](https://beta.nextjs.org/docs/api-reference/file-conventions/not-found) custom 404 pages inside the `/app` directory.
54
+
Until a permanent solution is available, incoming requests are checked against `existingPathnamePatterns` in [`middleware.ts`](./middleware.ts).
55
+
This enables custom 404 pages which are i18n-aware, but requires manual updates to `existingPathnamePatterns` each time a new app route is added.
56
+
Thus, the workaround is error-prone, especially for apps that have a lot of routes.
57
+
58
+
-**No progress bar when navigating between pages**
59
+
I like using [`nprogress`](https://www.npmjs.com/package/nprogress) in apps with client-side navigation between pages.
60
+
A progress bar improves the perceived performance of the app and makes it feel more responsive.
61
+
Unfortunately, `nprogress` does not work well with Next.js apps that use server components.
62
+
I hope to find a solution to this problem in the future.
0 commit comments