Files
softvowels-webpage/AGENTS.md
T
2026-06-17 23:58:51 +05:30

4.6 KiB

SoftVowels — project conventions

A monorepo with two apps:

apps/web   Astro 5  (static site, Tailwind v4)
apps/cms   Payload 3 (admin UI + REST/GraphQL, Next.js 15)

Source paths

  • apps/web/src/components/{layout,home,article,category,search,newsletter,ui}/ — components
  • apps/web/src/layouts/ — page layouts
  • apps/web/src/lib/ — Payload client, types, SEO, formatting
  • apps/web/src/styles/global.css (Tailwind v4 @theme tokens) and prose.css
  • apps/web/public/fonts/ — drop Geist-Variable.woff2 + GeistMono-Variable.woff2 here
  • apps/cms/src/collections/ — Payload collections
  • apps/cms/src/hooks/ — Payload hooks
  • apps/cms/src/lib/ — Payload helpers (e.g. withRevalidate)

Code style

  • All component files are .astro single-file components. Frontmatter (between ---) is TypeScript.
  • No comments in code unless explicitly requested.
  • Tailwind v4 tokens live in CSS (@theme in global.css). Do not create a tailwind.config.* file.
  • Use icon (astro-icon) with names like material-symbols:memory. Self-host icon font woff2 under public/icons/material-symbols-outlined.woff2 and wire it via @font-face in global.css (already declared; add the binary file when ready).
  • Prefer border border-border-subtle rounded-md over arbitrary values to stay on the 4px baseline.
  • For code blocks in MDX / Lexical output, the article body uses prose-article (see prose.css).

Lint / typecheck (web app)

cd apps/web
npx astro check
npx prettier --check "src/**/*.{ts,astro,css}"

There is no separate ESLint run; the project's quality bar is enforced by astro check and Prettier.

Local development (optional, not required for homeserver deploy)

If you have Node + pnpm on your dev machine:

pnpm install
pnpm dev:web    # Astro on :4321
pnpm dev:cms    # Payload on :3000

The homeserver deploy does not require Node or pnpm on the host — Docker builds both images from source.

Build outputs

  • apps/web/dist/ is generated by astro build inside the softvowels-web Docker image. Baked into the image at /usr/share/nginx/html/.
  • apps/cms/.next/standalone/ is generated by next build (with output: 'standalone') inside the softvowels-cms Docker image. Baked into the image and run via node server.js.
  • apps/cms/media/ (uploaded files) lives in a named Docker volume (softvowels-cms-uploads), not the image.

Deploy (homeserver, Docker only)

The host needs Docker and Docker Compose v2. Nothing else.

# 1. Get the code on the server
git clone <repo> /opt/softvowels
cd /opt/softvowels

# 2. Configure environment
cp .env.example .env
$EDITOR .env     # fill in POSTGRES_PASSWORD, PAYLOAD_SECRET, hostnames

# 3. Build and start
docker compose up -d --build

# 4. Watch the first boot
docker compose logs -f softvowels-cms
# On first run, Payload prints a one-time URL for creating the admin
# account. Open it, then visit https://cms.softvowels.example/admin.

Updating the site (no webhook yet)

Until the webhook is in place, each site update requires:

cd /opt/softvowels
git pull
docker compose build softvowels-web
docker compose up -d softvowels-web

That's the entire "redeploy" for a content change. The CMS does not need rebuilding for content changes — only the web image.

Nginx Proxy Manager setup

Add two proxied hosts in NPM:

Domain Forward to Notes
softvowels.example softvowels-web:80 (http) Force SSL, HSTS, HTTP/2, websockets off
cms.softvowels.example softvowels-cms:3000 (http) Force SSL, HSTS, websockets on (Payload admin uses them)

NPM must be able to resolve softvowels-web and softvowels-cms. The nginx_proxy_manager network is external: true in docker-compose.yml; the easiest way to make NPM see the containers is to run NPM on the same host and add the network to its container with:

docker network connect nginx_proxy_manager <npm-container-name>

Self-hosting fonts

Drop these two files into apps/web/public/fonts/ (before docker compose build):

The @font-face rules are already declared in global.css.

Environment

Root .env (used by docker compose):

POSTGRES_PASSWORD=
PAYLOAD_SECRET=
WEB_HOSTNAME=        # e.g. softvowels.example
CMS_HOSTNAME=        # e.g. cms.softvowels.example

REVALIDATE_TOKEN was removed when the webhook was deferred. Re-add it to .env and docker-compose.yml when the on-publish rebuild is wired back in.