Skip to content

Commit 29b70cf

Browse files
authored
feat: Better docs website (#238)
- Nice looking website - Cmd+K search for attributes and text - Create new attribute via UI - Creates a new file in GH from which users can create a PR. - Gonna add a workflow to run generation and commit the generated stuff automatically when adding a label to a PR. - Powered by Astro (static pages) and Svelte (islands for search and attribute creation) 🧡
1 parent f55a9bb commit 29b70cf

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

81 files changed

+4469
-6853
lines changed

.github/workflows/docs.yml

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
name: Deploy Docs
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
workflow_dispatch:
8+
9+
# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
10+
permissions:
11+
contents: read
12+
pages: write
13+
id-token: write
14+
15+
# Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued.
16+
# However, do NOT cancel in-progress runs as we want to allow these production deployments to complete.
17+
concurrency:
18+
group: "pages"
19+
cancel-in-progress: false
20+
21+
jobs:
22+
build:
23+
name: Build Docs
24+
runs-on: ubuntu-latest
25+
steps:
26+
- name: Checkout
27+
uses: actions/checkout@v4
28+
29+
- name: Set up Node
30+
uses: actions/setup-node@v4
31+
with:
32+
node-version-file: "package.json"
33+
34+
- name: Install dependencies
35+
run: yarn install --frozen-lockfile
36+
37+
- name: Build Astro site
38+
working-directory: docs
39+
run: yarn build
40+
41+
- name: Upload artifact
42+
uses: actions/upload-pages-artifact@v3
43+
with:
44+
path: docs/dist
45+
46+
deploy:
47+
name: Deploy to GitHub Pages
48+
needs: build
49+
runs-on: ubuntu-latest
50+
environment:
51+
name: github-pages
52+
url: ${{ steps.deployment.outputs.page_url }}
53+
steps:
54+
- name: Deploy to GitHub Pages
55+
id: deployment
56+
uses: actions/deploy-pages@v4

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,4 +146,7 @@ dist
146146
# Turborepo
147147
.turbo
148148

149+
# Playwright MCP temporary files
150+
.playwright-mcp/
151+
149152
.DS_Store

biome.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"vcs": { "enabled": false, "clientKind": "git", "useIgnoreFile": false },
44
"files": {
55
"ignoreUnknown": false,
6-
"ignore": ["dist/*", "javascript/sentry-conventions/package.json", "rust/*", "python/*", ".claude/*"]
6+
"ignore": ["dist/*", "javascript/sentry-conventions/package.json", "rust/*", "python/*", ".claude/*", ".astro/*"]
77
},
88
"formatter": {
99
"enabled": true,

docs/.gitignore

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# build output
2+
dist/
3+
# generated types
4+
.astro/
5+
6+
# dependencies
7+
node_modules/
8+
9+
# logs
10+
npm-debug.log*
11+
yarn-debug.log*
12+
yarn-error.log*
13+
pnpm-debug.log*
14+
15+
16+
# environment variables
17+
.env
18+
.env.production
19+
20+
# macOS-specific files
21+
.DS_Store
22+
23+
# jetbrains setting folder
24+
.idea/

docs/README.md

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
# Sentry Conventions Documentation
2+
3+
This is the Astro-based documentation site for Sentry Semantic Conventions.
4+
5+
## Features
6+
7+
- **Static Site Generation** - Built with [Astro](https://astro.build) for fast, static pages
8+
- **Instant Search** - cmd+k / ctrl+k search powered by [Pagefind](https://pagefind.app)
9+
- **Type-Safe Content** - Content collections with Zod schema validation
10+
- **Interactive Components** - Svelte components for search and forms
11+
- **Tailwind CSS** - Utility-first CSS framework for styling
12+
- **Attribute Creation** - Form-based attribute creation with GitHub PR integration
13+
14+
## Development
15+
16+
```bash
17+
# Install dependencies (from repo root, docs is a workspace)
18+
yarn install
19+
20+
# Start dev server
21+
yarn workspace docs dev
22+
23+
# Build for production
24+
yarn workspace docs build
25+
26+
# Preview production build
27+
yarn workspace docs preview
28+
```
29+
30+
Or from within the `docs/` directory:
31+
32+
```bash
33+
yarn dev
34+
yarn build
35+
yarn preview
36+
```
37+
38+
## Content Collections
39+
40+
The site reads directly from the `model/` directory in the repository root:
41+
42+
- **Attributes**: `model/attributes/**/*.json` - Span and breadcrumb attribute definitions
43+
- **Names**: `model/name/*.json` - Span name template definitions
44+
45+
Content is validated against Zod schemas matching the JSON schemas in `schemas/`.
46+
47+
## Deployment
48+
49+
The site is automatically deployed to GitHub Pages via the `.github/workflows/docs.yml` workflow:
50+
51+
1. On push to `main`, the workflow builds the Astro site
52+
2. Pagefind generates the search index
53+
3. The `dist/` folder is deployed to GitHub Pages
54+
55+
The site is available at: https://getsentry.github.io/sentry-conventions/
56+
57+
## Adding New Features
58+
59+
### Adding a new page
60+
61+
Create a new `.astro` file in `src/pages/`. The file path determines the URL:
62+
- `src/pages/foo.astro``/sentry-conventions/foo/`
63+
- `src/pages/bar/index.astro``/sentry-conventions/bar/`
64+
65+
### Adding interactive components
66+
67+
For client-side interactivity, create a Svelte component (`.svelte`) and use the `client:load` directive:
68+
69+
```astro
70+
---
71+
import MyComponent from '../components/MyComponent.svelte';
72+
---
73+
74+
<MyComponent client:load />
75+
```
76+
77+
### Styling
78+
79+
The project uses Tailwind CSS with a custom design system:
80+
81+
- **Global styles**: `src/styles/global.css` contains Tailwind directives, base styles, and custom component classes
82+
- **Tailwind config**: `tailwind.config.mjs` defines the design tokens (colors, spacing, etc.)
83+
- **Component styles**: Use Tailwind utility classes in Astro/Svelte components, or Astro's scoped `<style>` blocks for component-specific styles

docs/astro.config.mjs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// @ts-check
2+
import { defineConfig } from 'astro/config';
3+
import svelte from '@astrojs/svelte';
4+
import tailwind from '@astrojs/tailwind';
5+
6+
// https://astro.build/config
7+
export default defineConfig({
8+
integrations: [svelte(), tailwind()],
9+
// Configure for GitHub Pages - the site will be at https://getsentry.github.io/sentry-conventions/
10+
site: 'https://getsentry.github.io',
11+
base: '/sentry-conventions/',
12+
output: 'static',
13+
});

docs/package.json

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
{
2+
"name": "docs",
3+
"license": "MIT",
4+
"type": "module",
5+
"version": "0.0.1",
6+
"scripts": {
7+
"dev": "astro dev",
8+
"build": "astro build && yarn postbuild",
9+
"postbuild": "pagefind --site dist --output-subdir pagefind",
10+
"preview": "astro preview",
11+
"astro": "astro"
12+
},
13+
"dependencies": {
14+
"@astrojs/svelte": "^7.2.5",
15+
"@astrojs/tailwind": "^6.0.2",
16+
"astro": "^5.16.15",
17+
"dompurify": "^3.3.1",
18+
"svelte": "^5.48.1",
19+
"tailwindcss": "^3.4.0"
20+
},
21+
"devDependencies": {
22+
"@types/dompurify": "^3.2.0",
23+
"pagefind": "^1.4.0"
24+
},
25+
"volta": {
26+
"node": "22.15.0",
27+
"yarn": "1.22.22"
28+
}
29+
}

docs/public/.nojekyll

Whitespace-only changes.

docs/public/sentry-glyph.svg

Lines changed: 1 addition & 0 deletions
Loading
Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
---
2+
import PiiBadge from './PiiBadge.astro';
3+
import TypeBadge from './TypeBadge.astro';
4+
import type { Attribute } from '../content.config';
5+
import { parseAttributeId } from '../utils/category';
6+
7+
interface Props {
8+
attribute: Attribute;
9+
id: string;
10+
showCategory?: boolean;
11+
}
12+
13+
const { attribute, id, showCategory = false } = Astro.props;
14+
15+
const { category } = parseAttributeId(id);
16+
const isDeprecated = !!attribute.deprecation;
17+
const anchorId = attribute.key.replace(/\./g, '-').replace(/</g, '').replace(/>/g, '');
18+
const rawJson = JSON.stringify(attribute, null, 2);
19+
---
20+
21+
<article
22+
class:list={[
23+
'attribute-card bg-bg-secondary border border-border rounded-lg p-5 transition-colors duration-fast scroll-mt-24 hover:border-border-light',
24+
{ 'opacity-70 border-dashed hover:opacity-100': isDeprecated }
25+
]}
26+
id={anchorId}
27+
data-pagefind-body
28+
>
29+
<div class="flex flex-wrap items-start justify-between gap-3 mb-3">
30+
<h3 class="flex items-center gap-2 text-base m-0" data-pagefind-meta="title">
31+
<code class="text-base p-0 bg-transparent border-none text-accent" data-pagefind-index-attrs="data-key" data-key={attribute.key}>{attribute.key}</code>
32+
{isDeprecated && <span class="badge badge-deprecated">Deprecated</span>}
33+
</h3>
34+
<div class="flex flex-wrap items-center gap-2">
35+
<TypeBadge type={attribute.type} />
36+
<PiiBadge pii={attribute.pii.key} reason={attribute.pii.reason} />
37+
{attribute.is_in_otel != null && (
38+
<span class="badge badge-otel" title="Defined in OpenTelemetry Semantic Conventions">OTel: {attribute.is_in_otel ? 'True' : 'False'}</span>
39+
)}
40+
{attribute.has_dynamic_suffix && (
41+
<span class="badge badge-dynamic" title="This attribute has a dynamic suffix">Dynamic</span>
42+
)}
43+
{showCategory && (
44+
<a href={`${import.meta.env.BASE_URL}attributes/${category}/`} class="text-xs px-2 py-1 bg-bg-elevated rounded-sm text-text-muted hover:text-accent hover:bg-accent-soft">{category}</a>
45+
)}
46+
</div>
47+
</div>
48+
49+
<p class="text-sm text-text-secondary mb-4 leading-relaxed">{attribute.brief}</p>
50+
51+
<div class="flex flex-col gap-2">
52+
{attribute.pii.reason && (
53+
<div class="flex items-baseline gap-3 text-sm">
54+
<span class="text-text-muted min-w-[100px] flex-shrink-0">PII Reason</span>
55+
<span class="text-text-secondary">{attribute.pii.reason}</span>
56+
</div>
57+
)}
58+
59+
{attribute.example !== undefined && (
60+
<div class="flex items-baseline gap-3 text-sm">
61+
<span class="text-text-muted min-w-[100px] flex-shrink-0">Example</span>
62+
<code class="text-xs mr-1">{typeof attribute.example === 'object' ? JSON.stringify(attribute.example) : String(attribute.example)}</code>
63+
</div>
64+
)}
65+
66+
{attribute.alias && attribute.alias.length > 0 && (
67+
<div class="flex items-baseline gap-3 text-sm">
68+
<span class="text-text-muted min-w-[100px] flex-shrink-0">Aliases</span>
69+
<span class="text-text-secondary">
70+
{attribute.alias.map((a) => <code class="text-xs mr-1">{a}</code>)}
71+
</span>
72+
</div>
73+
)}
74+
75+
{attribute.sdks && attribute.sdks.length > 0 && (
76+
<div class="flex items-baseline gap-3 text-sm">
77+
<span class="text-text-muted min-w-[100px] flex-shrink-0">SDKs</span>
78+
<span class="inline-flex flex-wrap gap-2">
79+
{attribute.sdks.map((sdk) => (
80+
<span class="px-2 py-0.5 bg-bg-elevated border border-border rounded-sm text-xs text-text-secondary">{sdk}</span>
81+
))}
82+
</span>
83+
</div>
84+
)}
85+
86+
{attribute.has_dynamic_suffix && (
87+
<div class="flex items-baseline gap-3 text-sm">
88+
<span class="text-text-muted min-w-[100px] flex-shrink-0">Dynamic Suffix</span>
89+
<span class="text-text-secondary">Yes - the key contains dynamic parts</span>
90+
</div>
91+
)}
92+
93+
{isDeprecated && (
94+
<div class="mt-3 p-3 bg-error/10 rounded-md border-l-[3px] border-error">
95+
{attribute.deprecation?.replacement ? (
96+
<p class="text-sm m-0">Use <code class="text-accent">{attribute.deprecation.replacement}</code> instead.</p>
97+
) : (
98+
<p class="text-sm m-0">No replacement available at this time.</p>
99+
)}
100+
{attribute.deprecation?.reason && (
101+
<p class="mt-2 text-text-muted text-sm m-0">{attribute.deprecation.reason}</p>
102+
)}
103+
{attribute.deprecation?._status && (
104+
<p class="mt-2 text-text-muted text-xs m-0">Status: <code class="text-xs">{attribute.deprecation._status}</code></p>
105+
)}
106+
</div>
107+
)}
108+
</div>
109+
110+
<details class="mt-4 pt-3 border-t border-border group">
111+
<summary class="cursor-pointer list-none flex items-center gap-2 text-sm text-text-muted transition-colors duration-fast hover:text-text-secondary">
112+
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" class="transition-transform duration-fast group-open:rotate-90">
113+
<path d="M9 18l6-6-6-6"/>
114+
</svg>
115+
Raw JSON
116+
</summary>
117+
<div class="relative mt-3">
118+
<button class="copy-btn absolute top-2 right-2 flex items-center gap-1 px-2 py-1 bg-bg-elevated border border-border rounded text-text-muted text-xs cursor-pointer transition-all duration-fast z-10 hover:text-text-secondary hover:border-border-light" type="button" title="Copy JSON">
119+
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
120+
<rect x="9" y="9" width="13" height="13" rx="2" ry="2"/>
121+
<path d="M5 15H4a2 2 0 01-2-2V4a2 2 0 012-2h9a2 2 0 012 2v1"/>
122+
</svg>
123+
<span>Copy</span>
124+
</button>
125+
<pre class="m-0 p-4 pt-10 bg-bg-elevated border border-border rounded-md overflow-x-auto text-xs"><code class="json-code text-text-secondary">{rawJson}</code></pre>
126+
</div>
127+
</details>
128+
</article>
129+
130+
<script>
131+
// Copy button functionality for all attribute cards
132+
document.querySelectorAll('.attribute-card .copy-btn').forEach(copyBtn => {
133+
copyBtn.addEventListener('click', async () => {
134+
const jsonCode = copyBtn.closest('.relative')?.querySelector('.json-code');
135+
const text = jsonCode?.textContent;
136+
if (text) {
137+
await navigator.clipboard.writeText(text);
138+
const span = copyBtn.querySelector('span');
139+
if (span) {
140+
span.textContent = 'Copied!';
141+
setTimeout(() => {
142+
span.textContent = 'Copy';
143+
}, 2000);
144+
}
145+
}
146+
});
147+
});
148+
</script>

0 commit comments

Comments
 (0)