Skip to content

Commit 57d09ac

Browse files
committed
Update docs
1 parent 4c6aa1e commit 57d09ac

File tree

2 files changed

+128
-33
lines changed

2 files changed

+128
-33
lines changed

.env

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
FLICKR_USER_ID=
2+
FLICKR_API_KEY=
3+
4+
BASE_URL_EN=
5+
BASE_URL_RU=
6+
7+
UPDATE_PROFILE_SECURITY_TOKEN=
8+
UPDATE_PROFILE_PROXY_SERVER_URL=

README.md

Lines changed: 120 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -2,55 +2,142 @@
22

33
This repository contains the source code of my personal mini-website.
44
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.
66

77
## Key ingredients
88

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
1920

20-
## Short-term plans
21+
## Project structure
2122

22-
- [ ] finish README
23-
- [ ] improve locale animation (use framer-motion)
23+
The codebase is inspired by these Next.js examples:
2424

25-
## Project structure
25+
- [app-dir-i18n-routing](https://github.com/vercel/next.js/tree/canary/examples/app-dir-i18n-routing)
26+
- [with-tailwindcss](https://github.com/vercel/next.js/tree/canary/examples/with-tailwindcss)
27+
- [with-typescript](https://github.com/vercel/next.js/tree/canary/examples/with-typescript)
2628

27-
TODO
29+
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.
2839

2940
## Known issues
3041

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).
33-
- TODO: elaborate on
34-
- 404s (permanent solution)
35-
- nbprogress
36-
- https://github.com/vercel/next.js/issues/45499
37-
- https://github.com/apal21/nextjs-progressbar/issues/86
42+
- **Internationalized (i18n) is hacky**
43+
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.
63+
Related issues:
64+
- https://github.com/vercel/next.js/issues/45499
65+
- https://github.com/apal21/nextjs-progressbar/issues/86
3866

3967
## Local development
4068

41-
TODO describe how to run the app locally
69+
### Getting started
4270

43-
```sh
44-
pnpm install
45-
pnpm dev
46-
```
71+
1. Ensure you have [git](https://git-scm.com), [Node.js](https://nodejs.org) and [pnpm](https://pnpm.io) installed on your machine:
4772

48-
## Deployment
73+
```sh
74+
git --version
75+
## ≥ 2.30.0
76+
77+
node --version
78+
## ≥ 18.12.0
79+
80+
pnpm --version
81+
## ≥ 7.28.0
82+
```
83+
84+
1. Clone the repo from GitHub:
85+
86+
```sh
87+
cd PATH/TO/MISC/PROJECTS
88+
git clone https://github.com/kachkaev/website.git
89+
cd website
90+
```
91+
92+
1. Install dependencies:
93+
94+
```sh
95+
pnpm install
96+
```
97+
98+
1. Copy `.env` to `.env.local`:
99+
100+
```sh
101+
cp .env .env.local
102+
```
103+
104+
We will need `.env.local` later.
105+
Unlike `.env`, it is not tracked by git and is not committed to the repo.
106+
Because of that, .env.local` can be used to store secrets.
49107
50-
![thinking meme face](https://gitlab.com/kachkaev/website/uploads/a416ccf87b7a1cd2e2bb386f8109f936/thinking.png)
108+
1. Start Next.js in development mode:
109+
110+
```sh
111+
pnpm dev
112+
```
113+
114+
This will start the Next.js dev server on `http://localhost:3000`.
115+
Modifying source files will refresh the app.
116+
To stop running the dev server, press `ctrl+c`.
117+
118+
1. If you want to try out a production copy of the app, build and run it like this:
119+
120+
```sh
121+
pnpm build
122+
pnpm start
123+
```
124+
125+
### Updating profile infos
126+
127+
If you want to try updating profiles locally, you will need to set `UPDATE_PROFILE_SECURITY_TOKEN` in `.env.local`.
128+
129+
TODO
130+
131+
### Playing with i18n
132+
133+
TODO
134+
135+
## Deployment
51136

52137
TODO describe how to deploy the app
53138

139+
<img src="https://gitlab.com/kachkaev/website/uploads/a416ccf87b7a1cd2e2bb386f8109f936/thinking.png" alt="thinking meme face" width="120" />
140+
54141
### Docker
55142

56143
```sh
@@ -66,7 +153,7 @@ docker run \
66153

67154
### Kubernetes (K8S)
68155

69-
![concentrated meme face](https://gitlab.com/kachkaev/website/uploads/c0799225fbfc40e2c493ed290bc345d1/doing.png)
156+
<img src="https://gitlab.com/kachkaev/website/uploads/c0799225fbfc40e2c493ed290bc345d1/doing.png" alt="concentrated meme face" width="120" />
70157

71158
#### Namespace
72159

@@ -112,7 +199,7 @@ kubectl apply -f k8s/cron-jobs.yaml
112199

113200
All done!
114201

115-
![happy meme face](https://gitlab.com/kachkaev/website/uploads/83aa65c795d488f754a34a4e61d57cfd/done.png)
202+
<img src="https://gitlab.com/kachkaev/website/uploads/83aa65c795d488f754a34a4e61d57cfd/done.png" alt="happy meme face" width="120" />
116203

117204
To manually update the app deployment, this commands can be used:
118205

@@ -157,4 +244,4 @@ If you have questions, feel free to ask me anything by creating a new [GitHub is
157244

158245
The repository is licensed under [BSD-3-Clause license](./LICENSE.md), so you are free to do whatever you want with this stuff!
159246

160-
![thumbs-up meme face](https://gitlab.com/kachkaev/website/uploads/749d5f4679392be346e7e986f2e5e5e1/thumbs-up.png)
247+
<img src="https://gitlab.com/kachkaev/website/uploads/749d5f4679392be346e7e986f2e5e5e1/thumbs-up.png" alt="thumbs-up meme face" width="160" />

0 commit comments

Comments
 (0)