initial commit

This commit is contained in:
2026-06-17 22:37:47 +05:30
commit bc31b2508b
100 changed files with 18050 additions and 0 deletions
+122
View File
@@ -0,0 +1,122 @@
# SoftVowels — project conventions
A monorepo with two apps:
```
apps/web Astro 5 (static site, Tailwind v4)
apps/cms Payload 3 (admin UI + REST/GraphQL)
```
## Package manager
`pnpm` 9. From the repo root:
```bash
pnpm install # install both
pnpm dev # dev:web
pnpm dev:web # Astro only
pnpm dev:cms # Payload only
pnpm build # build:web
pnpm build:cms # build Payload
pnpm typecheck # Astro check
pnpm format # prettier
pnpm format:check # prettier --check
```
## 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 (e.g. `revalidateAstro`)
## 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
```bash
pnpm typecheck # astro check
pnpm format:check
```
There is no separate ESLint run; the project's quality bar is enforced by `astro check` and Prettier.
## Build outputs
- `apps/web/dist/` is bind-mounted into the `web` nginx container (`./apps/web/dist:/usr/share/nginx/html:ro`). The host-side webhook rewrites this folder on demand; the nginx container does not need to be rebuilt.
- `apps/cms/dist/` is built by Payload (Next.js) and runs as the CMS Node process.
## Deploy (homeserver)
1. Copy the repo to `/opt/softvowels` on the server.
2. `cp .env.example .env` and fill in the secrets.
3. `docker compose up -d --build`.
4. In Nginx Proxy Manager add two proxied hosts:
- `softvowels.example``web:80` (force SSL, HSTS)
- `cms.softvowels.example``cms:3000` (force SSL, HSTS)
5. On the host, install the rebuild webhook:
```bash
sudo cp scripts/softvowels-webhook.service /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable --now softvowels-webhook
```
Make sure `REBUILD_TOKEN` in `/etc/systemd/system/softvowels-webhook.service` matches `REVALIDATE_TOKEN` in `.env`.
## Revalidate flow
1. Editor publishes in `/admin`.
2. Payload `afterChange` hook POSTs to `http://host.docker.internal:4321/__revalidate?secret=…&collection=…&op=…`.
3. The host-side Node webhook spawns `scripts/rebuild.sh`, which `git pull`s and runs `pnpm --filter web build`.
4. nginx container now serves the new `apps/web/dist/`.
## Self-hosting fonts
Drop these two files into `apps/web/public/fonts/`:
- `Geist-Variable.woff2` (https://github.com/vercel/geist-font — rename `GeistVF.woff2`)
- `GeistMono-Variable.woff2` (rename `GeistMonoVF.woff2`)
The `@font-face` rules are already declared in `global.css`.
## Environment
Root `.env` (used by `docker compose`):
```
POSTGRES_PASSWORD=
PAYLOAD_SECRET=
REVALIDATE_TOKEN=
WEB_HOSTNAME=
CMS_HOSTNAME=
```
`apps/web/.env`:
```
PUBLIC_SITE_URL=
PUBLIC_PAYLOAD_API=
PAYLOAD_API_INTERNAL=
REVALIDATE_TOKEN=
```
`apps/cms/.env`:
```
PAYLOAD_SECRET=
DATABASE_URI=
PAYLOAD_PUBLIC_SERVER_URL=
SERVER_URL=
CORS_ORIGINS=
ASTRO_REVALIDATE_URL=
ASTRO_REVALIDATE_TOKEN=
```