`
}
@@ -33,8 +38,7 @@ export function computeRedirects(
const stem = f.replace(/\.md$/, '')
if (isTopLevel && skipStems.has(stem)) continue
const html = f.replace(/\.md$/, '.html')
- const newPath = `${BASE}docs/${stem}`.replace(/\/+/g, '/')
- out[html] = newPath
+ out[html] = TARGET
}
return out
}
@@ -66,7 +70,10 @@ function main() {
// Source-of-truth = the migrated docs/ tree under site/src/content/docs
const docsSrc = join(__dirname, '..', 'src', 'content', 'docs')
const mdFiles = walk(docsSrc)
- const skip = topLevelPageDirs()
+ // index.md would emit public/index.html and shadow the root redirect page
+ // (src/pages/index.astro → the hub marketing URL). Skip it so the root keeps
+ // pointing at marketing rather than the docs index.
+ const skip = topLevelPageDirs().add('index')
const mapped = computeRedirects(mdFiles, skip)
for (const [oldPath, newPath] of Object.entries(mapped)) {
const dest = join(PUBLIC_DIR, oldPath)
diff --git a/site/src/components/Redirect.astro b/site/src/components/Redirect.astro
new file mode 100644
index 0000000..5bf20bb
--- /dev/null
+++ b/site/src/components/Redirect.astro
@@ -0,0 +1,74 @@
+---
+/**
+ * Full-page redirect to the CorvidLabs hub.
+ *
+ * The standalone fledge site has been retired — both its marketing pages and
+ * its docs now live on the CorvidLabs hub. Every route on this site renders
+ * this component so that, however a visitor (or crawler) arrives, they land on
+ * the canonical hub URL.
+ *
+ * Emits, per the retirement plan:
+ * - for immediate browser redirect
+ * - so search engines fold ranking into the hub URL
+ * - a visible "This site has moved to CorvidLabs →" link for no-JS users
+ */
+interface Props {
+ /** Absolute hub URL to redirect to. */
+ to: string
+}
+
+const { to } = Astro.props as Props
+---
+
+
+
+
+
+
+ Moved to CorvidLabs
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/site/src/data/hub.ts b/site/src/data/hub.ts
new file mode 100644
index 0000000..da160aa
--- /dev/null
+++ b/site/src/data/hub.ts
@@ -0,0 +1,9 @@
+/**
+ * Canonical CorvidLabs hub URLs.
+ *
+ * The standalone fledge site has been retired; its marketing and docs are fully
+ * migrated to the CorvidLabs hub. These constants are the redirect targets used
+ * by every route on this (now redirect-only) site.
+ */
+export const HUB_MARKETING = 'https://corvidlabs.github.io/corvidlabs-site/fledge/'
+export const HUB_DOCS = 'https://corvidlabs.github.io/corvidlabs-site/fledge/docs/'
diff --git a/site/src/pages/404.astro b/site/src/pages/404.astro
index 8527465..e034a7f 100644
--- a/site/src/pages/404.astro
+++ b/site/src/pages/404.astro
@@ -1,18 +1,5 @@
---
-import BaseLayout from '../layouts/BaseLayout.astro'
-import Button from '../components/Button.astro'
-const base = import.meta.env.BASE_URL
+import Redirect from '../components/Redirect.astro'
+import { HUB_MARKETING } from '../data/hub'
---
-
-
-
404
-
This page took flight without us.
-
- The page you're looking for doesn't exist (any more). Try the docs or the plugin registry.
-
-
-
-
-
-
-
+
diff --git a/site/src/pages/blog/[...slug].astro b/site/src/pages/blog/[...slug].astro
index acc2cf2..6fae24d 100644
--- a/site/src/pages/blog/[...slug].astro
+++ b/site/src/pages/blog/[...slug].astro
@@ -1,22 +1,11 @@
---
import { getCollection } from 'astro:content'
-import ArticleLayout from '../../layouts/ArticleLayout.astro'
+import Redirect from '../../components/Redirect.astro'
+import { HUB_MARKETING } from '../../data/hub'
export async function getStaticPaths() {
const entries = await getCollection('blog', p => !p.data.draft)
- return entries.map(entry => ({ params: { slug: entry.slug }, props: { entry } }))
+ return entries.map(entry => ({ params: { slug: entry.slug } }))
}
-
-const { entry } = Astro.props
-const { Content } = await entry.render()
-const date = entry.data.date.toLocaleDateString('en-US', { year: 'numeric', month: 'long', day: 'numeric' })
-const meta = `${date} · ${entry.data.author} · ${entry.data.readTime} min read`
---
-
-
-
+
diff --git a/site/src/pages/blog/index.astro b/site/src/pages/blog/index.astro
index b63cbd9..12aee2d 100644
--- a/site/src/pages/blog/index.astro
+++ b/site/src/pages/blog/index.astro
@@ -1,97 +1,5 @@
---
-import { getCollection } from 'astro:content'
-import BaseLayout from '../../layouts/BaseLayout.astro'
-import PostCard from '../../components/PostCard.astro'
-import CategoryTag from '../../components/CategoryTag.astro'
-import plugins from '../../data/plugins.json' with { type: 'json' }
-const base = import.meta.env.BASE_URL
-const posts = (await getCollection('blog', p => !p.data.draft))
- .sort((a, b) => +b.data.date - +a.data.date)
-const featured = posts.find(p => p.data.featured)
-const rest = posts.filter(p => p !== featured)
-const fmt = (d: Date) => d.toLocaleDateString('en-US', { year: 'numeric', month: 'short', day: 'numeric' })
+import Redirect from '../../components/Redirect.astro'
+import { HUB_MARKETING } from '../../data/hub'
---
-
-
-
-
-
-
-
The fledge blog
-
Updates, plugins, and field notes.
-
Release notes, plugin spotlights, workflow deep-dives, and the occasional design rant.
-
-
-
-
-
-
+
diff --git a/site/src/pages/index.astro b/site/src/pages/index.astro
index 4612633..e034a7f 100644
--- a/site/src/pages/index.astro
+++ b/site/src/pages/index.astro
@@ -1,226 +1,5 @@
---
-import BaseLayout from '../layouts/BaseLayout.astro'
-import Badge from '../components/Badge.astro'
-import Button from '../components/Button.astro'
-import Terminal from '../components/Terminal.astro'
-import Pillar from '../components/Pillar.astro'
-import { getCollection } from 'astro:content'
-import plugins from '../data/plugins.json' with { type: 'json' }
-import type { RegistryEntry } from '../../scripts/build-plugin-registry'
-import { VERSION_MINOR } from '../data/version'
-
-const base = import.meta.env.BASE_URL
-const examples = await getCollection('examples', ({ data }) => !data.draft)
-const featuredExamples = examples.sort((a, b) => (a.data.order ?? 99) - (b.data.order ?? 99)).slice(0, 3)
-
-const spotlight = (plugins as RegistryEntry[])
- .filter(p => p.trust_tier === 'official')
- .slice(0, 4)
+import Redirect from '../components/Redirect.astro'
+import { HUB_MARKETING } from '../data/hub'
---
-
-
-
-
-
-
-
- {plugins.length} plugins shipping in {VERSION_MINOR}
-
Get your projects ready to fly.
-
One CLI for the dev loop. Any language. JSON by default. Scaffold, run, ship — without the bash spaghetti.
-
-
-
-
-
Install in a single command: cargo install fledge
-
-
-
-
# nothing → shipped, in three commands
-
$ fledge templates init my-cli -t rust-cli
-
✓ Scaffolded my-cli/
-
$ fledge lanes init
-
✓ fledge.toml: build, test, lint, ci
-
$ fledge lanes run ci
-
✓ build (1.8s)
-
✓ test (24 passed, 0.6s)
-
✓ lint
-
★ ci passed in 12s
-
$
-
-
-
-
-
-
-
-
-
-
{plugins.length}
plugins shipping
official + community
-
6
pillars
scaffold · run · spec · AI · ship · extend
-
∞
languages
Rust, TS, Python, Go, anything
-
1
binary
install, done
-
-
-
-
-
-
-
-
-
Six pillars
-
Everything you need from nothing to shipped, in one binary.
-
Each pillar is a focused subcommand. Plugins extend any of them. Pick what you need.
-
-
- Built-in templates for Rust, TS, Python, Go. Tera placeholders. Community registry.
- Task runner with composable lanes. Parallel/sequential. File watcher built in.
- Specs as constraints. Validate code matches spec. Agent-friendly source of truth.
- Spec-aware ask and review. Works with Claude, Ollama, OpenAI, any provider.
- Branch → commit (AI optional) → push → release → changelog.
- Plugin protocol in any language. {plugins.length} plugins to install. Or write your own.
-
Install fledge and run your first lane in under a minute.
-
- $
- cargo install fledge
-
-
-
-
-
-
-
-
-
-
-
-
+
diff --git a/site/src/pages/plugins/[slug].astro b/site/src/pages/plugins/[slug].astro
index c15f3a9..99b3574 100644
--- a/site/src/pages/plugins/[slug].astro
+++ b/site/src/pages/plugins/[slug].astro
@@ -1,162 +1,18 @@
---
-import { readdirSync, readFileSync, existsSync } from 'node:fs'
+import { readdirSync, existsSync } from 'node:fs'
import { join } from 'node:path'
-import BaseLayout from '../../layouts/BaseLayout.astro'
-import Button from '../../components/Button.astro'
-import type { FullEntry } from '../../../scripts/build-plugin-registry'
-
-// We use process.cwd() (not fileURLToPath(import.meta.url) per the plan) because
-// Astro 5 / Vite transforms .astro files into Vite chunks — import.meta.url then
-// resolves to a /@fs/... chunk path that doesn't reach the source tree. cwd is
-// stable because both `astro dev` and `astro build` are invoked from `site/`.
-const PER_PLUGIN_DIR = join(process.cwd(), 'src', 'data', 'plugins')
+import Redirect from '../../components/Redirect.astro'
+import { HUB_MARKETING } from '../../data/hub'
+// Enumerate the same plugin slugs the live site shipped so each retired plugin
+// URL still builds and redirects to the hub. Per-plugin pages now live on the
+// CorvidLabs hub marketing site.
export async function getStaticPaths() {
const dir = join(process.cwd(), 'src', 'data', 'plugins')
- if (!existsSync(dir)) return [] // (defensive: dir always exists after prebuild populates it; empty array fallback prevents a build hang when running ad-hoc from another directory)
+ if (!existsSync(dir)) return []
return readdirSync(dir)
.filter(f => f.endsWith('.json'))
- .map(f => {
- const slug = f.replace(/\.json$/, '')
- const data = JSON.parse(readFileSync(join(dir, f), 'utf-8')) as FullEntry
- return { params: { slug }, props: { plugin: data } }
- })
+ .map(f => ({ params: { slug: f.replace(/\.json$/, '') } }))
}
-
-const { plugin } = Astro.props as { plugin: FullEntry }
-const tierLabel = plugin.trust_tier.charAt(0).toUpperCase() + plugin.trust_tier.slice(1)
-const base = import.meta.env.BASE_URL
-
-// load related plugins from disk so we have title + description for cards
-const related = plugin.related_slugs
- .map(s => {
- const p = join(PER_PLUGIN_DIR, `${s}.json`)
- return existsSync(p) ? (JSON.parse(readFileSync(p, 'utf-8')) as FullEntry) : null
- })
- .filter((x): x is FullEntry => !!x)
---
-
-
-
-
-