init: Astro/Starlight docs site for gr-sarsat-modern

Diátaxis-structured documentation for 406 MHz SARSAT beacon reception:
- Tutorials: signal chain walkthrough
- Guides: antenna setup, message decoding
- Reference: block API, signal format
- Explanation: Cospas-Sarsat system overview

Includes extracted images from official Cospas-Sarsat specifications (LFS).
This commit is contained in:
Ryan Malloy 2026-02-13 05:01:21 -07:00
commit 41114373b9
1068 changed files with 452688 additions and 0 deletions

7
.gitattributes vendored Normal file
View File

@ -0,0 +1,7 @@
*.pdf filter=lfs diff=lfs merge=lfs -text
*.png filter=lfs diff=lfs merge=lfs -text
*.jpg filter=lfs diff=lfs merge=lfs -text
*.jpeg filter=lfs diff=lfs merge=lfs -text
*.gif filter=lfs diff=lfs merge=lfs -text
*.webp filter=lfs diff=lfs merge=lfs -text
*.svg filter=lfs diff=lfs merge=lfs -text

20
.gitignore vendored Normal file
View File

@ -0,0 +1,20 @@
# Dependencies
node_modules/
# Build output
dist/
# Astro
.astro/
# Environment
.env.local
.env.*.local
# IDE
.vscode/
.idea/
# OS
.DS_Store
Thumbs.db

76
Dockerfile Normal file
View File

@ -0,0 +1,76 @@
# syntax=docker/dockerfile:1
# gr-sarsat-modern documentation site
# Multi-stage build for Astro/Starlight
# ─────────────────────────────────────────────────────────────
# Development stage - with hot reload
# ─────────────────────────────────────────────────────────────
FROM node:22-bookworm-slim AS dev
WORKDIR /app
COPY package*.json ./
RUN npm ci
# Source mounted as volume in docker-compose
EXPOSE 4321
ENV HOST=0.0.0.0
ENV ASTRO_TELEMETRY_DISABLED=1
CMD ["npm", "run", "dev", "--", "--host", "0.0.0.0"]
# ─────────────────────────────────────────────────────────────
# Build stage - generate static site
# ─────────────────────────────────────────────────────────────
FROM node:22-bookworm-slim AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
ENV ASTRO_TELEMETRY_DISABLED=1
RUN npm run build
# ─────────────────────────────────────────────────────────────
# Production stage - serve static files with Caddy
# ─────────────────────────────────────────────────────────────
FROM caddy:2-alpine AS prod
COPY --from=builder /app/dist /srv
COPY <<EOF /etc/caddy/Caddyfile
:80 {
root * /srv
file_server
# SPA fallback
try_files {path} /index.html
# Security headers
header {
X-Content-Type-Options nosniff
X-Frame-Options DENY
Referrer-Policy strict-origin-when-cross-origin
}
# Cache static assets
@static {
path *.js *.css *.woff2 *.png *.svg *.jpg *.webp
}
header @static Cache-Control "public, max-age=31536000, immutable"
# Compress
encode gzip zstd
}
EOF
EXPOSE 80
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s \
CMD wget --no-verbose --tries=1 --spider http://127.0.0.1:80/ || exit 1

40
Makefile Normal file
View File

@ -0,0 +1,40 @@
# gr-sarsat-modern Documentation Site
.PHONY: dev prod build logs stop clean install
# Development with hot reload
dev:
docker compose --profile dev up --build
# Production deployment
prod:
docker compose --profile prod up -d --build
# Build images without starting
build:
docker compose --profile dev build
docker compose --profile prod build
# View logs
logs:
docker compose logs -f
# Stop all services
stop:
docker compose --profile dev --profile prod down
# Clean up (remove volumes and images)
clean:
docker compose --profile dev --profile prod down -v --rmi local
# Install dependencies locally (for IDE support)
install:
npm install
# Local dev without Docker
local:
npm run dev
# Build static site locally
static:
npm run build

88
astro.config.mjs Normal file
View File

