diff --git a/README.md b/README.md index a85136b..5a55be1 100644 --- a/README.md +++ b/README.md @@ -49,7 +49,7 @@ Register the repository in `content-sources.yaml`: sources: - owner: thiagogcm repo: adf4j - slug: adf4j-docs + slug: adf4j order: 0 ``` @@ -74,11 +74,11 @@ During sync, the site validates frontmatter and page order, removes source-owned Cloudflare Workers is both the request entrypoint and the runtime for the few features that need server-side behavior: -| Runtime path | Cloudflare responsibility | Result | -| --- | --- | --- | -| Normal page request | Serve the built site and run server-rendered fragments | Most content remains pre-rendered; dynamic work stays isolated. | -| Scheduled event | Query GitHub every six hours and write the aggregate to KV | Page requests read cached activity data instead of calling GitHub. | -| Cold stats cache | Start a background refresh with the request context | The response can show a fallback without waiting on GitHub. | +| Runtime path | Cloudflare responsibility | Result | +| -------------------------- | ------------------------------------------------------------- | ------------------------------------------------------------------------------------------- | +| Normal page request | Serve the built site and run server-rendered fragments | Most content remains pre-rendered; dynamic work stays isolated. | +| Scheduled event | Query GitHub every six hours and write the aggregate to KV | Page requests read cached activity data instead of calling GitHub. | +| Cold stats cache | Start a background refresh with the request context | The response can show a fallback without waiting on GitHub. | | `/api/confluence-adf.json` | Validate a public Confluence Cloud URL and fetch its ADF body | The browser receives a narrow JSON response, then performs the Markdown conversion locally. | The Worker delegates regular requests to the site runtime. Its scheduled handler refreshes GitHub statistics. The status island reads those statistics from the `GITHUB_STATS` KV namespace, while the Confluence route accepts only HTTPS `*.atlassian.net` wiki page URLs containing a numeric page ID. @@ -87,14 +87,14 @@ This boundary is intentional: content assembly belongs to the build, presentatio ## Working locally -| Command | Purpose | -| --- | --- | -| `npm run dev` | Sync external content, then start the development server. | -| `npm run sync:content` | Rebuild generated content from registered sources. | -| `npm run validate:sources` | Validate sources without writing generated output. | -| `npm run test:content-sync` | Test content normalization and link rewriting. | -| `npm run check` | Type-check the site and Worker integration. | -| `npm run build` | Sync content and produce the deployment build. | +| Command | Purpose | +| --------------------------- | --------------------------------------------------------- | +| `npm run dev` | Sync external content, then start the development server. | +| `npm run sync:content` | Rebuild generated content from registered sources. | +| `npm run validate:sources` | Validate sources without writing generated output. | +| `npm run test:content-sync` | Test content normalization and link rewriting. | +| `npm run check` | Type-check the site and Worker integration. | +| `npm run build` | Sync content and produce the deployment build. | ## Deployment diff --git a/astro.config.mjs b/astro.config.mjs index c0c88c5..fe74856 100644 --- a/astro.config.mjs +++ b/astro.config.mjs @@ -1,11 +1,11 @@ -import { defineConfig, fontProviders } from 'astro/config'; -import cloudflare from '@astrojs/cloudflare'; -import { unified } from '@astrojs/markdown-remark'; -import adf4jWasm from '@nthings.dev/adf4j-wasm/vite'; -import tailwindcss from '@tailwindcss/vite'; +import cloudflare from "@astrojs/cloudflare"; +import { unified } from "@astrojs/markdown-remark"; +import adf4jWasm from "@nthings.dev/adf4j-wasm/vite"; +import tailwindcss from "@tailwindcss/vite"; +import { defineConfig, fontProviders } from "astro/config"; export default defineConfig({ - site: 'https://nthings.dev', + site: "https://nthings.dev", adapter: cloudflare({ platformProxy: { enabled: true }, }), @@ -13,40 +13,40 @@ export default defineConfig({ plugins: [tailwindcss(), adf4jWasm()], }, markdown: { - syntaxHighlight: 'shiki', + syntaxHighlight: "shiki", // Dual themes: light colors inline, dark swapped via --shiki-dark in global.css. shikiConfig: { themes: { - light: 'github-light', - dark: 'github-dark', + light: "github-light", + dark: "github-dark", }, }, processor: unified({ smartypants: { - dashes: 'oldschool', + dashes: "oldschool", }, }), }, prefetch: { prefetchAll: true, - defaultStrategy: 'hover', + defaultStrategy: "hover", }, fonts: [ { provider: fontProviders.google(), - name: 'Inter', - cssVariable: '--font-body', + name: "Inter", + cssVariable: "--font-body", weights: [400, 500, 600, 700], - subsets: ['latin'], - fallbacks: ['system-ui', '-apple-system', 'sans-serif'], + subsets: ["latin"], + fallbacks: ["system-ui", "-apple-system", "sans-serif"], }, { provider: fontProviders.google(), - name: 'JetBrains Mono', - cssVariable: '--font-code', + name: "JetBrains Mono", + cssVariable: "--font-code", weights: [400, 500], - subsets: ['latin'], - fallbacks: ['ui-monospace', 'monospace'], + subsets: ["latin"], + fallbacks: ["ui-monospace", "monospace"], }, ], }); diff --git a/biome.json b/biome.json new file mode 100644 index 0000000..093aeb9 --- /dev/null +++ b/biome.json @@ -0,0 +1,64 @@ +{ + "$schema": "https://biomejs.dev/schemas/2.5.0/schema.json", + "vcs": { + "enabled": true, + "clientKind": "git", + "useIgnoreFile": true + }, + "files": { + "ignoreUnknown": true, + "includes": [ + "src/**", + "!src/**/*.css", + "astro.config.mjs", + "tsconfig.json", + "package.json" + ] + }, + "formatter": { + "enabled": true, + "indentStyle": "space", + "indentWidth": 2, + "lineWidth": 80, + "lineEnding": "lf" + }, + "linter": { + "enabled": true, + "rules": { + "preset": "recommended", + "style": { + "noNonNullAssertion": "off" + } + } + }, + "javascript": { + "formatter": { + "quoteStyle": "double", + "semicolons": "always" + } + }, + "assist": { + "enabled": true, + "actions": { + "source": { + "organizeImports": "on" + } + } + }, + "overrides": [ + { + "includes": [ + "**/*.astro" + ], + "linter": { + "rules": { + "correctness": { + "noUnusedVariables": "off", + "noUnusedImports": "off", + "noUnusedFunctionParameters": "off" + } + } + } + } + ] +} diff --git a/content-sources.yaml b/content-sources.yaml index 00fad30..cbd1c35 100644 --- a/content-sources.yaml +++ b/content-sources.yaml @@ -14,4 +14,3 @@ sources: - owner: thiagogcm repo: helm4j order: 2 - diff --git a/package-lock.json b/package-lock.json index 143ad69..f3f8bcb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,10 +11,10 @@ "@astrojs/cloudflare": "13.7.0", "@nthings.dev/adf4j-wasm": "1.0.2", "astro": "6.4.8", - "chart.js": "^4.5.1", + "chart.js": "4.5.1", "dompurify": "3.4.11", "markdown-it": "14.2.0", - "markdown-it-github-alerts": "^1.0.1", + "markdown-it-github-alerts": "1.0.1", "mermaid": "11.15.0", "prismjs": "1.30.0", "wrangler": "4.103.0" @@ -22,8 +22,10 @@ "devDependencies": { "@astrojs/check": "0.9.9", "@astrojs/markdown-remark": "7.2.0", + "@biomejs/biome": "2.5.0", "@tailwindcss/vite": "4.3.1", - "@types/markdown-it": "^14.1.2", + "@types/markdown-it": "14.1.2", + "@types/node": "24.13.0", "@types/prismjs": "1.26.6", "degit": "3.4.7", "tailwindcss": "4.3.1", @@ -294,6 +296,181 @@ "node": ">=6.9.0" } }, + "node_modules/@biomejs/biome": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@biomejs/biome/-/biome-2.5.0.tgz", + "integrity": "sha512-4kURkd9hAPrdDM3C9n82ycYgx8hvQcW6MjKTEejruj8rK0N8P3OPpdy8BvI8kt3KWY4ycF5XtDOrktetEfhfuw==", + "dev": true, + "license": "MIT OR Apache-2.0", + "bin": { + "biome": "bin/biome" + }, + "engines": { + "node": ">=14.21.3" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/biome" + }, + "optionalDependencies": { + "@biomejs/cli-darwin-arm64": "2.5.0", + "@biomejs/cli-darwin-x64": "2.5.0", + "@biomejs/cli-linux-arm64": "2.5.0", + "@biomejs/cli-linux-arm64-musl": "2.5.0", + "@biomejs/cli-linux-x64": "2.5.0", + "@biomejs/cli-linux-x64-musl": "2.5.0", + "@biomejs/cli-win32-arm64": "2.5.0", + "@biomejs/cli-win32-x64": "2.5.0" + } + }, + "node_modules/@biomejs/cli-darwin-arm64": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-arm64/-/cli-darwin-arm64-2.5.0.tgz", + "integrity": "sha512-Mn3Fwi3SA5fgmfCPqmzpWF2DLZnms3BVAhM088nTnGrTZmHS3wwIjcoZPqpXeNgd3DrrLH6xp8vTLIBuJoZiXw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-darwin-x64": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-x64/-/cli-darwin-x64-2.5.0.tgz", + "integrity": "sha512-rg3VPL5P8mYro6pqlXYXuJWph21slVp3SZtAqWSrkZs40d2gTzYmHF8E/X1iTID25btmNKltNDJ926sqVBp7DQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-linux-arm64": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64/-/cli-linux-arm64-2.5.0.tgz", + "integrity": "sha512-tl+LW8fdD96/xdeWtWwc82LIOc5CoY7N2AsogLTp5R4ECErYt+8Jl/N68ezN9vzSiqPTxw6vjcihoLPYKZHrlw==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-linux-arm64-musl": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64-musl/-/cli-linux-arm64-musl-2.5.0.tgz", + "integrity": "sha512-vQdM4oSGaf7ZNeGO9w5+Y8SBtyser9M6znxYbm7Ec8wInxJu1WiKxFYZW5Auj2d80bcVvefuGGRxoFOE0eee8g==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-linux-x64": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64/-/cli-linux-x64-2.5.0.tgz", + "integrity": "sha512-zpEGf4RQbFEh8Vt7OmavLyyOzRbtcE9osCqrS1kfvt8jDvxwhKXLSf7n0ebr/ov0RJ9ssP+lhs6C8a9WwFvrQA==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-linux-x64-musl": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64-musl/-/cli-linux-x64-musl-2.5.0.tgz", + "integrity": "sha512-+9hIcMngJ+yGUahXqZuZ8CoWKJE9SAZsFsM3QDvXpNsLbXZ9lqVzgBhOk/jTSYkOA0GLP9eu3teukqpLUojHMg==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-win32-arm64": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-arm64/-/cli-win32-arm64-2.5.0.tgz", + "integrity": "sha512-jB0wAvTLI4itx5VidqVUejPQFhRUxiZ9l9FvZ26D5fl6t3qme+ZB4PD3bTSeL1vZ8NI2Rx/zj6H9zcESuGHKGw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-win32-x64": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-x64/-/cli-win32-x64-2.5.0.tgz", + "integrity": "sha512-VT/lF+GId+67j8aDfLkxdxNoVApsPSTbyAtB3jJq0IWTrY77WXfbPfpngxq0bA6JCEv/7k8C9qWjDRKRznDlyw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=14.21.3" + } + }, "node_modules/@braintree/sanitize-url": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/@braintree/sanitize-url/-/sanitize-url-7.1.2.tgz", @@ -3234,6 +3411,16 @@ "@types/unist": "*" } }, + "node_modules/@types/node": { + "version": "24.13.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.13.0.tgz", + "integrity": "sha512-5vtOqGQr4NJKeEzV441FcOi2MeG9UTWq9LqVLGneDdu4vlX17H8kQ2PA2UmNwCUGPVDj4oBjNhS7ReVEIWJJrg==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "undici-types": "~7.18.0" + } + }, "node_modules/@types/prismjs": { "version": "1.26.6", "resolved": "https://registry.npmjs.org/@types/prismjs/-/prismjs-1.26.6.tgz", @@ -7690,6 +7877,13 @@ "node": ">=20.18.1" } }, + "node_modules/undici-types": { + "version": "7.18.2", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.18.2.tgz", + "integrity": "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==", + "devOptional": true, + "license": "MIT" + }, "node_modules/unenv": { "version": "2.0.0-rc.24", "resolved": "https://registry.npmjs.org/unenv/-/unenv-2.0.0-rc.24.tgz", diff --git a/package.json b/package.json index 5a92f53..4754013 100644 --- a/package.json +++ b/package.json @@ -8,6 +8,8 @@ "scripts": { "dev": "astro dev", "check": "astro check", + "lint": "biome check .", + "format": "biome format --write .", "sync:content": "node scripts/sync-content-sources.mjs", "validate:sources": "node scripts/sync-content-sources.mjs --validate-only", "test:content-sync": "node --test \"scripts/content-sources/**/*.test.mjs\"", @@ -22,10 +24,10 @@ "@astrojs/cloudflare": "13.7.0", "@nthings.dev/adf4j-wasm": "1.0.2", "astro": "6.4.8", - "chart.js": "^4.5.1", + "chart.js": "4.5.1", "dompurify": "3.4.11", "markdown-it": "14.2.0", - "markdown-it-github-alerts": "^1.0.1", + "markdown-it-github-alerts": "1.0.1", "mermaid": "11.15.0", "prismjs": "1.30.0", "wrangler": "4.103.0" @@ -33,8 +35,10 @@ "devDependencies": { "@astrojs/check": "0.9.9", "@astrojs/markdown-remark": "7.2.0", + "@biomejs/biome": "2.5.0", "@tailwindcss/vite": "4.3.1", - "@types/markdown-it": "^14.1.2", + "@types/markdown-it": "14.1.2", + "@types/node": "24.13.0", "@types/prismjs": "1.26.6", "degit": "3.4.7", "tailwindcss": "4.3.1", diff --git a/src/components/Adf4jDemo.astro b/src/components/Adf4jDemo.astro index 63ea794..a5f9182 100644 --- a/src/components/Adf4jDemo.astro +++ b/src/components/Adf4jDemo.astro @@ -111,5 +111,5 @@ const EXAMPLE_URL = diff --git a/src/components/DirectoryEntry.astro b/src/components/DirectoryEntry.astro index 98cbf6d..752fa36 100644 --- a/src/components/DirectoryEntry.astro +++ b/src/components/DirectoryEntry.astro @@ -1,6 +1,6 @@ --- -import Icon from "./Icon.astro"; -import type { EntryAction } from "../lib/project-actions"; +import Icon from "@/components/Icon.astro"; +import type { EntryAction } from "@/lib/project-actions"; interface Props { title: string; diff --git a/src/components/Footer.astro b/src/components/Footer.astro index a738faf..8837cf1 100644 --- a/src/components/Footer.astro +++ b/src/components/Footer.astro @@ -1,7 +1,7 @@ --- -import Icon from "./Icon.astro"; -import Logo from "./Logo.astro"; -import { SITE, SOCIAL_LINKS } from "../consts"; +import Icon from "@/components/Icon.astro"; +import Logo from "@/components/Logo.astro"; +import { SITE, SOCIAL_LINKS } from "@/consts"; const year = new Date().getFullYear(); --- diff --git a/src/components/Header.astro b/src/components/Header.astro index 5180738..f779e01 100644 --- a/src/components/Header.astro +++ b/src/components/Header.astro @@ -1,9 +1,9 @@ --- -import Icon from "./Icon.astro"; -import Logo from "./Logo.astro"; -import Tabs from "./Tabs.astro"; -import ThemeToggle from "./ThemeToggle.astro"; -import { SOCIAL_LINKS } from "../consts"; +import Icon from "@/components/Icon.astro"; +import Logo from "@/components/Logo.astro"; +import Tabs from "@/components/Tabs.astro"; +import ThemeToggle from "@/components/ThemeToggle.astro"; +import { SOCIAL_LINKS } from "@/consts"; ---