diff --git a/docs/astro.config.ts b/docs/astro.config.ts
index 2a446f01..67877f66 100644
--- a/docs/astro.config.ts
+++ b/docs/astro.config.ts
@@ -11,6 +11,7 @@ import sitemap from "@astrojs/sitemap";
import { llmsTxtPostProcess } from "./src/integrations/llms-txt-post-process";
import config from "./src/config/config.json";
+import { sidebarGroups } from "./src/config/sidebar-groups";
// https://astro.build/config
export default defineConfig({
@@ -120,72 +121,24 @@ export default defineConfig({
Footer: "./src/components/starlight/Footer.astro",
SiteTitle: "./src/components/starlight/SiteTitle.astro",
},
- sidebar: [
- {
- label: "Getting Started",
- collapsed: true,
- autogenerate: { directory: "docs/getting-started" },
- },
- {
- label: "Screenshots & Recordings",
- collapsed: true,
- items: [
- { slug: "docs/features/capturing/screenshots" },
- { slug: "docs/features/capturing/recordings" },
- { slug: "docs/features/capturing/floating-thumbnail" },
- { slug: "docs/features/capturing/app-store-connect-optimization" },
- { slug: "docs/features/capturing/touch-indicators" },
- { slug: "docs/features/capturing/120-fps-recordings" },
- ],
- },
- {
- label: "Simulator Camera",
- link: "/docs/features/capturing/simulator-camera-support",
- },
- {
- label: "Status Bar",
- link: "/docs/features/capturing/statusbar-appearance",
- },
- {
- label: "Design Comparison",
- collapsed: true,
- autogenerate: { directory: "docs/features/design-comparison" },
- },
- {
- label: "App Actions",
- collapsed: true,
- autogenerate: { directory: "docs/features/app-actions" },
- },
- {
- label: "Networking",
- collapsed: true,
- autogenerate: { directory: "docs/features/networking" },
- },
- {
- label: "Build Insights",
- collapsed: true,
- autogenerate: { directory: "docs/features/build-insights" },
- },
- {
- label: "Accessibility",
- collapsed: true,
- autogenerate: { directory: "docs/features/accessibility" },
- },
- {
- label: "User Defaults Editor",
- link: "/docs/features/user-defaults-editor",
- },
- {
- label: "Settings",
- collapsed: true,
- autogenerate: { directory: "docs/settings" },
- },
- {
- label: "Support",
- collapsed: true,
- autogenerate: { directory: "docs/support" },
- },
- ],
+ sidebar: sidebarGroups.map((group) => {
+ if (group.directory) {
+ return {
+ label: group.label,
+ collapsed: group.collapsed,
+ autogenerate: { directory: group.directory },
+ };
+ }
+ const slugs = group.slugs!;
+ if (slugs.length === 1) {
+ return { label: group.label, link: `/${slugs[0]}` };
+ }
+ return {
+ label: group.label,
+ collapsed: group.collapsed,
+ items: slugs.map((slug) => ({ slug })),
+ };
+ }),
}),
mdx(),
llmsTxtPostProcess(),
diff --git a/docs/public/llms-ctx.txt b/docs/public/llms-ctx.txt
new file mode 100644
index 00000000..113eb5d7
--- /dev/null
+++ b/docs/public/llms-ctx.txt
@@ -0,0 +1,43 @@
+# RocketSim — Product Context
+
+## What is RocketSim?
+RocketSim is a macOS developer tool that enhances Apple's iOS Simulator with professional-grade features for capturing, debugging, testing, and design validation. It's available on the Mac App Store and used by individual developers and large teams worldwide.
+
+## Who is it for?
+iOS, macOS, watchOS, and visionOS developers who use Xcode and the iOS Simulator for app development and testing.
+
+## Core Feature Areas
+
+### Capturing
+Professional screenshots and recordings with device bezels, custom backgrounds, touch indicators, and App Store Connect optimization. Supports GIF, MP4, and JPEG/PNG formats.
+
+### Networking
+Real-time network traffic monitoring via RocketSim Connect, historical networking insights, and network speed throttling (3G, Edge, airplane mode) for testing poor connectivity.
+
+### App Actions
+Test push notifications, deep links/universal links, location simulation, and privacy permissions without a physical device. Manage everything from a persistent side window.
+
+### Design Comparison
+Overlay design mockups from Figma or Sketch with adjustable opacity. Add grid overlays and rulers. Use the pixel-level magnifier for precise layout verification.
+
+### Accessibility
+Toggle accessibility settings (Dynamic Type, Increase Contrast, Bold Text, Reduce Motion, etc.) from the side window. VoiceOver Navigator visualizes element order and supports keyboard-driven navigation.
+
+### Build Insights
+Track Xcode build counts, durations, and trends. Compare incremental vs. clean builds. Team Build Insights lets teams compare performance across machines and Xcode versions.
+
+### Other
+User Defaults real-time editor, status bar customization, simulator camera support, and configurable keyboard shortcuts.
+
+## Technical Details
+- Platform: macOS (enhances the iOS/watchOS/visionOS Simulator in Xcode)
+- Distribution: Mac App Store (out-of-store distribution available on request — contact support@rocketsim.app)
+- Sandboxed: Yes
+- RocketSim Connect: Local Bonjour-based framework for Simulator-to-RocketSim communication (debug builds only)
+
+## Links
+- Website: https://www.rocketsim.app
+- Documentation: https://www.rocketsim.app/docs
+- GitHub (issues & features): https://github.com/AvdLee/RocketSimApp
+- YouTube: https://www.youtube.com/@rocketsimapp
+- Developer: Antoine van der Lee (https://www.avanderlee.com)
diff --git a/docs/src/config/sidebar-groups.ts b/docs/src/config/sidebar-groups.ts
new file mode 100644
index 00000000..d82a4aed
--- /dev/null
+++ b/docs/src/config/sidebar-groups.ts
@@ -0,0 +1,75 @@
+interface SidebarGroupDef {
+ label: string;
+ collapsed?: boolean;
+ /** For autogenerate groups: directory relative to the content collection root */
+ directory?: string;
+ /** For explicit item/link groups: slug paths relative to the content collection root */
+ slugs?: string[];
+}
+
+export const sidebarGroups: SidebarGroupDef[] = [
+ {
+ label: "Getting Started",
+ collapsed: true,
+ directory: "docs/getting-started",
+ },
+ {
+ label: "Screenshots & Recordings",
+ collapsed: true,
+ slugs: [
+ "docs/features/capturing/screenshots",
+ "docs/features/capturing/recordings",
+ "docs/features/capturing/floating-thumbnail",
+ "docs/features/capturing/app-store-connect-optimization",
+ "docs/features/capturing/touch-indicators",
+ "docs/features/capturing/120-fps-recordings",
+ ],
+ },
+ {
+ label: "Simulator Camera",
+ slugs: ["docs/features/capturing/simulator-camera-support"],
+ },
+ {
+ label: "Status Bar",
+ slugs: ["docs/features/capturing/statusbar-appearance"],
+ },
+ {
+ label: "Design Comparison",
+ collapsed: true,
+ directory: "docs/features/design-comparison",
+ },
+ {
+ label: "App Actions",
+ collapsed: true,
+ directory: "docs/features/app-actions",
+ },
+ {
+ label: "Networking",
+ collapsed: true,
+ directory: "docs/features/networking",
+ },
+ {
+ label: "Build Insights",
+ collapsed: true,
+ directory: "docs/features/build-insights",
+ },
+ {
+ label: "Accessibility",
+ collapsed: true,
+ directory: "docs/features/accessibility",
+ },
+ {
+ label: "User Defaults Editor",
+ slugs: ["docs/features/user-defaults-editor"],
+ },
+ {
+ label: "Settings",
+ collapsed: true,
+ directory: "docs/settings",
+ },
+ {
+ label: "Support",
+ collapsed: true,
+ directory: "docs/support",
+ },
+];
diff --git a/docs/src/integrations/llms-txt-post-process.ts b/docs/src/integrations/llms-txt-post-process.ts
index 6652f0d7..b340baaa 100644
--- a/docs/src/integrations/llms-txt-post-process.ts
+++ b/docs/src/integrations/llms-txt-post-process.ts
@@ -1,10 +1,58 @@
import type { AstroIntegration } from "astro";
-import { readFile, writeFile } from "node:fs/promises";
+import { readFile, readdir, writeFile } from "node:fs/promises";
import { fileURLToPath } from "node:url";
import path from "node:path";
+import { sidebarGroups } from "../config/sidebar-groups";
+import siteConfig from "../config/config.json";
+
+const baseUrl = siteConfig.site.base_url;
+
+interface PageInfo {
+ title: string;
+ slug: string;
+ order: number;
+ groupLabel: string;
+}
+
+const FULL_SYSTEM_HEADER = `
+This is the official documentation for RocketSim, a macOS developer tool that enhances Apple's iOS Simulator.
+
+Product: RocketSim — available on the Mac App Store
+Developer: Antoine van der Lee (https://www.avanderlee.com)
+Website: ${baseUrl}
+Supported platforms: iOS, macOS, watchOS, and visionOS development via the Simulator
+
+Key capabilities:
+- Professional screenshot and video capture with device bezels and App Store Connect optimization
+- Network traffic monitoring and debugging via RocketSim Connect
+- Push notification testing without a physical device
+- Deep link and universal link testing
+- Location simulation with custom coordinates and predefined routes
+- Design comparison with pixel-perfect overlays, grids, and rulers
+- Accessibility testing: Dynamic Type, environment overrides, and VoiceOver Navigator
+- Xcode build insights and team build analytics
+- User Defaults real-time editor
+- Network speed throttling and Simulator airplane mode
+- Privacy permission management (grant, revoke, reset)
+
+Target audience: iOS, macOS, watchOS, and visionOS developers using Xcode and the Simulator.
+`;
+
+const SMALL_SYSTEM_HEADER = `
+This is a compact version of the official documentation for RocketSim, a macOS developer tool that enhances Apple's iOS Simulator with features for capturing, networking, design comparison, accessibility testing, and more.
+
+Product: RocketSim — available on the Mac App Store
+Developer: Antoine van der Lee (https://www.avanderlee.com)
+Website: ${baseUrl}
+Supported platforms: iOS, macOS, watchOS, and visionOS development via the Simulator
+Target audience: iOS, macOS, watchOS, and visionOS developers using Xcode and the Simulator.
+`;
/**
* Post-processes the generated llms-full.txt and llms-small.txt files to:
+ * - Replace the SYSTEM header with an enriched product context block
+ * - Inject an auto-generated table of contents derived from the sidebar config
+ * - Add cross-reference "Related" links between pages in the same sidebar group
* - Remove the home/index page (only contains navigation components)
* - Remove the 404 page
* - Convert components to YouTube links
@@ -14,6 +62,8 @@ import path from "node:path";
* - Convert :::tip/:::note directives to blockquotes (full) or strip them (small)
* - Fix escaped bold-in-link markdown as safety net
* - Differentiate llms-small.txt (strip testimonials, tips, extra whitespace)
+ *
+ * Also enhances llms.txt with a reference to llms-ctx.txt.
*/
export function llmsTxtPostProcess(): AstroIntegration {
return {
@@ -21,6 +71,8 @@ export function llmsTxtPostProcess(): AstroIntegration {
hooks: {
"astro:build:done": async ({ dir }) => {
const outputDir = fileURLToPath(dir);
+ const contentRoot = path.join(process.cwd(), "src/content/docs");
+ const pages = await scanContentPages(contentRoot);
const variants = [
{ file: "llms-full.txt", variant: "full" as const },
@@ -31,24 +83,190 @@ export function llmsTxtPostProcess(): AstroIntegration {
const filePath = path.join(outputDir, file);
try {
let content = await readFile(filePath, "utf-8");
- content = transformLlmsTxt(content, variant);
+ const toc = buildTableOfContents(pages, variant);
+ const relatedLinks = buildRelatedLinks(pages, variant);
+ content = transformLlmsTxt(content, variant, toc, relatedLinks);
await writeFile(filePath, content, "utf-8");
} catch {
// File might not exist, skip
}
}
- // Enhance llms.txt with richer metadata
- const llmsTxtPath = path.join(outputDir, "llms.txt");
- try {
- const buildDate = new Date().toISOString().split("T")[0];
- const enhancedLlmsTxt = `# RocketSim
+ await enhanceLlmsTxtIndex(outputDir);
+ },
+ },
+ };
+}
+
+async function scanContentPages(contentRoot: string): Promise {
+ const pages: PageInfo[] = [];
+
+ for (const group of sidebarGroups) {
+ if (group.directory) {
+ const dirPath = path.join(contentRoot, group.directory);
+ let files: string[];
+ try {
+ files = await readdir(dirPath);
+ } catch {
+ continue;
+ }
+
+ for (const file of files.filter(
+ (f) => f.endsWith(".md") || f.endsWith(".mdx"),
+ )) {
+ const content = await readFile(path.join(dirPath, file), "utf-8");
+ const fm = extractFrontmatter(content);
+ const slug = group.directory + "/" + file.replace(/\.(mdx?)$/, "");
+ pages.push({
+ title: fm.title,
+ slug,
+ order: fm.sidebarOrder ?? 999,
+ groupLabel: group.label,
+ });
+ }
+ } else if (group.slugs) {
+ for (let i = 0; i < group.slugs.length; i++) {
+ const slug = group.slugs[i];
+ const content = await readContentFile(contentRoot, slug);
+ if (!content) continue;
+ const fm = extractFrontmatter(content);
+ pages.push({
+ title: fm.title,
+ slug,
+ order: i,
+ groupLabel: group.label,
+ });
+ }
+ }
+ }
+
+ return pages;
+}
+
+async function readContentFile(
+ contentRoot: string,
+ slug: string,
+): Promise {
+ for (const ext of [".md", ".mdx"]) {
+ try {
+ return await readFile(path.join(contentRoot, slug + ext), "utf-8");
+ } catch {
+ continue;
+ }
+ }
+ return null;
+}
+
+function extractFrontmatter(content: string): {
+ title: string;
+ sidebarOrder?: number;
+} {
+ const fmMatch = content.match(/^---\n([\s\S]*?)\n---/);
+ if (!fmMatch) return { title: "" };
+ const fm = fmMatch[1];
+ const titleMatch = fm.match(/title:\s*"([^"]+)"/);
+ const orderMatch = fm.match(/order:\s*(\d+)/);
+ return {
+ title: titleMatch?.[1] ?? "",
+ sidebarOrder: orderMatch ? parseInt(orderMatch[1]) : undefined,
+ };
+}
+
+function buildTableOfContents(
+ pages: PageInfo[],
+ variant: "full" | "small",
+): string {
+ const groupOrder = sidebarGroups.map((g) => g.label);
+ const grouped = new Map();
+
+ for (const label of groupOrder) {
+ grouped.set(label, []);
+ }
+
+ for (const page of pages) {
+ if (variant === "small" && page.title === "Testimonials") continue;
+ grouped.get(page.groupLabel)?.push(page);
+ }
+
+ let toc = "## Table of Contents\n";
+
+ for (const label of groupOrder) {
+ const groupPages = grouped.get(label);
+ if (!groupPages || groupPages.length === 0) continue;
+
+ groupPages.sort((a, b) => a.order - b.order);
+
+ toc += `\n### ${label}\n`;
+ for (const page of groupPages) {
+ toc += `- ${page.title}\n`;
+ }
+ }
+
+ return toc.trimEnd();
+}
+
+function buildRelatedLinks(
+ pages: PageInfo[],
+ variant: "full" | "small",
+): Record {
+ const filtered =
+ variant === "small"
+ ? pages.filter((p) => p.title !== "Testimonials")
+ : pages;
+ const grouped = new Map();
+ for (const page of filtered) {
+ if (!grouped.has(page.groupLabel)) {
+ grouped.set(page.groupLabel, []);
+ }
+ grouped.get(page.groupLabel)!.push(page);
+ }
+
+ const related: Record = {};
+
+ for (const groupPages of grouped.values()) {
+ if (groupPages.length < 2) continue;
+
+ for (const page of groupPages) {
+ related[page.title] = groupPages
+ .filter((p) => p.slug !== page.slug)
+ .map((p) => `[${p.title}](/${p.slug})`);
+ }
+ }
+
+ return related;
+}
+
+function addRelatedLinks(
+ page: string,
+ relatedLinks: Record,
+): string {
+ const titleMatch = page.match(/^# (.+)/);
+ if (!titleMatch) return page;
+ const title = titleMatch[1].trim();
+
+ const related = relatedLinks[title];
+ if (related && related.length > 0) {
+ return (
+ page.trimEnd() +
+ "\n\n### Related\n" +
+ related.map((r) => `- ${r}`).join("\n") +
+ "\n"
+ );
+ }
+ return page;
+}
+
+async function enhanceLlmsTxtIndex(outputDir: string): Promise {
+ const llmsTxtPath = path.join(outputDir, "llms.txt");
+ try {
+ const buildDate = new Date().toISOString().split("T")[0];
+ const enhancedLlmsTxt = `# RocketSim
> RocketSim is a macOS developer tool that enhances Apple's iOS Simulator with professional-grade features for capturing, debugging, testing, and design validation. Available on the Mac App Store for iOS, macOS, watchOS, and visionOS developers.
Last updated: ${buildDate}
-Website: https://www.rocketsim.app
-Documentation: https://www.rocketsim.app/docs
+Website: ${baseUrl}
+Documentation: ${baseUrl}/docs
GitHub: https://github.com/AvdLee/RocketSimApp
Support: support@rocketsim.app
@@ -62,36 +280,41 @@ Support: support@rocketsim.app
- Xcode build insights and team analytics
- Network speed throttling and Simulator airplane mode
+## Context
+
+- [Product context](${baseUrl}/llms-ctx.txt): concise product overview, feature summary, and technical details for RocketSim
+
## Documentation Sets
-- [Abridged documentation](https://www.rocketsim.app/llms-small.txt): compact version with non-essential content removed
-- [Complete documentation](https://www.rocketsim.app/llms-full.txt): full documentation for RocketSim
+- [Abridged documentation](${baseUrl}/llms-small.txt): compact version with non-essential content removed
+- [Complete documentation](${baseUrl}/llms-full.txt): full documentation for RocketSim
## Quick Start
-- [Getting Started](https://www.rocketsim.app/docs/getting-started/onboarding)
-- [Product Tour](https://www.rocketsim.app/docs/getting-started/product-tour-and-quick-demos)
-- [FAQ](https://www.rocketsim.app/docs/support/faq)
+- [Getting Started](${baseUrl}/docs/getting-started/onboarding)
+- [Product Tour](${baseUrl}/docs/getting-started/product-tour-and-quick-demos)
+- [FAQ](${baseUrl}/docs/support/faq)
## Notes
- All documentation is automatically generated from the same source as the official docs
- The "Last updated" date reflects when the documentation was last built and deployed
`;
- await writeFile(llmsTxtPath, enhancedLlmsTxt, "utf-8");
- } catch {
- // File might not exist
- }
- },
- },
- };
+ await writeFile(llmsTxtPath, enhancedLlmsTxt, "utf-8");
+ } catch {
+ // File might not exist
+ }
}
-function transformLlmsTxt(content: string, variant: "full" | "small"): string {
- // Preserve the header
+function transformLlmsTxt(
+ content: string,
+ variant: "full" | "small",
+ toc: string,
+ relatedLinks: Record,
+): string {
+ // Extract and discard the original header
const systemMatch = content.match(/^([\s\S]*?<\/SYSTEM>\n\n)/);
- const systemHeader = systemMatch?.[1] ?? "";
- const body = systemHeader ? content.slice(systemHeader.length) : content;
+ const body = systemMatch ? content.slice(systemMatch[1].length) : content;
// Split into page sections (each starts with "# Title")
const pages = body.split(/(?=^# )/m);
@@ -111,7 +334,17 @@ function transformLlmsTxt(content: string, variant: "full" | "small"): string {
return true;
});
- let result = systemHeader + filteredPages.join("");
+ // Add cross-reference links to relevant pages
+ const pagesWithRelated = filteredPages.map((page) =>
+ addRelatedLinks(page, relatedLinks),
+ );
+
+ // Assemble with enriched SYSTEM header and TOC
+ const newSystemHeader =
+ variant === "full" ? FULL_SYSTEM_HEADER : SMALL_SYSTEM_HEADER;
+
+ let result =
+ newSystemHeader + "\n\n" + toc + "\n\n" + pagesWithRelated.join("");
// Convert components to markdown links (handles multi-line tags)
result = result.replace(//g, (match) => {
@@ -146,9 +379,9 @@ function transformLlmsTxt(content: string, variant: "full" | "small"): string {
// Convert to blockquotes
result = result.replace(
/^:::(tip|note|caution|danger)\n([\s\S]*?)^:::/gm,
- (_match, type: string, content: string) => {
+ (_match, type: string, contentBlock: string) => {
const label = type.charAt(0).toUpperCase() + type.slice(1);
- const quoted = content
+ const quoted = contentBlock
.trimEnd()
.split("\n")
.map((line) => `> ${line}`)