@ -0,0 +1,88 @@
import { defineConfig } from 'astro/config';
import starlight from '@astrojs/starlight';
import starlightClientMermaid from '@pasqal-io/starlight-client-mermaid';
export default defineConfig({
site: 'https://sarsat.l.supported.systems',
telemetry: false,
devToolbar: { enabled: false },
integrations: [
starlight({
plugins: [starlightClientMermaid()],
title: 'gr-sarsat-modern',
description: 'GNU Radio 3.10+ blocks for decoding Cospas-Sarsat 406 MHz emergency distress beacons',
logo: {
light: './src/assets/sarsat-logo-light.svg',
dark: './src/assets/sarsat-logo-dark.svg',
replacesTitle: false,
},
social: {
github: 'https://git.supported.systems/rf/gr-sarsat-modern',
},
editLink: {
baseUrl: 'https://git.supported.systems/rf/gr-sarsat-modern/edit/main/docs-site/',
},
customCss: ['./src/styles/custom.css'],
// Diataxis-organized sidebar
sidebar: [
{
label: 'Start Here',
items: [
{ label: 'Introduction', slug: '' },
{ label: 'Quick Start', slug: 'quickstart' },
],
},
{
label: 'Tutorials',
autogenerate: { directory: 'tutorials' },
badge: { text: 'Learning', variant: 'tip' },
},
{
label: 'How-To Guides',
autogenerate: { directory: 'guides' },
badge: { text: 'Tasks', variant: 'note' },
},
{
label: 'Reference',
autogenerate: { directory: 'reference' },
badge: { text: 'Info', variant: 'caution' },
},
{
label: 'Explanation',
autogenerate: { directory: 'explanation' },
badge: { text: 'Understanding', variant: 'success' },
},
{
label: 'Cospas-Sarsat System',
collapsed: true,
autogenerate: { directory: 'cospas-sarsat' },
},
],
head: [
{
tag: 'meta',
attrs: {
name: 'theme-color',
content: '#0066cc',
},
},
],
components: {
// Can override components later
},
}),
],
vite: {
server: {
host: '0.0.0.0',
// HMR config only when behind reverse proxy
...(process.env.VITE_HMR_HOST && {
hmr: {
host: process.env.VITE_HMR_HOST,
protocol: 'wss',
clientPort: 443,
},
}),
},
},
});

60
docker-compose.yml Normal file
View File

@ -0,0 +1,60 @@
# gr-sarsat-modern Documentation Site
# Usage:
# Dev: docker compose --profile dev up
# Prod: docker compose --profile prod up -d
services:
# ─────────────────────────────────────────────────────────────
# Development - hot reload with volume mounts
# ─────────────────────────────────────────────────────────────
docs-dev:
profiles: ["dev"]
build:
context: .
target: dev
restart: unless-stopped
networks:
- caddy
volumes:
- ./src:/app/src:ro
- ./public:/app/public:ro
- ./astro.config.mjs:/app/astro.config.mjs:ro
- ./tsconfig.json:/app/tsconfig.json:ro
environment:
- ASTRO_TELEMETRY_DISABLED=1
- VITE_HMR_HOST=${DOMAIN}
labels:
caddy: ${DOMAIN}
caddy.reverse_proxy: "{{upstreams 4321}}"
# WebSocket support for HMR
caddy.reverse_proxy.flush_interval: "-1"
caddy.reverse_proxy.transport: "http"
caddy.reverse_proxy.transport.read_timeout: "0"
caddy.reverse_proxy.transport.write_timeout: "0"
caddy.reverse_proxy.transport.keepalive: "5m"
caddy.reverse_proxy.transport.keepalive_idle_conns: "10"
caddy.reverse_proxy.stream_timeout: "24h"
caddy.reverse_proxy.stream_close_delay: "5s"
# ─────────────────────────────────────────────────────────────
# Production - static site served by embedded Caddy
# ─────────────────────────────────────────────────────────────
docs-prod:
profiles: ["prod"]
build:
context: .
target: prod
restart: unless-stopped
networks:
- caddy
labels:
caddy: ${DOMAIN}
caddy.reverse_proxy: "{{upstreams 80}}"
# Security headers
caddy.header.X-Content-Type-Options: "nosniff"
caddy.header.X-Frame-Options: "DENY"
caddy.header.Referrer-Policy: "strict-origin-when-cross-origin"
networks:
caddy:
external: true

8728
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

18
package.json Normal file
View File

@ -0,0 +1,18 @@
{
"name": "sarsat-docs",
"version": "0.1.0",
"private": true,
"scripts": {
"dev": "astro dev",
"build": "astro build",
"preview": "astro preview"
},
"dependencies": {
"@astrojs/starlight": "^0.32.0",
"@pasqal-io/starlight-client-mermaid": "^0.1.0",
"@types/three": "^0.182.0",
"astro": "^5.0.0",
"sharp": "^0.33.0",
"three": "^0.182.0"
}
}

BIN
public/images/antennas/qfh-406mhz-3d.svg (Stored with Git LFS) Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Some files were not shown because too many files have changed in this diff Show More