+ {{ project_name }} +
+ +
+ {{ project_description }}
+
+
+ diff --git a/.gitignore b/.gitignore index 3854de1..64cfe3e 100644 --- a/.gitignore +++ b/.gitignore @@ -218,3 +218,7 @@ __marimo__/ .opencode/ plans/ .repomixignore + +# VIM files +.*.sw? +.*.un~ diff --git a/copier.yaml b/copier.yaml index 4fcd14a..c7f206d 100644 --- a/copier.yaml +++ b/copier.yaml @@ -79,3 +79,4 @@ publish_to_pypi: ############# Tasks ################## _tasks: - "ln -sf AGENTS.md CLAUDE.md" + - "bash -c '[[ -f site-docs/zensical.toml ]] && [[ ! -e zensical.toml ]] && ln -sf site-docs/zensical.toml . || echo No need to link zensical.toml'" diff --git a/template/{% if enable_docs_site %}site-docs{% endif%}/docs/getting-started.md.jinja b/template/{% if enable_docs_site %}site-docs{% endif%}/docs/getting-started.md.jinja new file mode 100644 index 0000000..0443c8b --- /dev/null +++ b/template/{% if enable_docs_site %}site-docs{% endif%}/docs/getting-started.md.jinja @@ -0,0 +1,17 @@ +--- +icon: lucide/rocket +description: {{ project_description }} +tags: + - installation + - quickstart + - presets +--- + +# Getting Started + +## Installation + +```bash +uv tool install {{ repository_name }} +{{ project_name }} --version +``` diff --git a/template/{% if enable_docs_site %}site-docs{% endif%}/docs/index.md b/template/{% if enable_docs_site %}site-docs{% endif%}/docs/index.md new file mode 100644 index 0000000..bec229e --- /dev/null +++ b/template/{% if enable_docs_site %}site-docs{% endif%}/docs/index.md @@ -0,0 +1,6 @@ +--- +icon: lucide/rocket +template: landing.html +--- + +# Home diff --git a/template/{% if enable_docs_site %}site-docs{% endif%}/docs/javascripts/commit-count.js.jinja b/template/{% if enable_docs_site %}site-docs{% endif%}/docs/javascripts/commit-count.js.jinja new file mode 100644 index 0000000..ed0b8c4 --- /dev/null +++ b/template/{% if enable_docs_site %}site-docs{% endif%}/docs/javascripts/commit-count.js.jinja @@ -0,0 +1,46 @@ +/** + * Fetches total commit count from the GitHub API and displays it + * in the #commit-count-badge element on the landing page. + * + * Uses the Link header pagination trick: request 1 commit per page, + * read the last page number from the Link header — that IS the count. + */ + +; (function () { + const GITHUB_REPO = '{{ repository_namespace }}/{{ repository_name }}'; + + function formatCount(n) { + if (n >= 1000) return (n / 1000).toFixed(1).replace(/\.0$/, '') + 'k'; + return String(n); + } + + async function fetchCommitCount() { + const label = document.getElementById('github-commit-count'); + if (!label) return; + + try { + const res = await fetch( + `https://api.github.com/repos/${GITHUB_REPO}/commits?per_page=1`, + { headers: { Accept: 'application/vnd.github+json' } } + ); + if (!res.ok) return; + + const link = res.headers.get('Link') || ''; + const match = link.match(/[?&]page=(\d+)>;\s*rel="last"/); + if (!match) return; + + const total = parseInt(match[1], 10); + label.textContent = `${formatCount(total)} commits`; + } catch (_) { + // Silently fail — label stays with placeholder + } + } + + if (typeof document$ !== 'undefined') { + document$.subscribe(fetchCommitCount); + } else if (document.readyState === 'loading') { + document.addEventListener('DOMContentLoaded', fetchCommitCount); + } else { + fetchCommitCount(); + } +})(); diff --git a/template/{% if enable_docs_site %}site-docs{% endif%}/docs/javascripts/hero-scene.js b/template/{% if enable_docs_site %}site-docs{% endif%}/docs/javascripts/hero-scene.js new file mode 100644 index 0000000..61d780a --- /dev/null +++ b/template/{% if enable_docs_site %}site-docs{% endif%}/docs/javascripts/hero-scene.js @@ -0,0 +1,251 @@ +/** + * Flowing Wave Field — abstract background animation using Three.js. + * + * A grid of particles undulates using layered sine waves, creating an + * organic, ocean-like surface. Particles are orange (#F97316), connections + * are white with low opacity. Mouse movement warps the wave locally. + * + */ + +;(function () { + // ── Bookkeeping for teardown ── + let animationId = null; + let renderer = null; + let mouseMoveHandler = null; + let resizeHandler = null; + + function teardown() { + if (animationId) { + cancelAnimationFrame(animationId); + animationId = null; + } + if (renderer) { + renderer.dispose(); + renderer = null; + } + if (mouseMoveHandler) { + document.removeEventListener('mousemove', mouseMoveHandler); + mouseMoveHandler = null; + } + if (resizeHandler) { + window.removeEventListener('resize', resizeHandler); + resizeHandler = null; + } + } + + function init() { + teardown(); + + const canvas = document.getElementById('hero-canvas'); + if (!canvas) return; + + // ── Scene & Renderer ── + const scene = new THREE.Scene(); + renderer = new THREE.WebGLRenderer({ canvas, alpha: true, antialias: true }); + renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2)); + + // ── Camera — angled top-down for wave perspective ── + const camera = new THREE.PerspectiveCamera( + 60, + window.innerWidth / window.innerHeight, + 1, + 1000 + ); + camera.position.set(0, 120, 200); + camera.lookAt(0, 0, 0); + + // ── Wave grid configuration ── + const COLS = 50; + const ROWS = 50; + const SPACING = 8; + const PARTICLE_COUNT = COLS * ROWS; + + // Center the grid so it looks symmetric + const offsetX = ((COLS - 1) * SPACING) / 2; + const offsetZ = ((ROWS - 1) * SPACING) / 2; + + // ── Create particles (Points) ── + const geometry = new THREE.BufferGeometry(); + const positions = new Float32Array(PARTICLE_COUNT * 3); + + // Initialize flat grid positions + for (let row = 0; row < ROWS; row++) { + for (let col = 0; col < COLS; col++) { + const i = (row * COLS + col) * 3; + positions[i] = col * SPACING - offsetX; // x + positions[i + 1] = 0; // y (will be animated) + positions[i + 2] = row * SPACING - offsetZ; // z + } + } + geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3)); + + // Circle texture for soft round particles + function createCircleTexture() { + const c = document.createElement('canvas'); + c.width = 32; + c.height = 32; + const ctx = c.getContext('2d'); + // Soft radial gradient for glow effect + const grad = ctx.createRadialGradient(16, 16, 0, 16, 16, 16); + grad.addColorStop(0, 'rgba(255, 255, 255, 1)'); + grad.addColorStop(0.4, 'rgba(255, 255, 255, 0.8)'); + grad.addColorStop(1, 'rgba(255, 255, 255, 0)'); + ctx.fillStyle = grad; + ctx.fillRect(0, 0, 32, 32); + const tex = new THREE.Texture(c); + tex.needsUpdate = true; + return tex; + } + + const pointsMaterial = new THREE.PointsMaterial({ + color: 0xF97316, // Orange accent + size: 2.5, + map: createCircleTexture(), + transparent: true, + alphaTest: 0.01, + opacity: 0.9, + depthWrite: false, + blending: THREE.AdditiveBlending + }); + + const points = new THREE.Points(geometry, pointsMaterial); + scene.add(points); + + // ── Connection lines between nearby particles ── + const lineGeometry = new THREE.BufferGeometry(); + // Max possible lines: each particle connects to right + down neighbor + const maxLines = (COLS - 1) * ROWS + COLS * (ROWS - 1); + const linePositions = new Float32Array(maxLines * 6); + lineGeometry.setAttribute( + 'position', + new THREE.BufferAttribute(linePositions, 3).setUsage(THREE.DynamicDrawUsage) + ); + + const lineMaterial = new THREE.LineBasicMaterial({ + color: 0xffffff, // White connections + transparent: true, + opacity: 0.08, + depthWrite: false + }); + + const lines = new THREE.LineSegments(lineGeometry, lineMaterial); + scene.add(lines); + + // ── Mouse tracking ── + const mouse = { x: 9999, y: 9999 }; + mouseMoveHandler = (e) => { + // Normalize mouse to [-1, 1] range relative to canvas + const rect = canvas.parentNode.getBoundingClientRect(); + mouse.x = ((e.clientX - rect.left) / rect.width) * 2 - 1; + mouse.y = -((e.clientY - rect.top) / rect.height) * 2 + 1; + }; + document.addEventListener('mousemove', mouseMoveHandler); + + // ── Resize handler ── + resizeHandler = () => { + const container = canvas.parentNode; + if (!container) return; + const w = container.clientWidth; + const h = container.clientHeight; + renderer.setSize(w, h); + camera.aspect = w / h; + camera.updateProjectionMatrix(); + }; + window.addEventListener('resize', resizeHandler); + resizeHandler(); + + // ── Animation loop ── + const clock = new THREE.Clock(); + + function animate() { + animationId = requestAnimationFrame(animate); + const t = clock.getElapsedTime(); + const pos = points.geometry.attributes.position.array; + + // Project mouse into world space for local wave distortion + const mouseVec = new THREE.Vector3(mouse.x, mouse.y, 0.5); + mouseVec.unproject(camera); + const dir = mouseVec.sub(camera.position).normalize(); + // Intersect with y=0 plane + const dist = -camera.position.y / dir.y; + const mouseWorld = camera.position.clone().add(dir.multiplyScalar(dist)); + + // Update each particle's Y using layered sine waves + for (let row = 0; row < ROWS; row++) { + for (let col = 0; col < COLS; col++) { + const i = (row * COLS + col) * 3; + const x = pos[i]; + const z = pos[i + 2]; + + // Layer 1: primary wave (large, slow) + let y = Math.sin(x * 0.04 + t * 0.8) * 12; + // Layer 2: cross wave (medium, faster) + y += Math.sin(z * 0.06 + t * 1.2) * 8; + // Layer 3: diagonal ripple (detail) + y += Math.sin((x + z) * 0.05 + t * 0.6) * 5; + + // Mouse influence — push wave up near cursor + const dx = x - mouseWorld.x; + const dz = z - mouseWorld.z; + const mouseDist = Math.sqrt(dx * dx + dz * dz); + if (mouseDist < 60) { + const influence = 1 - mouseDist / 60; + y += influence * 20; + } + + pos[i + 1] = y; + } + } + points.geometry.attributes.position.needsUpdate = true; + + // Update connection lines between grid neighbors + const lnPos = lines.geometry.attributes.position.array; + let li = 0; + + for (let row = 0; row < ROWS; row++) { + for (let col = 0; col < COLS; col++) { + const i = (row * COLS + col) * 3; + + // Connect to right neighbor + if (col < COLS - 1) { + const j = (row * COLS + col + 1) * 3; + lnPos[li++] = pos[i]; lnPos[li++] = pos[i + 1]; lnPos[li++] = pos[i + 2]; + lnPos[li++] = pos[j]; lnPos[li++] = pos[j + 1]; lnPos[li++] = pos[j + 2]; + } + // Connect to bottom neighbor + if (row < ROWS - 1) { + const j = ((row + 1) * COLS + col) * 3; + lnPos[li++] = pos[i]; lnPos[li++] = pos[i + 1]; lnPos[li++] = pos[i + 2]; + lnPos[li++] = pos[j]; lnPos[li++] = pos[j + 1]; lnPos[li++] = pos[j + 2]; + } + } + } + + lines.geometry.attributes.position.needsUpdate = true; + lines.geometry.setDrawRange(0, li / 3); + + // Slow rotation for dynamism + scene.rotation.y += 0.0008; + + renderer.render(scene, camera); + } + + animate(); + } + + // ── Hook into Zensical SPA navigation ── + function safeInit() { + if (typeof THREE === 'undefined') return; + init(); + } + + if (typeof document$ !== 'undefined') { + document$.subscribe(safeInit); + } + + if (document.readyState === 'loading') { + document.addEventListener('DOMContentLoaded', safeInit); + } else { + safeInit(); + } +})(); diff --git a/template/{% if enable_docs_site %}site-docs{% endif%}/docs/stylesheets/hero.css b/template/{% if enable_docs_site %}site-docs{% endif%}/docs/stylesheets/hero.css new file mode 100644 index 0000000..c61eb15 --- /dev/null +++ b/template/{% if enable_docs_site %}site-docs{% endif%}/docs/stylesheets/hero.css @@ -0,0 +1,479 @@ +/* ============================================================ + Landing page — Techy / Abstract dark theme for odoo-venv + Typography: JetBrains Mono (code) + IBM Plex Sans (body) + Colors: Dark bg, orange/white accents (Trobz brand) + ============================================================ */ +@import url("https://fonts.googleapis.com/css2?family=IBM+Plex+Sans:wght@300;400;500;600;700&family=JetBrains+Mono:wght@400;500;600;700&display=swap"); + +/* ---------- CSS Custom Properties ---------- */ +:root { + --ov-bg: #111111; + --ov-text: #f5f5f5; + --ov-text-muted: #a3a3a3; + --ov-accent: #f97316; + --ov-accent-glow: rgba(249, 115, 22, 0.4); + --ov-primary: #ea580c; + --ov-surface: rgba(255, 255, 255, 0.06); + --ov-border: rgba(255, 255, 255, 0.12); + --ov-font-mono: "JetBrains Mono", "Fira Code", monospace; + --ov-font-sans: "IBM Plex Sans", system-ui, sans-serif; + + /* Layout */ + --ov-container-width: 1440px; + --ov-split-ratio: 0.9fr 2.1fr; +} + +/* ---------- Fullscreen layout reset (landing only) ---------- */ +body:has(.ov-landing), +body:has(.ov-landing) .md-main__inner, +body:has(.ov-landing) .md-main, +body:has(.ov-landing) .md-content, +body:has(.ov-landing) .md-content__inner { + margin: 0 !important; + padding: 0 !important; + max-width: none !important; + background: var(--ov-bg) !important; + height: 100vh; + overflow: hidden; +} + +/* ---------- Landing wrapper ---------- */ +.ov-landing { + position: relative; + display: flex; + align-items: center; + justify-content: center; + width: 100%; + height: 100vh; + background: var(--ov-bg); + color: var(--ov-text); + overflow: hidden; +} + +/* ---------- Three.js canvas (background) ---------- */ +.ov-landing__canvas { + position: absolute; + inset: 0; + width: 100%; + height: 100%; + z-index: 0; + opacity: 0.6; + pointer-events: none; +} + +/* ══════════════════════════════════════════════════════ + Split layout — left: copy, right: demo + ══════════════════════════════════════════════════════ */ + +.ov-split { + position: relative; + z-index: 1; + display: grid; + grid-template-columns: var(--ov-split-ratio); + align-items: center; + gap: 4rem; + width: 100%; + max-width: var(--ov-container-width); + padding: 0 4rem; +} + +/* ---------- Left column — hero copy ---------- */ +.ov-split__copy { + display: flex; + flex-direction: column; + align-items: flex-start; + gap: 1.5rem; +} + +/* ---------- Right column — demo frame ---------- */ +.ov-split__demo { + display: flex; + align-items: center; + justify-content: center; + animation: ease-out 0.8s both; +} + +/* ---------- GitHub badge ---------- */ +.ov-github-badge { + position: fixed; + top: 1.5rem; + right: 1.5rem; + z-index: 100; + display: flex; + align-items: center; + gap: 0.75rem; + padding: 0.6rem 1.2rem; + background: var(--ov-surface); + border: 1px solid var(--ov-border); + border-radius: 999px; + color: var(--ov-text) !important; + font-family: var(--ov-font-mono); + font-size: 0.85rem; + text-decoration: none; + backdrop-filter: blur(12px); + transition: all 0.2s ease; + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2); +} + +.ov-github-badge:hover { + background: var(--ov-border); + transform: translateY(-2px); + box-shadow: 0 6px 16px rgba(0, 0, 0, 0.3); +} + +/* ---------- Terminal badge ---------- */ +.ov-hero__badge { + display: inline-flex; + align-items: center; + gap: 0.5rem; + padding: 0.5rem 1.25rem; + background: var(--ov-surface); + border: 1px solid var(--ov-border); + border-radius: 999px; + font-family: var(--ov-font-mono); + font-size: 0.875rem; + color: var(--ov-text-muted); + backdrop-filter: blur(8px); + animation: ov-fadeDown 0.6s ease-out both; +} + +.ov-hero__prompt { + color: var(--ov-accent); + font-weight: 600; +} + +.ov-hero__cmd { + color: var(--ov-text); +} + +/* Blinking cursor — CSS only */ +.ov-hero__cursor { + display: inline-block; + width: 2px; + height: 1em; + background: var(--ov-accent); + animation: ov-blink 1s step-end infinite; +} + +/* ---------- Title ---------- */ +.ov-hero__title { + margin: 0 !important; + animation: ov-fadeUp 0.7s ease-out 0.2s both; +} + +.ov-hero__line { + display: block; + font-family: var(--ov-font-mono); + font-weight: 700; + letter-spacing: -0.03em; + line-height: 1.1 !important; + white-space: nowrap; +} + +.ov-hero__line--1 { + font-size: clamp(2.5rem, 6vw, 5rem) !important; + background: linear-gradient(135deg, #fff 0%, #f97316 50%, #ea580c 100%); + -webkit-background-clip: text; + background-clip: text; + -webkit-text-fill-color: transparent; +} + +/* ---------- Subtitle ---------- */ +.ov-hero__subtitle { + font-family: var(--ov-font-sans); + font-size: clamp(0.95rem, 2vw, 1.15rem); + font-weight: 300; + line-height: 1.6; + color: var(--ov-text-muted); + margin: 0; + animation: ov-fadeUp 0.7s ease-out 0.4s both; +} + +.ov-hero__accent { + color: var(--ov-accent); + font-weight: 500; +} + +/* ---------- CTA buttons ---------- */ +.ov-hero__actions { + display: flex; + gap: 1rem; + flex-wrap: wrap; + animation: ov-fadeUp 0.7s ease-out 0.6s both; +} + +.ov-btn { + display: inline-flex; + align-items: center; + gap: 0.5rem; + padding: 0.75rem 1.75rem; + font-family: var(--ov-font-mono); + font-weight: 500; + font-size: 0.9rem; + text-decoration: none; + border-radius: 8px; + cursor: pointer; + transition: all 0.2s ease-out; +} + +.ov-btn__icon { + flex-shrink: 0; +} + +/* Primary — solid accent button */ +.ov-btn--primary { + background: var(--ov-primary); + color: #fff !important; + border: 1px solid transparent; + box-shadow: 0 0 20px rgba(249, 115, 22, 0.3); +} + +.ov-btn--primary:hover { + background: #c2410c; + box-shadow: 0 0 30px rgba(249, 115, 22, 0.5); + transform: translateY(-2px); +} + +/* Ghost — outlined button */ +.ov-btn--ghost { + background: transparent; + color: var(--ov-text) !important; + border: 1px solid var(--ov-border); +} + +.ov-btn--ghost:hover { + background: var(--ov-surface); + border-color: var(--ov-text-muted); + transform: translateY(-2px); +} + +/* ══════════════════════════════════════════════════════ + Terminal / macOS window frame (CSS only) + ══════════════════════════════════════════════════════ */ + +.ov-terminal-frame { + width: 100%; + border-radius: 12px; + background: #1a1a1a; + border: 1px solid var(--ov-border); + box-shadow: + 0 32px 64px rgba(0, 0, 0, 0.6), + 0 0 0 1px rgba(255, 255, 255, 0.04), + 0 0 60px var(--ov-accent-glow); + overflow: hidden; + transition: box-shadow 0.3s ease; +} + +.ov-terminal-frame:hover { + box-shadow: + 0 40px 80px rgba(0, 0, 0, 0.7), + 0 0 0 1px rgba(255, 255, 255, 0.06), + 0 0 90px rgba(249, 115, 22, 0.55); +} + +/* Title bar with traffic lights */ +.ov-terminal-frame__bar { + display: flex; + align-items: center; + gap: 0.5rem; + padding: 0.625rem 1rem; + background: #242424; + border-bottom: 1px solid rgba(255, 255, 255, 0.06); + user-select: none; +} + +/* Traffic-light dots */ +.ov-terminal-frame__dot { + display: block; + width: 12px; + height: 12px; + border-radius: 50%; + flex-shrink: 0; +} + +.ov-terminal-frame__dot--red { + background: #ff5f57; +} + +.ov-terminal-frame__dot--yellow { + background: #ffbd2e; +} + +.ov-terminal-frame__dot--green { + background: #28c941; +} + +.ov-terminal-frame__bar-title { + flex: 1; + text-align: center; + font-family: var(--ov-font-sans); + font-size: 0.75rem; + font-weight: 400; + color: var(--ov-text-muted); + margin-right: calc(3 * 12px + 2 * 0.5rem); + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +.ov-terminal-frame__body { + display: block; + line-height: 0; + background: #0d0d0d; +} + +.ov-terminal-frame__gif { + display: block; + width: 100%; + height: auto; +} + +/* ══════════════════════════════════════════════════════ + Feature highlights (unused currently, kept for future) + ══════════════════════════════════════════════════════ */ + +.ov-hero__features { + display: flex; + gap: 2rem; + flex-wrap: wrap; + margin-top: 0.5rem; + animation: ov-fadeUp 0.7s ease-out 0.8s both; +} + +.ov-feature { + display: flex; + align-items: center; + gap: 0.5rem; + font-family: var(--ov-font-sans); + font-size: 0.875rem; + color: var(--ov-text-muted); +} + +.ov-feature__icon { + color: var(--ov-accent); + flex-shrink: 0; +} + +/* ---------- Animations ---------- */ +@keyframes ov-fadeDown { + from { + opacity: 0; + transform: translateY(-16px); + } + + to { + opacity: 1; + transform: translateY(0); + } +} + +@keyframes ov-fadeUp { + from { + opacity: 0; + transform: translateY(16px); + } + + to { + opacity: 1; + transform: translateY(0); + } +} + +@keyframes ov-blink { + + 0%, + 100% { + opacity: 1; + } + + 50% { + opacity: 0; + } +} + +/* ---------- Reduced motion (accessibility) ---------- */ +@media (prefers-reduced-motion: reduce) { + + .ov-hero__badge, + .ov-hero__title, + .ov-hero__subtitle, + .ov-hero__actions, + .ov-hero__features, + .ov-split__demo { + animation: none !important; + } + + .ov-hero__cursor { + animation: none !important; + opacity: 1; + } + + .ov-btn:hover { + transform: none; + } +} + +/* ---------- Responsive: tablet (≤ 960px) — stack vertically ---------- */ +@media screen and (max-width: 60rem) { + .ov-split { + grid-template-columns: 1fr; + gap: 2.5rem; + padding: 2rem 2rem; + justify-items: center; + overflow-y: auto; + max-height: 100vh; + } + + .ov-split__copy { + align-items: center; + text-align: center; + } + + .ov-hero__actions { + justify-content: center; + } + + .ov-hero__line--1 { + font-size: clamp(2.5rem, 10vw, 4rem) !important; + } + + .ov-terminal-frame { + max-width: 600px; + } + + body:has(.ov-landing), + body:has(.ov-landing) .md-main__inner, + body:has(.ov-landing) .md-main, + body:has(.ov-landing) .md-content, + body:has(.ov-landing) .md-content__inner { + overflow: auto; + height: auto; + } +} + +/* ---------- Responsive: mobile (≤ 480px) ---------- */ +@media screen and (max-width: 30rem) { + .ov-split { + padding: 1.5rem 1.25rem; + gap: 2rem; + } + + .ov-hero__badge { + font-size: 0.75rem; + padding: 0.4rem 1rem; + } + + .ov-hero__actions { + flex-direction: column; + width: 100%; + } + + .ov-btn { + justify-content: center; + width: 100%; + } + + .ov-terminal-frame { + border-radius: 8px; + } +} diff --git a/template/{% if enable_docs_site %}site-docs{% endif%}/docs/stylesheets/site.css b/template/{% if enable_docs_site %}site-docs{% endif%}/docs/stylesheets/site.css new file mode 100644 index 0000000..a8929ee --- /dev/null +++ b/template/{% if enable_docs_site %}site-docs{% endif%}/docs/stylesheets/site.css @@ -0,0 +1,9 @@ +/* ============================================================ + Global site overrides — applied across all pages + ============================================================ */ + +/* Hide the logo + site name in the header, keep search & theme toggle */ +.md-header__button.md-logo, +.md-header__topic { + display: none; +} diff --git a/template/{% if enable_docs_site %}site-docs{% endif%}/overrides/landing.html.jinja b/template/{% if enable_docs_site %}site-docs{% endif%}/overrides/landing.html.jinja new file mode 100644 index 0000000..8edaba9 --- /dev/null +++ b/template/{% if enable_docs_site %}site-docs{% endif%}/overrides/landing.html.jinja @@ -0,0 +1,78 @@ +{% raw %}{% extends "base.html" %} + +{# Hide default MkDocs chrome — we own the full viewport #} +{% block header %}{% endblock %} +{% block footer %}{% endblock %} +{% block tabs %}{% endblock %} +{% block site_nav %}{% endblock %} + +{% block content %}{% endraw %} +
+ {{ project_description }}
+
+
+