Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 72 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
name: CI

on:
pull_request:
branches: [main]
push:
branches: [main]

permissions:
contents: read

concurrency:
group: ci-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
format:
name: Format
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: pnpm/action-setup@v6
with:
version: 9
- uses: actions/setup-node@v6
with:
node-version: 22
cache: 'pnpm'
- run: pnpm install --frozen-lockfile
- name: Format check (cms)
run: pnpm --filter cms run format:check
- name: Format check (web)
if: ${{ !cancelled() }}
run: pnpm --filter web run format:check

lint:
name: Lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: pnpm/action-setup@v6
with:
version: 9
- uses: actions/setup-node@v6
with:
node-version: 22
cache: 'pnpm'
- run: pnpm install --frozen-lockfile
- name: Lint (cms)
run: pnpm --filter cms run lint
- name: Lint (web)
if: ${{ !cancelled() }}
run: pnpm --filter web run lint

type-check:
name: Type Check
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: pnpm/action-setup@v6
with:
version: 9
- uses: actions/setup-node@v6
with:
node-version: 22
cache: 'pnpm'
- run: pnpm install --frozen-lockfile
- name: Type check (cms)
run: pnpm --filter cms run check
- name: Astro check (web)
if: ${{ !cancelled() }}
run: pnpm --filter web run check
22 changes: 22 additions & 0 deletions .github/workflows/pr-title.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
name: PR Title

on:
pull_request:
types: [opened, edited, synchronize, reopened]

permissions:
pull-requests: read

