9b6638eb00
Deploy / deploy (push) Successful in 1m13s
Deux courbes partagées dans lib/motion.ts, pour que le CSS et Framer aient le même feeling, et quatre primitives que Tailwind ne sait pas exprimer : reflet de bouton, halo qui suit le curseur, soulignement qui se dessine, secousse d'erreur. Nouveaux composants : Stagger (les collections se distribuent une par une), Spotlight (trouve son parent tout seul, donc les cartes restent des composants serveur), ScrollProgress, BackToTop, Parallax, Spinner, CheckMark. Reveal accepte maintenant une direction. Côté rendu : le trait de nav glisse d'un onglet à l'autre, les cartes se soulèvent, le hero réagit au scroll, les piliers entrent en zig-zag, la lightbox glisse dans le sens demandé et les formulaires répondent. prefers-reduced-motion est respecté partout : Framer coupe via useReducedMotion, le CSS via la media query déjà en place. Le commit embarque aussi la réorganisation des composants par domaine qui était en cours dans l'arbre de travail — les deux étaient trop imbriquées pour être séparées proprement. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
138 lines
5.2 KiB
Markdown
138 lines
5.2 KiB
Markdown
# Highland Games Studio — Website
|
|
|
|
Marketing and devblog site for Highland Games Studio. _Where summits become worlds._
|
|
|
|
Built with **Next.js 16** (App Router), **React 19**, **Tailwind CSS 4** and **Framer Motion**.
|
|
Devblog posts are authored in MDX and rendered with `next-mdx-remote`.
|
|
|
|
## Getting started
|
|
|
|
```bash
|
|
npm install
|
|
npm run dev
|
|
```
|
|
|
|
Open [http://localhost:3000](http://localhost:3000).
|
|
|
|
## Scripts
|
|
|
|
| Command | Description |
|
|
| ------------------ | ---------------------------------------- |
|
|
| `npm run dev` | Start the dev server |
|
|
| `npm run build` | Production build |
|
|
| `npm run start` | Serve the production build |
|
|
| `npm run lint` | Run ESLint |
|
|
|
|
Asset generation scripts (require `sharp`, already a devDependency):
|
|
|
|
```bash
|
|
node scripts/build-favicon.mjs # favicon + app icon from the mountain mark
|
|
node scripts/build-wordmark.mjs # transparent wordmark from "Full Logo.png"
|
|
```
|
|
|
|
## Project structure
|
|
|
|
```text
|
|
app/ Routes, layouts, server actions, metadata (sitemap/robots/feed/OG)
|
|
app/components/ui/ Design-system primitives (Section, SectionHeading, ButtonLink, Logo…)
|
|
app/components/layout/ Navbar, Footer, SocialLinks
|
|
app/components/game/ GameCard, ScreenshotGallery
|
|
app/components/home/ Home hero
|
|
app/components/devblog/ PostList
|
|
app/components/forms/ ContactForm, Newsletter
|
|
content/devblog/ Devblog posts as .mdx (frontmatter: title, date, excerpt, tags, game)
|
|
lib/ Data + helpers (games registry, devblog loader, site config, formatting)
|
|
public/ Static assets (studio logos, game art, hero video)
|
|
scripts/ One-off asset build scripts
|
|
```
|
|
|
|
### Content lives in `lib/`, never in a page
|
|
|
|
- `lib/site.ts` — studio identity, navigation, contact channels, social accounts, brand assets.
|
|
- `lib/games.ts` — the games registry: title, description, genres, key art, banner **and
|
|
screenshots**.
|
|
|
|
Pages read from these. That is what keeps the home page and `/games/[slug]` in sync — the
|
|
featured block, the "From the workshop" gallery and the game page all render the same record.
|
|
|
|
### Design rule: no text over artwork
|
|
|
|
The Emberwild key art is light cream and the in-game captures are bright green, so body text
|
|
laid over them is unreadable at any gradient strength. Cards therefore put the image on one
|
|
panel and the text on a solid `bg-surface` panel; the game page shows the banner alone and
|
|
places the title underneath. Keep it that way when adding new layouts.
|
|
|
|
## Adding a game or new screenshots
|
|
|
|
Drop the files in `public/image/Games/<Game>/`, then add or edit the entry in `lib/games.ts`:
|
|
|
|
```ts
|
|
{
|
|
slug: "emberwild",
|
|
title: "Emberwild",
|
|
status: "in-development", // in-development | coming-soon | released
|
|
tagline: "One readable line.",
|
|
description: "Full pitch, shown in the About block.",
|
|
genres: ["Survival", "Crafting"],
|
|
releaseWindow: "TBA",
|
|
keyArt: "/image/Games/Emberwild/Cover.png", // illustration, shown contained
|
|
banner: "/image/Games/Emberwild/Capture_1.png", // wide in-game shot, page banner
|
|
screenshots: [
|
|
{ src: "/image/Games/Emberwild/Capture_2.png", caption: "Autumn treeline" },
|
|
],
|
|
}
|
|
```
|
|
|
|
The gallery, the home page teaser, `/games`, the sitemap and the JSON-LD all pick it up.
|
|
|
|
## Configuration
|
|
|
|
Copy `.env.example` to `.env.local` and fill in the values.
|
|
|
|
- **Site URL** — set `NEXT_PUBLIC_SITE_URL` per environment (used by metadata, sitemap,
|
|
robots, RSS and JSON-LD). Defaults to `https://highlandgamesstudio.com` — see `lib/site.ts`.
|
|
- **Contact form (Resend)** — the contact form sends email via [Resend](https://resend.com).
|
|
Set `RESEND_API_KEY`, `CONTACT_TO_EMAIL` (who receives messages) and `CONTACT_FROM_EMAIL`
|
|
(sender, must be on a domain verified in Resend). Without these, the form returns a
|
|
friendly error instead of sending. See `app/actions/contact.ts`.
|
|
|
|
## Adding a devblog post
|
|
|
|
Create a file in `content/devblog/`, e.g. `2026-06-01-my-post.mdx`:
|
|
|
|
```mdx
|
|
---
|
|
title: "My post title"
|
|
date: "2026-06-01"
|
|
excerpt: "One-line summary for listings and SEO."
|
|
author: "Highland Games Studio"
|
|
tags: ["devlog"]
|
|
game: "emberwild"
|
|
---
|
|
|
|
Your MDX content here.
|
|
```
|
|
|
|
## Deployment
|
|
|
|
Pushes to `master` deploy to the Hetzner server via the Gitea Actions workflow
|
|
(`.gitea/workflows/deploy.yml`), which SSHes in, pulls, builds, and restarts the
|
|
PM2 process (`highland`, in `/var/www/highland`).
|
|
|
|
Requires these **repo secrets** (Gitea → repo → Settings → Actions → Secrets):
|
|
`SSH_HOST`, `SSH_USER`, `SSH_PORT`, `SSH_PRIVATE_KEY`.
|
|
|
|
Server-side prerequisites (one-time):
|
|
|
|
- A registered Gitea `act_runner` with the `ubuntu-latest` label.
|
|
- `/var/www/highland` is a clone of this repo whose `origin` can pull the **private**
|
|
Gitea repo non-interactively (deploy key or token in the remote URL).
|
|
- Node + `pm2` installed, with the app running as the `highland` process.
|
|
|
|
## Known TODOs
|
|
|
|
See `TODO.md` for the full list. The two blockers are the 84 MB hero video
|
|
(`public/Video/Header_Video.mp4`) and the social links, which are still unpublished
|
|
(`SOCIAL_LINKS` in `lib/site.ts` — entries with `href: null` are hidden rather than
|
|
rendered as dead `#` links).
|