feat: add Open Graph image generation and SEO metadata

- Introduced `PageSeo` component for managing page metadata for social sharing.
- Created Open Graph image templates using SVG and static fonts for better visual representation.
- Implemented service alert management with functions to check active alerts and format route numbers.
- Added utility functions for generating and watching alert validity.
- Developed a script to generate Open Graph images dynamically based on page content.
- Included tests for service alert functionalities to ensure correctness and reliability.
This commit is contained in:
2026-10-05 13:02:06 +03:00
parent 6460846134
commit 142ec97959
35 changed files with 8226 additions and 4690 deletions

View File

@@ -14,8 +14,39 @@ Departure times use `scheduledTime`. Historical delay is removed from the ETA co
The city and stop menus use the landing’s custom menu style. Long catalogues have search and a bounded scroll area. Stops with the same name share one menu entry; direction chips retain their separate stop IDs and use the API’s stop `description`. Countdown labels show hours and minutes. Menus support keyboard navigation and Escape, and interface animations respect reduced-motion preferences. The homepage FAQ explains the timetable and links to the contribution page.
On touchscreens, opening a menu does not automatically focus search or bring up the keyboard. Tapping search keeps the menu open as the visible viewport changes. Keyboard navigation scrolls only the options, and search text is at least 16px to avoid input zoom on iOS.
For Docker Compose, supply `RIDEBUS_API_KEY` and optionally `RIDEBUS_API_BASE_URL` through the shell environment or a local `.env` file. Environment files are excluded from the image build context. Do not commit credentials.
## Server deployment
Run the landing as a separate Compose project alongside the API and admin panel:
```sh
cp .env.example .env
# Set RIDEBUS_API_KEY in .env without committing the file.
chmod 600 .env
docker compose config --quiet
docker compose up -d --build --wait
docker compose ps
```
The service publishes port 3000 by default. Point the existing reverse proxy for `ridebus.by` at the server or LXC container's IP and port 3000. TLS is handled by that proxy. Compose does not require Traefik or an existing Docker network.
Set `RIDEBUS_PORT` in `.env` to use a different port. Set `RIDEBUS_BIND_ADDRESS` to restrict the listening address; its default is `0.0.0.0` so a reverse proxy in a separate LXC container can reach the site.
The image runs the Next.js standalone server as the `node` user, includes an HTTP health check, and receives the API key only at runtime. Updates use `docker compose up -d --build --wait` from the landing's directory. This only updates the `ridebus-landing` project.
## Open Graph images
`yarn dev` and `yarn build` generate eight 1200 × 630 PNG images before starting Next.js: one for each of the home, contribution, privacy and terms pages in English and Russian. To regenerate only the images, run `yarn generate:og` (or `npm run generate:og`).
Output is written to `public/images/og/{page}-{locale}.png` and is excluded from Git. The Docker build generates and copies it into the standalone image. Each page supplies its own canonical URL, localized Open Graph tags and Twitter large-image card; the image URLs use the production origin `https://ridebus.by`.
Edit the page copy and routes in `lib/social.mjs`, and the layout in `lib/og-template.mjs`. The template reuses the landing's bus logo, stars, rounded cards, blue and purple palette, and Manrope/Caveat typography. Local fonts include Latin and Cyrillic characters, so image generation needs no external requests or browser. Font sources and licenses are in `assets/fonts/og/`.
In-page anchors such as `/#download` use the homepage preview: crawlers do not request the fragment, so separate previews apply to actual page URLs.
## Checks
```sh