jobs:
validate:
name: Validate PR Title
runs-on: ubuntu-latest
steps:
- uses: amannn/action-semantic-pull-request@v5
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
scopes: |
web
cms
requireScope: false
4 changes: 3 additions & 1 deletion cms/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,16 @@
"type": "module",
"scripts": {
"build": "cross-env NODE_OPTIONS=--no-deprecation next build",
"check": "cross-env NODE_OPTIONS=--no-deprecation tsc --noEmit",
"dev": "cross-env NODE_OPTIONS=--no-deprecation next dev",
"devsafe": "rm -rf .next && cross-env NODE_OPTIONS=--no-deprecation next dev",
"generate:importmap": "cross-env NODE_OPTIONS=--no-deprecation payload generate:importmap",
"generate:types": "cross-env NODE_OPTIONS=--no-deprecation payload generate:types",
"lint": "cross-env NODE_OPTIONS=--no-deprecation eslint .",
"payload": "cross-env NODE_OPTIONS=--no-deprecation payload",
"start": "cross-env NODE_OPTIONS=--no-deprecation next start",
"format": "prettier --write src"
"format": "prettier --write src",
"format:check": "prettier --check src"
},
"dependencies": {
"@ai-sdk/anthropic": "^3.0.71",
Expand Down
3 changes: 2 additions & 1 deletion web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
"lint": "eslint --config eslint.config.js src",
"preview": "astro preview",
"astro": "astro",
"format": "prettier --write src"
"format": "prettier --write src",
"format:check": "prettier --check src"
},
"dependencies": {
"@astrojs/vercel": "^8.2.0",
Expand Down
4 changes: 2 additions & 2 deletions web/src/cms/getPageData.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import type { CollectionSlug } from 'payload'
import type { Config } from 'cms/src/payload-types'
import { payloadSDK } from './sdk'
import type { Locale } from './types'

/** Fetches a single page document from the CMS. */
export async function getPageData<T>(
collection: CollectionSlug,
collection: keyof Config['collections'],
id: string,
locale: Locale,
options?: { preview?: boolean },
Expand Down
10 changes: 8 additions & 2 deletions web/src/cms/getRedirects.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,17 @@ export async function getRedirects(): Promise<Record<string, RedirectConfig>> {
// the Astro config file, use process.env to access the environment variable instead.
const bypassSecret = process.env.CMS_VERCEL_AUTOMATION_BYPASS_SECRET

// Skip the CMS fetch when credentials are not available (e.g. CI type checks, local dev without CMS).
if (!process.env.CMS_URL || !process.env.CMS_API_KEY) {
console.warn('[getRedirects] CMS_URL or CMS_API_KEY not set — skipping redirects fetch.')
return {}
}

const payloadSDK = new PayloadSDK<Config>({
baseURL: process.env.CMS_URL! + '/api',
baseURL: process.env.CMS_URL + '/api',
baseInit: {
headers: {
Authorization: `api-keys API-Key ${process.env.CMS_API_KEY!}`,
Authorization: `api-keys API-Key ${process.env.CMS_API_KEY}`,
},
},
fetch: (input, init) => fetch(input, addBypassHeader(init, bypassSecret)),
Expand Down
2 changes: 1 addition & 1 deletion web/src/cms/sdk/cachedFetch.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { CMS_VERCEL_AUTOMATION_BYPASS_SECRET } from 'astro:env/server'
import { addBypassHeader } from './bypassHeader'
import { cache } from '../cache'
import { addBypassHeader } from './bypassHeader'

/**
* Creates a cache key from the URL and init options
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
import RichTextLexical from '@jhb.software/astro-payload-richtext-lexical/RichTextLexical.astro'
import type { ResolveInternalLink } from '@jhb.software/astro-payload-richtext-lexical'
import RichTextLexical from '@jhb.software/astro-payload-richtext-lexical/RichTextLexical.astro'
import type { RichTextBlock as RichTextBlockType } from 'cms/src/payload-types'
import { normalizePath } from '../../../utils/normalizePath'
import BlockRenderer from './BlockRenderer.astro'
Expand Down
8 changes: 7 additions & 1 deletion web/src/layout/Layout.astro
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,13 @@ const showCacheButton = import.meta.env.DEV && !preview
{
enableAnalytics && (
<>
<script is:inline id="psbl" data-domain={websiteConfig.domain} src="/js/script.js" async />
<script
is:inline
id="psbl"
data-domain={websiteConfig.domain}
src="/js/script.js"
async
/>
<script
is:inline
set:html={`window.plausible = window.plausible || function() { (window.plausible.q = window.plausible.q || []).push(arguments) }`}
Expand Down
2 changes: 1 addition & 1 deletion web/src/layout/collections/ArticleLayout.astro
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
---
import ArticleTagsList from '@/components/ArticleTagsList.astro'
import RichTextBlock from '@/components/blocks/RichTextBlock/RichTextBlock.astro'
import type { LexicalNode } from '@jhb.software/astro-payload-richtext-lexical'
import BreadcrumbsBlock from '@/components/Breadcrumbs.astro'
import Img from '@/components/Img.astro'
import TableOfContents from '@/components/TableOfContents.astro'
import SectionShell from '@/layout/SectionShell.astro'
import { articleSchema } from '@/schema/article'
import { extractHeadings } from '@/utils/extractHeadings'
import { normalizePath } from '@/utils/normalizePath'
import type { LexicalNode } from '@jhb.software/astro-payload-richtext-lexical'
import { Schema } from 'astro-seo-schema'
import type { Article, Author, Breadcrumbs } from 'cms/src/payload-types'

Expand Down
25 changes: 14 additions & 11 deletions web/src/pages/404.astro
Original file line number Diff line number Diff line change
Expand Up @@ -32,17 +32,20 @@ const isProductionDeployment = VERCEL_ENV === 'production'

{
!preview && isProductionDeployment && (
<script is:inline>
document.addEventListener('DOMContentLoaded', function () {
plausible('404', {
props: {
path: document.location.pathname,
userAgent: navigator.userAgent,
referrer: document.referrer,
}
});
});
</script>
<script
is:inline
set:html={`
document.addEventListener('DOMContentLoaded', function () {
plausible('404', {
props: {
path: document.location.pathname,
userAgent: navigator.userAgent,
referrer: document.referrer,
},
});
});
`}
/>
)
}
</Layout>
52 changes: 27 additions & 25 deletions web/src/pages/[lang]/500.astro
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import type { AstroGlobal } from 'astro'
import { VERCEL_ENV } from 'astro:env/server'
import { House, RefreshCw } from 'lucide-astro'


// NOTE: It is important that the localized 500 pages are static to ensure no DB calls are made when requests
// to non-existing resources come in. This is especially important for handling spam bot requests.

Expand All @@ -34,7 +33,7 @@ const translations = {
'Ein Problem mit der Datenbankverbindung',
],
reloadButton: 'Seite neu laden',
homeButton: 'Zur Startseite'
homeButton: 'Zur Startseite',
},
en: {
title: 'Internal Server Error',
Expand All @@ -45,8 +44,8 @@ const translations = {
'A database connection issue',
],
reloadButton: 'Reload page',
homeButton: 'Go to homepage'
}
homeButton: 'Go to homepage',
},
}

const t = translations[locale]
Expand All @@ -60,7 +59,7 @@ const t = translations[locale]
}}
lang={locale}
>
<section class="boxed flex flex-col items-center gap-8 py-48 text-center max-w-2xl mx-auto">
<section class="boxed mx-auto flex max-w-2xl flex-col items-center gap-8 py-48 text-center">
<svg
xmlns="http://www.w3.org/2000/svg"
width="48"
Expand All @@ -73,24 +72,24 @@ const t = translations[locale]
stroke-linejoin="round"
class="text-red-500"
>
<path d="M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z"/>
<line x1="12" y1="9" x2="12" y2="13"/>
<line x1="12" y1="17" x2="12.01" y2="17"/>
<path
d="M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z"
></path>
<line x1="12" y1="9" x2="12" y2="13"></line>
<line x1="12" y1="17" x2="12.01" y2="17"></line>
</svg>

<h1 class="text-3xl font-bold">{t.title}</h1>

<div class="text-left space-y-4">
<p class="text-lg text-center">{t.description}</p>
<div class="space-y-4 text-left">
<p class="text-center text-lg">{t.description}</p>

<ul class="list-disc list-inside space-y-2 text-gray-700 dark:text-gray-300">
{t.causes.map((cause) => (
<li>{cause}</li>
))}
<ul class="list-inside list-disc space-y-2 text-gray-700 dark:text-gray-300">
{t.causes.map((cause) => <li>{cause}</li>)}
</ul>
</div>

<div class="flex gap-4 flex-wrap justify-center">
<div class="flex flex-wrap justify-center gap-4">
<button
onclick="window.location.reload()"
class:list={[buttonStyles('primary'), 'cursor-pointer']}
Expand All @@ -108,17 +107,20 @@ const t = translations[locale]

{
!preview && isProductionDeployment && (
<script is:inline>
document.addEventListener('DOMContentLoaded', function () {
plausible('500', {
props: {
path: document.location.pathname,
userAgent: navigator.userAgent,
referrer: document.referrer,
}
<script
is:inline
set:html={`
document.addEventListener('DOMContentLoaded', function () {
plausible('500', {
props: {
path: document.location.pathname,
userAgent: navigator.userAgent,
referrer: document.referrer,
},
});
});
});
</script>
`}
/>
)
}
</Layout>
6 changes: 5 additions & 1 deletion web/src/utils/extractHeadings.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
import type { HeadingNode, LexicalNode, TextNode } from '@jhb.software/astro-payload-richtext-lexical'
import type { TocItem } from '@/components/TableOfContents.astro'
import type {
HeadingNode,
LexicalNode,
TextNode,
} from '@jhb.software/astro-payload-richtext-lexical'
import slugifyId from './slugifyId'

export function extractHeadings(nodes: LexicalNode[]): TocItem[] {
Expand Down
Loading