2026-07-19 17:29:33 -07:00
// @ts-check
import { defineConfig } from "astro/config" ;
import starlight from "@astrojs/starlight" ;
2026-08-10 23:27:47 +09:00
import sitemap from "@astrojs/sitemap" ;
2026-07-19 17:29:33 -07:00
import llmsTxt from "starlight-llms-txt" ;
2026-08-10 23:27:47 +09:00
import { execFileSync } from "node:child_process" ;
2026-07-19 17:29:33 -07:00
// docs.beardrive.ai — the public product documentation.
//
// This is a standalone static site, deliberately NOT embedded into the Go
// binary the way the hub frontend (internal/webapp/static) and the cloud
// landing page (cloud/internal/landing/dist) are. Docs change far more often
// than the binary does, and a Pagefind search index has no business shipping
// inside every self-hoster's install. It deploys on its own, on push.
//
// It lives in the OSS repo because that's what it documents: the CLI, the sync
// model, self-hosting. "Edit this page" resolves to something an outside
// contributor can actually open a PR against.
2026-08-10 23:27:47 +09:00
// `lastmod` for the sitemap, from the commit that last touched each page.
//
// The tempting shortcut — stamp every URL with the build time — is worse than
// emitting nothing: a sitemap that reports the whole site changed on every
// deploy teaches Google to disregard its lastmod entirely, and freshness is
// most of what a sitemap is for on a docs site.
//
// Which is also why the shallow check exists. A CI checkout is depth-1 by
// default, and there `git log` attributes every file to the one commit it has
// — the same uniform lie in a different costume. No history, no lastmod.
// (A host that wants these dates must clone with full history:
// actions/checkout needs `fetch-depth: 0`.)
const lastmodBySource = (() => {
const git = (... args ) =>
execFileSync ( "git" , args , { cwd : import . meta . dirname , encoding : "utf8" }). trim ();
try {
if ( git ( "rev-parse" , "--is-shallow-repository" ) === "true" ) return new Map ();
// One `git log` for every page rather than one per page. Newest commit
// first, so the first time a path appears is its last modification.
const log = git ( "log" , "--format=%cI" , "--name-only" , "--relative" , "--" , "src/content/docs" );
const map = new Map ();
let when = "" ;
for ( const line of log . split ( "\n" )) {
if ( ! line ) continue ;
else if ( /^\d{4}-\d\d-\d\dT/ . test ( line )) when = line ;
else if ( ! map . has ( line )) map . set ( line , when );
}
return map ;
} catch {
return new Map (); // built from a tarball, or no git installed — not fatal
}
})();
/** `/reference/cli/` -> the date on `src/content/docs/reference/cli.md`. */
function lastmodFor ( url ) {
const slug = new URL ( url ). pathname . replace ( /^\/|\/$/g , "" ) || "index" ;
for ( const ext of [ ".md" , ".mdx" ]) {
const at = lastmodBySource . get ( `src/content/docs/ ${ slug }${ ext } ` );
if ( at ) return at ;
}
}
2026-07-19 17:29:33 -07:00
export default defineConfig ({
site : "https://docs.beardrive.ai" ,
2026-07-19 20:52:20 -07:00
// The docs were reorganized around the agent-first path; these URLs were
// public and indexed. Astro emits meta-refresh pages for static output —
// real 301s belong in the host config (see README, "Deploying").
redirects : {
"/start/install" : "/manual/install/" ,
"/start/quickstart" : "/manual/setup-by-hand/" ,
"/guides/connect-an-agent" : "/start/setup/" ,
2026-07-30 12:40:47 +09:00
"/manual/skills-and-hooks" : "/manual/hooks/" ,
2026-08-11 19:02:50 -07:00
// Use cases moved to the marketing site, which already published the same
// six pages at the same slugs. They were live and indexed here for a
// month, so every one of them keeps a redirect — off-site, which is
// exactly what a page that is no longer documentation should do.
"/use-cases/team-artifacts" : "https://beardrive.ai/use-cases/team-artifacts" ,
"/use-cases/team-wiki" : "https://beardrive.ai/use-cases/team-wiki" ,
"/use-cases/business-context" : "https://beardrive.ai/use-cases/business-context" ,
"/use-cases/company-brain" : "https://beardrive.ai/use-cases/company-brain" ,
"/use-cases/personal-wiki" : "https://beardrive.ai/use-cases/personal-wiki" ,
"/use-cases/multi-device" : "https://beardrive.ai/use-cases/multi-device" ,
// The one with no counterpart over there yet — land on the index rather
// than a 404 someone else's deploy has to fix.
"/use-cases/shared-skills" : "https://beardrive.ai/use-cases/" ,
2026-07-19 20:52:20 -07:00
},
2026-07-19 17:29:33 -07:00
integrations : [
2026-08-10 23:27:47 +09:00
// Starlight adds @astrojs/sitemap itself, but only when the config hasn't
// already — declaring it here replaces that default rather than doubling
// it, which is the supported way to reach these options. (Starlight's own
// version only sets `i18n`, and this site is single-language.)
sitemap ({ serialize : ( item ) => ({ ... item , lastmod : lastmodFor ( item . url ) }) }),
2026-07-19 17:29:33 -07:00
starlight ({
title : "BearDrive" ,
description :
"Google Drive for AI agents. One shared folder your whole team's agents read and write — real files, synced in seconds, with history, provenance, and share links." ,
logo : { src : "./src/assets/bear.svg" , alt : "BearDrive" },
2026-08-11 19:02:50 -07:00
// The logo is the way back to beardrive.ai. Starlight always points it
// at the docs root, so the link lives in a component override.
components : { SiteTitle : "./src/components/SiteTitle.astro" },
2026-07-19 17:29:33 -07:00
customCss : [ "./src/styles/tokens.gen.css" , "./src/styles/custom.css" ],
social : [
{
icon : "github" ,
label : "GitHub" ,
href : "https://github.com/runbear-io/beardrive" ,
},
],
editLink : {
baseUrl :
"https://github.com/runbear-io/beardrive/edit/main/web/docs/" ,
},
// Docs are the top AI-citation surface for a dev tool, so ship the
// machine-readable index too: /llms.txt and /llms-full.txt.
//
// Convention puts llms.txt at the ROOT domain, not a docs subdomain.
// beardrive.ai/llms.txt should redirect (or proxy) here — that lives in
// the cloud landing, and is the one cross-repo coordination point this
// split introduces.
plugins : [ llmsTxt ()],
sidebar : [
{
2026-07-19 20:52:20 -07:00
// The reading order IS the recommended path, and the recommended path
// is agent-first: nobody should meet `brew install` before they meet
// /beardrive:install. Everything CLI lives under "Manual setup",
// one click away and never on the critical path.
2026-07-19 17:29:33 -07:00
label : "Start here" ,
items : [
{ label : "What is BearDrive?" , slug : "" },
2026-07-19 20:52:20 -07:00
{ label : "Set up with your agent" , slug : "start/setup" },
{ label : "Your first hour" , slug : "start/first-hour" },
2026-07-19 17:29:33 -07:00
],
},
{
// Guides are about working with agents — that's what the product is
// for. Command-by-command CLI detail belongs in Reference.
label : "Working with agents" ,
items : [
{ label : "Shared agent memory" , slug : "guides/shared-agent-memory" },
{ label : "Artifacts and links" , slug : "guides/agent-artifacts" },
{ label : "What agents read" , slug : "guides/what-agents-read" },
{ label : "Scoping the folder" , slug : "guides/scoping" },
],
},
2026-07-19 20:52:20 -07:00
{
// For people who would rather type it, and for machines with no agent
// on them. Same destination, more steps.
label : "Manual setup (optional)" ,
items : [
{ label : "Install the CLI" , slug : "manual/install" },
{ label : "Set up by hand" , slug : "manual/setup-by-hand" },
2026-07-30 12:40:47 +09:00
{ label : "Hooks in detail" , slug : "manual/hooks" },
2026-07-19 20:52:20 -07:00
],
},
2026-07-19 17:29:33 -07:00
{
label : "Self-hosting" ,
items : [
{ label : "Run a hub" , slug : "self-hosting/run-a-hub" },
{ label : "Authentication" , slug : "self-hosting/authentication" },
{ label : "Database" , slug : "self-hosting/database" },
],
},
{
label : "Reference" ,
items : [
{ label : "CLI" , slug : "reference/cli" },
{ label : "Project files" , slug : "reference/project-files" },
{ label : "Hub config" , slug : "reference/hub-config" },
2026-07-23 19:04:05 -07:00
{ label : "Migrate between hubs" , slug : "reference/migration" },
2026-07-19 17:29:33 -07:00
],
},
{
label : "Concepts" ,
2026-07-27 10:41:57 +09:00
items : [
{ label : "How sync works" , slug : "concepts/how-it-works" },
{ label : "Project permissions" , slug : "concepts/permissions" },
],
2026-07-19 17:29:33 -07:00
},
2026-08-11 19:02:50 -07:00
// Off-site, and last on purpose: the sidebar order is the recommended
// path, so nothing that leaves the docs belongs above the docs.
{
label : "More" ,
items : [
{ label : "Use cases" , link : "https://beardrive.ai/use-cases/" },
{ label : "Blog" , link : "https://beardrive.ai/blog/" },
{ label : "GitHub" , link : "https://github.com/runbear-io/beardrive" },
],
},
2026-07-19 17:29:33 -07:00
],
}),
],
});