From a789e2f98c7a14e6b98df75e8d0de0168a23fd04 Mon Sep 17 00:00:00 2001 From: YanceyA Date: Sat, 18 Oct 2025 22:10:38 +1300 Subject: [PATCH 01/24] Inital commit with bulk of Aether overview, architecture, hardware, builds and such. --- content/docs/lib/index.mdx | 88 +++++++++++++++++++++++++++++++++++++- 1 file changed, 86 insertions(+), 2 deletions(-) diff --git a/content/docs/lib/index.mdx b/content/docs/lib/index.mdx index 6963520..5fea6f6 100644 --- a/content/docs/lib/index.mdx +++ b/content/docs/lib/index.mdx @@ -4,5 +4,89 @@ description: The Aether framework for building motion control applications in Ru icon: House --- -## What is Aether? -Aether is a framework for building motion control applications in Rust. It provides a set of components and tools for building motion control applications. +## Overview + +Aether is a Rust-based framework for high‑performance motion control. It is both a set of composable libraries and a host runtime that coordinates real‑time control across heterogeneous devices. The same building blocks power domain solutions like Aether Printer (3D printing) while remaining usable as standalone crates in other robotics and montion control contexts. + +- Libraries compose into applications and can be used independently. +- The system can combine EtherCAT devices, Mesa cards, and “AetherMCU” boards in one installation. +- Components emphasize determinism, tight real‑time loops, and low overhead. + +## Goals + +- Be the obvious choice for robot motion control tasks. +- Meet hard real‑time constraints (e.g., EtherCAT cycle times) while keeping higher‑level logic responsive. +- Enable zero‑copy, low‑overhead interfaces between controller and core. +- Provide modular crates with stable surfaces and compile‑time enforced versioning where linked. +- Support device discoverability and simple configuration of devices through well‑defined descriptors. +- Log relevant metrics to reproduce exact machine state and motion paths. +- To be a modern Rust based etherCAT capable LinuxCNC replacement. + +## Architecture + +- Core and Controller + - Core: hard real‑time. Executes motion schedules and device I/O within strict cycle budgets. + - Controller: soft real‑time. Feeds the core; if it falls behind, the core safely waits for new commands. + - Linking: prefer in‑process linking (controller + core in Rust) to avoid serialization and enable direct data sharing. + +- Planner and Motion Queues + - Planner accepts long sequences (e.g., G‑code), enforces machine limits, and produces motion segments. + - Motion queues flow from planner to core; the core marks execution and exposes how much is committed for replanning. + - Control modes (e.g., position follower) sample from movement queues; the planner can update or replace segments. + +- Interfaces and Versioning + - Keep controller↔core communication low‑overhead; link for compile‑time API guarantees. + - Introduce explicit serialization only when a stable external interface is required. + - Thin controller patterns allow wrappers (e.g., PyO3 or FFI) without compromising real‑time boundaries. + +- Scope and Discoverability + - Keep the real‑time path strictly EtherCAT to limit scope and ensure determinism. + - Integrate non‑real‑time pieces on the controller side. + - Use existing EtherCAT XML descriptors and add higher‑level descriptors when needed; the UI should identify connected hardware and map it to functions. + +### High‑Level Diagram + + CTRL[Controller - soft RT]\n CTRL --> PLAN[Planner + Motion Queue]\n PLAN --> CTRL\n CTRL --> CORE[Core - hard RT]\n CORE --> EC[EtherCAT Network]\n EC --> DEV[AetherMCU / Mesa / EtherCAT Devices]"} /> + +## Hardware & Protocols + +- Device Model + - Treat microcontroller nodes like EtherCAT devices. + - Use a register‑based protocol for MCUs to align with established fieldbus patterns and support protocol evolution. + +- Boards and Drivers + - Focus on a curated set of BSPs (e.g., BTT Kraken, then Octopus) rather than a large hardware matrix. + - Prefer driver “direct mode” where possible; use very high effective microstepping on the device while keeping host communication compact. + +- Packaging and Updates + - Aether Printer is distributable as a packaged binary. + - MCU updates depend on the platform (e.g., DFU on some boards; some EtherCAT devices may not be updated in the field). + - Minimize firmware churn by decoupling host releases from MCU firmware where feasible. + +## Aether Is Not: + +- Tied to vendor lock‑in or C++‑centric stacks. +- Locked into recompiling MCU firmwares in lockstep with host releases; the system should discover and configure compatible devices. +- Aiming for plug‑and‑play on arbitrary boards in early phases; curated BSPs keep complexity in check. +- Chasing the extreme MCU flexibility approach; prioritize predictable, high‑performance hardware compositions. +- On a fixed public timeline; quality and correctness come first. + +## What You Can Build + +Aether is a launchpad for motion‑centric projects — from hobby robots to production‑grade machines. Here are a few ways to put it to work: + +- 3D printers with precision and insight + - Build on Aether Printer to drive multi‑axis printers at high control rates. + - Run drivers in direct modes with very high effective microstepping while keeping host communication compact. + - Capture deterministic logs so you can reproduce exact print states, compare paths, and debug confidently. + +- Robotics, CNC, and pick‑and‑place + - Compose planners and control modes for arms, gantries, and routers. + - Re‑plan motion on the fly when sensors, cameras, or external systems provide late‑arriving inputs. + - Keep hard real‑time in the core while pushing iterative logic to a responsive controller. + +## Where It Fits + +- Aether provides the motion control substrate for robotics and machines that benefit from deterministic timing, EtherCAT networking, and modular composition. +- For 3D printing, Aether Printer integrates these pieces into an end‑to‑end firmware stack. +- Bridging to other ecosystems is possible via modules on the real‑time side without bending the core architecture. From a22694bc040a51fb0624b74ed3c8252d3a018022 Mon Sep 17 00:00:00 2001 From: YanceyA Date: Sun, 19 Oct 2025 09:44:58 +1300 Subject: [PATCH 02/24] Add accordian style FAQ --- content/docs/lib/index.mdx | 75 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/content/docs/lib/index.mdx b/content/docs/lib/index.mdx index 5fea6f6..c22ba17 100644 --- a/content/docs/lib/index.mdx +++ b/content/docs/lib/index.mdx @@ -90,3 +90,78 @@ Aether is a launchpad for motion‑centric projects — from hobby robots to pro - Aether provides the motion control substrate for robotics and machines that benefit from deterministic timing, EtherCAT networking, and modular composition. - For 3D printing, Aether Printer integrates these pieces into an end‑to‑end firmware stack. - Bridging to other ecosystems is possible via modules on the real‑time side without bending the core architecture. + +## Frequently Asked Questions + +
+ What is Aether? How do “Aether Printer” and “AetherMCU” fit in? +

+ Aether is the project and the set of libraries for motion control applications. + Aether Printer is the 3D‑printer firmware built on that base. + AetherMCU is the reference MCU implementation. +

+
+ +
+ How is Aether different from Klipper or Marlin? +

+ Aether draws a hard boundary between host and MCU (both process and license). It favors board‑specific MCU builds over one generic firmware and avoids re‑flashing MCUs in lock‑step with host releases. On the wire, AetherMCU speaks a register‑based (fieldbus‑style) protocol rather than ad‑hoc commands. + Aether is a ground up redesign using current state of the art hardware and software methods. +

+
+ +
+ What hardware will be supported first? +

+ Initial target is the BTT Octopus with TMC5160s for initial release, then broader board coverage. The goal is to ship something that prints well on common, capable hardware and expand from there. +

+
+ +
+ Will I need to update MCU firmware often? +

+ No. Aether explicitly avoids frequent MCU updates tied to host changes. Occasional updates may happen, but device behavior should remain stable across controller versions. +

+
+ +
+ Does Aether require EtherCAT? What’s the communication model? +

+ An AetherMCU instance will be treated like an EtherCAT‑style device: deterministic cycles, register‑mapped IO, and descriptor‑based discovery/config. EtherCAT is first‑class, and bridging modules can be used where needed—no hard lock‑in. +

+
+ +
+ Can I reuse existing Klipper MCUs or accessories within Aether Printer? +

+ Direct reuse of a Klipper MCU isn’t planned. Some accessories that speak Klipper protocols may be bridged or re‑targeted, but the preference is Aether‑native or EtherCAT‑style devices for clean discovery/config and timing guarantees. +

+
+ +
+ What performance targets are you aiming for? +

+ On a Pi 5, the target control cycle is around 500 μs, with room to go lower using kernel/driver tuning. On MCUs, timer hardware (e.g., repetition counters) enables step rates far beyond typical host‑bit‑banged approaches. +

+
+ +
+ How do device discovery and configuration work? Is hot‑plug planned? +

+ Devices describe their resources (EtherCAT‑style). Discovery aims to be robust, but not everything is auto‑detectable—there is always a safe “not detected” fallback with manual configuration. Hot‑plug is planned where feasible; real‑time safety wins if there’s a trade‑off. +

+
+ +
+ Which advanced features are in scope soon? +

+ Real‑time capabilities: resonance compensation, live encoder feedback and lag detection (including extruder), closed‑loop/servo control, and a modern motion planner (aligned with ideas pioneered in Prunt). For 3D printers an MPC temperature control library will ship via a Rust port of the existing Marlin/Klipper work. +

+
+ +
+ When will it be ready? +

+ When it’s good. Near‑term: reach Klipper/Marlin‑parity on targeted hardware; then land the more ambitious features. Quality and correctness drive the schedule. +

+
From 7d2833026dbbc3a874731bdc5884d5384a0d6367 Mon Sep 17 00:00:00 2001 From: Philipp Molitor Date: Sun, 19 Oct 2025 18:08:22 +0200 Subject: [PATCH 03/24] use advanced components --- content/docs/lib/index.mdx | 189 +++++++++++++++---------------------- 1 file changed, 75 insertions(+), 114 deletions(-) diff --git a/content/docs/lib/index.mdx b/content/docs/lib/index.mdx index c22ba17..dd522aa 100644 --- a/content/docs/lib/index.mdx +++ b/content/docs/lib/index.mdx @@ -4,7 +4,20 @@ description: The Aether framework for building motion control applications in Ru icon: House --- -## Overview +import { Callout } from "fumadocs-ui/components/callout"; +import { Cards, Card } from "fumadocs-ui/components/card"; +import { Accordion, Accordions } from 'fumadocs-ui/components/accordion'; + +import { CpuIcon, LightbulbIcon, PackageOpenIcon } from "lucide-react"; + + + ## This documentation is in its very early stages. [!toc] [#alpha-warning] + We are still working on the alpha release of Aether.
+ Expect things to change and break frequently as we continue to develop the project. +
+ + +## Overview [#overview] Aether is a Rust-based framework for high‑performance motion control. It is both a set of composable libraries and a host runtime that coordinates real‑time control across heterogeneous devices. The same building blocks power domain solutions like Aether Printer (3D printing) while remaining usable as standalone crates in other robotics and montion control contexts. @@ -12,7 +25,8 @@ Aether is a Rust-based framework for high‑performance motion control. It is bo - The system can combine EtherCAT devices, Mesa cards, and “AetherMCU” boards in one installation. - Components emphasize determinism, tight real‑time loops, and low overhead. -## Goals + +## Goals [#goals] - Be the obvious choice for robot motion control tasks. - Meet hard real‑time constraints (e.g., EtherCAT cycle times) while keeping higher‑level logic responsive. @@ -22,56 +36,68 @@ Aether is a Rust-based framework for high‑performance motion control. It is bo - Log relevant metrics to reproduce exact machine state and motion paths. - To be a modern Rust based etherCAT capable LinuxCNC replacement. -## Architecture -- Core and Controller - - Core: hard real‑time. Executes motion schedules and device I/O within strict cycle budgets. - - Controller: soft real‑time. Feeds the core; if it falls behind, the core safely waits for new commands. - - Linking: prefer in‑process linking (controller + core in Rust) to avoid serialization and enable direct data sharing. +## Architecture [#architecture] -- Planner and Motion Queues - - Planner accepts long sequences (e.g., G‑code), enforces machine limits, and produces motion segments. - - Motion queues flow from planner to core; the core marks execution and exposes how much is committed for replanning. - - Control modes (e.g., position follower) sample from movement queues; the planner can update or replace segments. +### Core and Controller -- Interfaces and Versioning - - Keep controller↔core communication low‑overhead; link for compile‑time API guarantees. - - Introduce explicit serialization only when a stable external interface is required. - - Thin controller patterns allow wrappers (e.g., PyO3 or FFI) without compromising real‑time boundaries. +- Core: hard real‑time. Executes motion schedules and device I/O within strict cycle budgets. +- Controller: soft real‑time. Feeds the core; if it falls behind, the core safely waits for new commands. +- Linking: prefer in‑process linking (controller + core in Rust) to avoid serialization and enable direct data sharing. -- Scope and Discoverability - - Keep the real‑time path strictly EtherCAT to limit scope and ensure determinism. - - Integrate non‑real‑time pieces on the controller side. - - Use existing EtherCAT XML descriptors and add higher‑level descriptors when needed; the UI should identify connected hardware and map it to functions. +### Planner and Motion Queues -### High‑Level Diagram +- Planner accepts long sequences (e.g., G‑code), enforces machine limits, and produces motion segments. +- Motion queues flow from planner to core; the core marks execution and exposes how much is committed for replanning. +- Control modes (e.g., position follower) sample from movement queues; the planner can update or replace segments. - CTRL[Controller - soft RT]\n CTRL --> PLAN[Planner + Motion Queue]\n PLAN --> CTRL\n CTRL --> CORE[Core - hard RT]\n CORE --> EC[EtherCAT Network]\n EC --> DEV[AetherMCU / Mesa / EtherCAT Devices]"} /> +### Interfaces and Versioning -## Hardware & Protocols +- Keep controller↔core communication low‑overhead; link for compile‑time API guarantees. +- Introduce explicit serialization only when a stable external interface is required. +- Thin controller patterns allow wrappers (e.g., PyO3 or FFI) without compromising real‑time boundaries. -- Device Model - - Treat microcontroller nodes like EtherCAT devices. - - Use a register‑based protocol for MCUs to align with established fieldbus patterns and support protocol evolution. +### Scope and Discoverability -- Boards and Drivers - - Focus on a curated set of BSPs (e.g., BTT Kraken, then Octopus) rather than a large hardware matrix. - - Prefer driver “direct mode” where possible; use very high effective microstepping on the device while keeping host communication compact. +- Keep the real‑time path strictly EtherCAT to limit scope and ensure determinism. +- Integrate non‑real‑time pieces on the controller side. +- Use existing EtherCAT XML descriptors and add higher‑level descriptors when needed; the UI should identify connected hardware and map it to functions. -- Packaging and Updates - - Aether Printer is distributable as a packaged binary. - - MCU updates depend on the platform (e.g., DFU on some boards; some EtherCAT devices may not be updated in the field). - - Minimize firmware churn by decoupling host releases from MCU firmware where feasible. +### High‑Level Diagram [#high-level-diagram] -## Aether Is Not: +```mermaid +flowchart TD + UI[Aether UI] --> CTRL[Controller - soft RT] + CTRL --> PLAN[Planner + Motion Queue] + PLAN --> CTRL + CTRL --> CORE[Core - hard RT] + CORE --> EC[EtherCAT Network] + EC --> ETHERCAT_DEV[EtherCAT Devices] + EC --> MESA[Mesa] + EC --> AETHERMCU[AetherMCU] +``` -- Tied to vendor lock‑in or C++‑centric stacks. -- Locked into recompiling MCU firmwares in lockstep with host releases; the system should discover and configure compatible devices. -- Aiming for plug‑and‑play on arbitrary boards in early phases; curated BSPs keep complexity in check. -- Chasing the extreme MCU flexibility approach; prioritize predictable, high‑performance hardware compositions. -- On a fixed public timeline; quality and correctness come first. -## What You Can Build +## Hardware & Protocols [#hardware-protocols] + + + }> + - Treat microcontroller nodes like EtherCAT devices. + - Use a register‑based protocol for MCUs to align with established fieldbus patterns and support protocol evolution. + + }> + - Focus on a curated set of BSPs (e.g., BTT Kraken, then Octopus) rather than a large hardware matrix. + - Prefer driver “direct mode” where possible; use very high effective microstepping on the device while keeping host communication compact. + + }> + - Aether Printer is distributable as a packaged binary. + - MCU updates depend on the platform (e.g., DFU on some boards; some EtherCAT devices may not be updated in the field). + - Minimize firmware churn by decoupling host releases from MCU firmware where feasible. + + + + +## What you can build [#what-you-can-build] Aether is a launchpad for motion‑centric projects — from hobby robots to production‑grade machines. Here are a few ways to put it to work: @@ -85,83 +111,18 @@ Aether is a launchpad for motion‑centric projects — from hobby robots to pro - Re‑plan motion on the fly when sensors, cameras, or external systems provide late‑arriving inputs. - Keep hard real‑time in the core while pushing iterative logic to a responsive controller. -## Where It Fits + +## Where it fits [#where-it-fits] - Aether provides the motion control substrate for robotics and machines that benefit from deterministic timing, EtherCAT networking, and modular composition. - For 3D printing, Aether Printer integrates these pieces into an end‑to‑end firmware stack. - Bridging to other ecosystems is possible via modules on the real‑time side without bending the core architecture. -## Frequently Asked Questions - -
- What is Aether? How do “Aether Printer” and “AetherMCU” fit in? -

- Aether is the project and the set of libraries for motion control applications. - Aether Printer is the 3D‑printer firmware built on that base. - AetherMCU is the reference MCU implementation. -

-
- -
- How is Aether different from Klipper or Marlin? -

- Aether draws a hard boundary between host and MCU (both process and license). It favors board‑specific MCU builds over one generic firmware and avoids re‑flashing MCUs in lock‑step with host releases. On the wire, AetherMCU speaks a register‑based (fieldbus‑style) protocol rather than ad‑hoc commands. - Aether is a ground up redesign using current state of the art hardware and software methods. -

-
- -
- What hardware will be supported first? -

- Initial target is the BTT Octopus with TMC5160s for initial release, then broader board coverage. The goal is to ship something that prints well on common, capable hardware and expand from there. -

-
- -
- Will I need to update MCU firmware often? -

- No. Aether explicitly avoids frequent MCU updates tied to host changes. Occasional updates may happen, but device behavior should remain stable across controller versions. -

-
- -
- Does Aether require EtherCAT? What’s the communication model? -

- An AetherMCU instance will be treated like an EtherCAT‑style device: deterministic cycles, register‑mapped IO, and descriptor‑based discovery/config. EtherCAT is first‑class, and bridging modules can be used where needed—no hard lock‑in. -

-
- -
- Can I reuse existing Klipper MCUs or accessories within Aether Printer? -

- Direct reuse of a Klipper MCU isn’t planned. Some accessories that speak Klipper protocols may be bridged or re‑targeted, but the preference is Aether‑native or EtherCAT‑style devices for clean discovery/config and timing guarantees. -

-
- -
- What performance targets are you aiming for? -

- On a Pi 5, the target control cycle is around 500 μs, with room to go lower using kernel/driver tuning. On MCUs, timer hardware (e.g., repetition counters) enables step rates far beyond typical host‑bit‑banged approaches. -

-
- -
- How do device discovery and configuration work? Is hot‑plug planned? -

- Devices describe their resources (EtherCAT‑style). Discovery aims to be robust, but not everything is auto‑detectable—there is always a safe “not detected” fallback with manual configuration. Hot‑plug is planned where feasible; real‑time safety wins if there’s a trade‑off. -

-
- -
- Which advanced features are in scope soon? -

- Real‑time capabilities: resonance compensation, live encoder feedback and lag detection (including extruder), closed‑loop/servo control, and a modern motion planner (aligned with ideas pioneered in Prunt). For 3D printers an MPC temperature control library will ship via a Rust port of the existing Marlin/Klipper work. -

-
- -
- When will it be ready? -

- When it’s good. Near‑term: reach Klipper/Marlin‑parity on targeted hardware; then land the more ambitious features. Quality and correctness drive the schedule. -

-
+ +## What Aether is Not [#what-aether-is-not] + +- Tied to vendor lock‑in or C++‑centric stacks. +- Locked into recompiling MCU firmwares in lockstep with host releases; the system should discover and configure compatible devices. +- Aiming for plug‑and‑play on arbitrary boards in early phases; curated BSPs keep complexity in check. +- Chasing the extreme MCU flexibility approach; prioritize predictable, high‑performance hardware compositions. +- On a fixed public timeline; quality and correctness come first. From cf7367d32972ed947bb3ff7bc1169afa1ec7031c Mon Sep 17 00:00:00 2001 From: Philipp Molitor Date: Sun, 19 Oct 2025 18:08:36 +0200 Subject: [PATCH 04/24] add faq as a seperate page --- content/docs/lib/faq.mdx | 50 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 content/docs/lib/faq.mdx diff --git a/content/docs/lib/faq.mdx b/content/docs/lib/faq.mdx new file mode 100644 index 0000000..38bc06e --- /dev/null +++ b/content/docs/lib/faq.mdx @@ -0,0 +1,50 @@ +--- +title: Frequently Asked Questions +description: Everything essential you need to know about Aether. +icon: HelpCircle +--- + + + + Aether is the project and the set of libraries for motion control applications. + Aether Printer is the 3D‑printer firmware built on that base. + AetherMCU is the reference MCU implementation. + + + + Aether draws a hard boundary between host and MCU (both process and license). It favors board‑specific MCU builds over one generic firmware and avoids re‑flashing MCUs in lock‑step with host releases. On the wire, AetherMCU speaks a register‑based (fieldbus‑style) protocol rather than ad‑hoc commands. + Aether is a ground up redesign using current state of the art hardware and software methods. + + + + Initial target is the BTT Octopus with TMC5160s for initial release, then broader board coverage. The goal is to ship something that prints well on common, capable hardware and expand from there. + + + + No. Aether explicitly avoids frequent MCU updates tied to host changes. Occasional updates may happen, but device behavior should remain stable across controller versions. + + + + An AetherMCU instance will be treated like an EtherCAT‑style device: deterministic cycles, register‑mapped IO, and descriptor‑based discovery/config. EtherCAT is first‑class, and bridging modules can be used where needed—no hard lock‑in. + + + + Direct reuse of a Klipper MCU isn't planned. Some accessories that speak Klipper protocols may be bridged or re‑targeted, but the preference is Aether‑native or EtherCAT‑style devices for clean discovery/config and timing guarantees. + + + + On a Pi 5, the target control cycle is around 500 μs, with room to go lower using kernel/driver tuning. On MCUs, timer hardware (e.g., repetition counters) enables step rates far beyond typical host‑bit‑banged approaches. + + + + Devices describe their resources (EtherCAT‑style). Discovery aims to be robust, but not everything is auto‑detectable—there is always a safe "not detected" fallback with manual configuration. Hot‑plug is planned where feasible; real‑time safety wins if there's a trade‑off. + + + + Real‑time capabilities: resonance compensation, live encoder feedback and lag detection (including extruder), closed‑loop/servo control, and a modern motion planner (aligned with ideas pioneered in Prunt). For 3D printers an MPC temperature control library will ship via a Rust port of the existing Marlin/Klipper work. + + + + When it's good. Near‑term: reach Klipper/Marlin‑parity on targeted hardware; then land the more ambitious features. Quality and correctness drive the schedule. + + From 209e51a8588374cf29f49a358be74cd03dadbca6 Mon Sep 17 00:00:00 2001 From: Philipp Molitor Date: Mon, 20 Oct 2025 21:50:15 +0200 Subject: [PATCH 05/24] add metadata base url --- .github/workflows/deploy.yaml | 2 ++ src/app/(marketing)/page.tsx | 15 +++++++++++++++ src/app/docs/[[...slug]]/page.tsx | 9 ++++++++- src/config.ts | 4 ++++ 4 files changed, 29 insertions(+), 1 deletion(-) diff --git a/.github/workflows/deploy.yaml b/.github/workflows/deploy.yaml index dd91822..126b8d6 100644 --- a/.github/workflows/deploy.yaml +++ b/.github/workflows/deploy.yaml @@ -22,6 +22,8 @@ jobs: run: bun run lint - name: Build run: bun run build + env: + NEXT_PUBLIC_SITE_HOST: ${{ vars.SITE_HOST }} - name: Upload artifact uses: actions/upload-pages-artifact@v3 with: diff --git a/src/app/(marketing)/page.tsx b/src/app/(marketing)/page.tsx index f5d7b70..cfbca54 100644 --- a/src/app/(marketing)/page.tsx +++ b/src/app/(marketing)/page.tsx @@ -1,3 +1,7 @@ +import type { Metadata } from "next"; + +import { SITE_BASE_URL } from "@/config"; + import { Hero } from "@/components/marketing/Hero"; export default function LandingPage() { @@ -55,3 +59,14 @@ export default function LandingPage() { ); } + +export async function generateMetadata( + _props: PageProps<"/">, +): Promise { + return { + title: "Aether", + description: + "Aether is a motion control ecosystem for the robotics of tomorrow.", + metadataBase: new URL(SITE_BASE_URL), + }; +} diff --git a/src/app/docs/[[...slug]]/page.tsx b/src/app/docs/[[...slug]]/page.tsx index e2774a4..a17ac17 100644 --- a/src/app/docs/[[...slug]]/page.tsx +++ b/src/app/docs/[[...slug]]/page.tsx @@ -18,6 +18,7 @@ import { DOCS_GITHUB_BRANCH, DOCS_GITHUB_OWNER, DOCS_GITHUB_REPO, + SITE_BASE_URL, } from "@/config"; import { getMDXComponents } from "@/mdx-components"; @@ -118,11 +119,17 @@ export async function generateMetadata( const page = source.getPage(params.slug); if (!page) notFound(); + const image = getDocsPageImage(page); + return { title: page.data.title, description: page.data.description, openGraph: { - images: getDocsPageImage(page).url, + images: image.url, + }, + twitter: { + images: image.url, }, + metadataBase: new URL(SITE_BASE_URL), }; } diff --git a/src/config.ts b/src/config.ts index 954980e..e4b86b0 100644 --- a/src/config.ts +++ b/src/config.ts @@ -6,3 +6,7 @@ export const DISCORD_URL = "https://discord.gg/aetherware"; export const DOCS_GITHUB_OWNER = "AetherWareFoundation"; export const DOCS_GITHUB_REPO = "AetherWareFoundation.github.io"; export const DOCS_GITHUB_BRANCH = "main"; + +export const SITE_HOST = process.env.NEXT_PUBLIC_SITE_HOST ?? "localhost:3000"; +export const SITE_PROTOCOL = `http${process.env.NODE_ENV === "production" ? "s" : ""}:`; +export const SITE_BASE_URL = `${SITE_PROTOCOL}//${SITE_HOST}`; From 44efb911cd1823dd4853ce1ec4b4718e805d79a6 Mon Sep 17 00:00:00 2001 From: Philipp Molitor Date: Mon, 20 Oct 2025 23:43:09 +0200 Subject: [PATCH 06/24] rename ci action --- .github/workflows/{pr-lint.yaml => pr-ci.yaml} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename .github/workflows/{pr-lint.yaml => pr-ci.yaml} (94%) diff --git a/.github/workflows/pr-lint.yaml b/.github/workflows/pr-ci.yaml similarity index 94% rename from .github/workflows/pr-lint.yaml rename to .github/workflows/pr-ci.yaml index f976e64..16e9b4a 100644 --- a/.github/workflows/pr-lint.yaml +++ b/.github/workflows/pr-ci.yaml @@ -1,4 +1,4 @@ -name: PR Lint +name: PR continuous integration on: pull_request_target: From f05adede4f2a88bff23da68a709ffc9006266b3d Mon Sep 17 00:00:00 2001 From: Philipp Molitor Date: Mon, 20 Oct 2025 23:43:25 +0200 Subject: [PATCH 07/24] fix llm mdx file type --- src/app/docs/[[...slug]]/page.tsx | 4 +-- src/app/docs/llms.mdx/[[...slug]]/route.tsx | 28 +++++++++++++++------ src/lib/content.ts | 11 ++++++++ 3 files changed, 33 insertions(+), 10 deletions(-) diff --git a/src/app/docs/[[...slug]]/page.tsx b/src/app/docs/[[...slug]]/page.tsx index a17ac17..88fd667 100644 --- a/src/app/docs/[[...slug]]/page.tsx +++ b/src/app/docs/[[...slug]]/page.tsx @@ -12,7 +12,7 @@ import { EditOnGitHub, } from "fumadocs-ui/page"; -import { getDocsPageImage, source } from "@/lib/content"; +import { getDocsMdxPath, getDocsPageImage, source } from "@/lib/content"; import { DynamicLucideIcon } from "@/components/DynamicLucideIcon"; import { DOCS_GITHUB_BRANCH, @@ -35,7 +35,7 @@ export default async function Page(props: PageProps<"/docs/[[...slug]]">) { if (!page) notFound(); const MDX = page.data.body; - const mdxUrl = `/docs/llms.mdx/${page.slugs.join("/")}${page.absolutePath.endsWith("/index.mdx") ? "/index" : ""}`; + const mdxUrl = getDocsMdxPath(page); return ( , ) { let { slug } = await params; - if (slug && slug.length > 0 && slug?.at(-1) === "index") + if (slug && slug.length > 0 && slug.at(-1) === "index.mdx") slug = slug.slice(0, -1); const page = source.getPage(slug); if (!page) notFound(); @@ -21,12 +21,24 @@ export async function GET( } export function generateStaticParams() { - const mapped = source.generateParams().map((p) => { - type Params = typeof p; - const page = source.getPage(p.slug); - if (page?.absolutePath.endsWith("/index.mdx")) - return { ...p, slug: [...p.slug, "index"] } satisfies Params; - return p; - }); + const mapped = source + .generateParams() + .map((p) => { + type Params = typeof p; + const page = source.getPage(p.slug); + if (!page) return null; + + const slugs = page.slugs; + + // index would collide with directories + if (page.absolutePath.endsWith("/index.mdx")) slugs.push("index"); + + // add mdx extension + const last = slugs.pop(); + slugs.push(`${last}.mdx`); + + return { ...p, slug: slugs } satisfies Params; + }) + .filter((p) => !!p); return mapped; } diff --git a/src/lib/content.ts b/src/lib/content.ts index 1fbde6c..4939157 100644 --- a/src/lib/content.ts +++ b/src/lib/content.ts @@ -1,3 +1,5 @@ +import type { Route } from "next"; + import type { InferPageType } from "fumadocs-core/source"; import { loader } from "fumadocs-core/source"; import { lucideIconsPlugin } from "fumadocs-core/source/lucide-icons"; @@ -18,6 +20,15 @@ export function getDocsPageImage(page: InferPageType) { }; } +export function getDocsMdxPath( + page: InferPageType, +): Route<`/docs/llms.mdx/${string}`> { + const isIndex = page.absolutePath.endsWith("/index.mdx"); + const slug = `${page.slugs.join("/")}${isIndex ? "/index" : ""}.mdx`; + + return `/docs/llms.mdx/${slug}`; +} + export async function getDocsLLMText(page: InferPageType) { const processed = await page.data.getText("processed"); return `# ${page.data.title} (${page.url})\n\n${processed}`; From dbc1bcb2607ccec154c72e8a2744699ff2416d81 Mon Sep 17 00:00:00 2001 From: Philipp Molitor Date: Tue, 21 Oct 2025 12:26:12 +0200 Subject: [PATCH 08/24] fix routing in build --- src/app/docs/llms.mdx/[[...slug]]/route.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/docs/llms.mdx/[[...slug]]/route.tsx b/src/app/docs/llms.mdx/[[...slug]]/route.tsx index 9c315b2..abf9f1d 100644 --- a/src/app/docs/llms.mdx/[[...slug]]/route.tsx +++ b/src/app/docs/llms.mdx/[[...slug]]/route.tsx @@ -28,7 +28,7 @@ export function generateStaticParams() { const page = source.getPage(p.slug); if (!page) return null; - const slugs = page.slugs; + const slugs = [...page.slugs]; // make a copy, messes with the build otherwise // index would collide with directories if (page.absolutePath.endsWith("/index.mdx")) slugs.push("index"); From 0c19457820c9488d56e1612f17498214dd6567b8 Mon Sep 17 00:00:00 2001 From: Philipp Molitor Date: Tue, 21 Oct 2025 18:34:32 +0200 Subject: [PATCH 09/24] fix last change date in docs --- .github/workflows/deploy.yaml | 4 +++- .github/workflows/pr-ci.yaml | 3 ++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/workflows/deploy.yaml b/.github/workflows/deploy.yaml index 126b8d6..aa97516 100644 --- a/.github/workflows/deploy.yaml +++ b/.github/workflows/deploy.yaml @@ -11,7 +11,9 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v5 + with: + fetch-depth: 0 # needed for "last updated" to work for doc pages - name: Setup Bun uses: oven-sh/setup-bun@v2 with: diff --git a/.github/workflows/pr-ci.yaml b/.github/workflows/pr-ci.yaml index 16e9b4a..dca9a0a 100644 --- a/.github/workflows/pr-ci.yaml +++ b/.github/workflows/pr-ci.yaml @@ -11,8 +11,9 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: + fetch-depth: 1 # we don't need the history, just the latest commit - this breaks "last updated" doc pages though! ref: ${{ github.event.pull_request.head.sha }} - name: Setup Bun uses: oven-sh/setup-bun@v2 From 976692e699352df2bcdc1296d45f04294b285f1e Mon Sep 17 00:00:00 2001 From: Philipp Molitor Date: Tue, 21 Oct 2025 18:36:15 +0200 Subject: [PATCH 10/24] improve llm urls --- .../{docs => (llms)}/llms-full.txt/route.ts | 0 src/app/{docs => (llms)}/llms.txt/route.tsx | 2 +- src/app/docs-llm/[[...slug]]/route.tsx | 40 +++++++++++++++++ src/app/docs/llms.mdx/[[...slug]]/route.tsx | 44 ------------------- src/lib/content.ts | 29 ++++++++++-- 5 files changed, 66 insertions(+), 49 deletions(-) rename src/app/{docs => (llms)}/llms-full.txt/route.ts (100%) rename src/app/{docs => (llms)}/llms.txt/route.tsx (92%) create mode 100644 src/app/docs-llm/[[...slug]]/route.tsx delete mode 100644 src/app/docs/llms.mdx/[[...slug]]/route.tsx diff --git a/src/app/docs/llms-full.txt/route.ts b/src/app/(llms)/llms-full.txt/route.ts similarity index 100% rename from src/app/docs/llms-full.txt/route.ts rename to src/app/(llms)/llms-full.txt/route.ts diff --git a/src/app/docs/llms.txt/route.tsx b/src/app/(llms)/llms.txt/route.tsx similarity index 92% rename from src/app/docs/llms.txt/route.tsx rename to src/app/(llms)/llms.txt/route.tsx index 4f1af4f..0cd2305 100644 --- a/src/app/docs/llms.txt/route.tsx +++ b/src/app/(llms)/llms.txt/route.tsx @@ -5,7 +5,7 @@ export const revalidate = false; export async function GET() { const scanned: string[] = []; - scanned.push(`# ${SITE_NAME} Docs`); + scanned.push(`# ${SITE_NAME} Documentation`); const map = new Map(); for (const page of source.getPages()) { diff --git a/src/app/docs-llm/[[...slug]]/route.tsx b/src/app/docs-llm/[[...slug]]/route.tsx new file mode 100644 index 0000000..84aec54 --- /dev/null +++ b/src/app/docs-llm/[[...slug]]/route.tsx @@ -0,0 +1,40 @@ +import { notFound } from "next/navigation"; +import { type NextRequest, NextResponse } from "next/server"; + +import { + getDocsLLMText, + getDocsMdxSlug, + getDocsPageFromMdxUrl, + source, +} from "@/lib/content"; + +export const revalidate = false; + +export async function GET( + _req: NextRequest, + { params }: RouteContext<"/docs-llm/[[...slug]]">, +) { + const { slug } = await params; + const page = getDocsPageFromMdxUrl(slug ?? []); + if (!page) notFound(); + + const mdxText = await getDocsLLMText(page); + + return new NextResponse(mdxText, { + headers: { "Content-Type": "text/markdown" }, + }); +} + +export function generateStaticParams() { + const mapped = source + .generateParams() + .map((p) => { + type Params = typeof p; + const page = source.getPage(p.slug); + if (!page) return null; + + return { ...p, slug: getDocsMdxSlug(page) } satisfies Params; + }) + .filter((p) => !!p); + return mapped; +} diff --git a/src/app/docs/llms.mdx/[[...slug]]/route.tsx b/src/app/docs/llms.mdx/[[...slug]]/route.tsx deleted file mode 100644 index abf9f1d..0000000 --- a/src/app/docs/llms.mdx/[[...slug]]/route.tsx +++ /dev/null @@ -1,44 +0,0 @@ -import { notFound } from "next/navigation"; -import { type NextRequest, NextResponse } from "next/server"; - -import { getDocsLLMText, source } from "@/lib/content"; - -export const revalidate = false; - -export async function GET( - _req: NextRequest, - { params }: RouteContext<"/docs/llms.mdx/[[...slug]]">, -) { - let { slug } = await params; - if (slug && slug.length > 0 && slug.at(-1) === "index.mdx") - slug = slug.slice(0, -1); - const page = source.getPage(slug); - if (!page) notFound(); - - return new NextResponse(await getDocsLLMText(page), { - headers: { "Content-Type": "text/markdown" }, - }); -} - -export function generateStaticParams() { - const mapped = source - .generateParams() - .map((p) => { - type Params = typeof p; - const page = source.getPage(p.slug); - if (!page) return null; - - const slugs = [...page.slugs]; // make a copy, messes with the build otherwise - - // index would collide with directories - if (page.absolutePath.endsWith("/index.mdx")) slugs.push("index"); - - // add mdx extension - const last = slugs.pop(); - slugs.push(`${last}.mdx`); - - return { ...p, slug: slugs } satisfies Params; - }) - .filter((p) => !!p); - return mapped; -} diff --git a/src/lib/content.ts b/src/lib/content.ts index 4939157..4c3851b 100644 --- a/src/lib/content.ts +++ b/src/lib/content.ts @@ -22,11 +22,32 @@ export function getDocsPageImage(page: InferPageType) { export function getDocsMdxPath( page: InferPageType, -): Route<`/docs/llms.mdx/${string}`> { - const isIndex = page.absolutePath.endsWith("/index.mdx"); - const slug = `${page.slugs.join("/")}${isIndex ? "/index" : ""}.mdx`; +): Route<`/docs-llm/${string}`> { + return `/docs-llm/${page.slugs.join("/")}.md`; +} + +export function getDocsMdxSlug( + page: InferPageType, +): Array { + const slugs = [...page.slugs]; // make a copy, messes with the build otherwise + + // add md extension + const last = slugs.pop(); + slugs.push(`${last}.md`); + + return slugs; +} - return `/docs/llms.mdx/${slug}`; +export function getDocsPageFromMdxUrl( + slug: Array, +): InferPageType | undefined { + const slugs = [...slug]; + if (slugs.length > 0) { + const s = slugs.pop(); + if (s) slugs.push(s.replace(".md", "")); + } + console.log(slugs); + return source.getPage(slugs); } export async function getDocsLLMText(page: InferPageType) { From e3d4a931fdb351b9c06ab4cf3f36781946eaadbc Mon Sep 17 00:00:00 2001 From: Philipp Molitor Date: Tue, 21 Oct 2025 18:36:44 +0200 Subject: [PATCH 11/24] add authors per docs page --- source.config.ts | 17 ++++++++--------- src/app/docs/[[...slug]]/page.tsx | 21 ++++++++++++++++++++- 2 files changed, 28 insertions(+), 10 deletions(-) diff --git a/source.config.ts b/source.config.ts index 2100903..c26dee4 100644 --- a/source.config.ts +++ b/source.config.ts @@ -6,18 +6,17 @@ import { metaSchema, } from "fumadocs-mdx/config"; -// You can customise Zod schemas for frontmatter and `meta.json` here -// see https://fumadocs.dev/docs/mdx/collections +import { z } from "zod"; + +// https://fumadocs.dev/docs/mdx/collections export const docs = defineDocs({ docs: { - schema: frontmatterSchema, - postprocess: { - includeProcessedMarkdown: true, - }, - }, - meta: { - schema: metaSchema, + schema: frontmatterSchema.extend({ + authors: z.optional(z.array(z.string())), + }), + postprocess: { includeProcessedMarkdown: true }, }, + meta: { schema: metaSchema }, }); export default defineConfig({ diff --git a/src/app/docs/[[...slug]]/page.tsx b/src/app/docs/[[...slug]]/page.tsx index 88fd667..7e18305 100644 --- a/src/app/docs/[[...slug]]/page.tsx +++ b/src/app/docs/[[...slug]]/page.tsx @@ -3,6 +3,7 @@ import path from "node:path"; import type { Metadata } from "next"; import Link from "next/link"; import { notFound } from "next/navigation"; +import { Fragment } from "react"; import { DocsBody, @@ -12,6 +13,8 @@ import { EditOnGitHub, } from "fumadocs-ui/page"; +import { DotIcon } from "lucide-react"; + import { getDocsMdxPath, getDocsPageImage, source } from "@/lib/content"; import { DynamicLucideIcon } from "@/components/DynamicLucideIcon"; import { @@ -47,7 +50,23 @@ export default async function Page(props: PageProps<"/docs/[[...slug]]">) { tableOfContent={{ style: "clerk" }} > {page.data.title} - {page.data.description} + + {page.data.description} + + {(page.data.authors?.length ?? 0) > 0 && ( +

+ Written by +

+ {page.data.authors?.map((author, i) => ( + + {i > 0 && } + {author} + + ))} +
+

+ )} +
From 01c640bf432358f869bb6d22e7e395587f3ed2f9 Mon Sep 17 00:00:00 2001 From: Philipp Molitor Date: Tue, 21 Oct 2025 18:36:52 +0200 Subject: [PATCH 12/24] add robots.txt and sitemap.xml --- src/app/robots.ts | 15 +++++++++++++++ src/app/sitemap.ts | 43 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+) create mode 100644 src/app/robots.ts create mode 100644 src/app/sitemap.ts diff --git a/src/app/robots.ts b/src/app/robots.ts new file mode 100644 index 0000000..fdd6985 --- /dev/null +++ b/src/app/robots.ts @@ -0,0 +1,15 @@ +import type { MetadataRoute } from "next"; + +import { SITE_BASE_URL } from "@/config"; + +export const revalidate = false; + +export default function robots(): MetadataRoute.Robots { + return { + rules: { + userAgent: "*", + allow: "/", + }, + sitemap: `${SITE_BASE_URL}/sitemap.xml`, + }; +} diff --git a/src/app/sitemap.ts b/src/app/sitemap.ts new file mode 100644 index 0000000..1bef23a --- /dev/null +++ b/src/app/sitemap.ts @@ -0,0 +1,43 @@ +import type { MetadataRoute } from "next"; + +import { getDocsMdxPath, source } from "@/lib/content"; +import { SITE_BASE_URL } from "@/config"; + +export const revalidate = false; + +type Sitemap = MetadataRoute.Sitemap; +type SitemapEntry = Sitemap[number]; + +function url(path: string): string { + return new URL(path, SITE_BASE_URL).toString(); +} + +export default async function sitemap(): Promise { + const docsPages = source.getPages(); + return [ + // marketing + { + url: url("/"), + changeFrequency: "monthly", + priority: 1, + }, + + // docs (pages and mdx) + ...docsPages.flatMap((page) => { + const { lastModified } = page.data; + const entryPage: SitemapEntry = { + url: url(page.url), + lastModified: lastModified ? new Date(lastModified) : undefined, + changeFrequency: "weekly", + priority: 0.5, + }; + const entryMdx: SitemapEntry = { + ...entryPage, + url: url(getDocsMdxPath(page)), + priority: 0.2, + }; + + return [entryPage, entryMdx]; + }), + ]; +} From 27690798b45a36262c137898d9b346fb8c6efefe Mon Sep 17 00:00:00 2001 From: Philipp Molitor Date: Tue, 21 Oct 2025 20:38:14 +0200 Subject: [PATCH 13/24] consistent md suffix --- src/lib/content.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/lib/content.ts b/src/lib/content.ts index 4c3851b..1039753 100644 --- a/src/lib/content.ts +++ b/src/lib/content.ts @@ -6,6 +6,8 @@ import { lucideIconsPlugin } from "fumadocs-core/source/lucide-icons"; import { docs } from "@/.source"; +const LLM_MDX_SUFFIX = ".md"; + export const source = loader({ baseUrl: "/docs", source: docs.toFumadocsSource(), @@ -23,7 +25,7 @@ export function getDocsPageImage(page: InferPageType) { export function getDocsMdxPath( page: InferPageType, ): Route<`/docs-llm/${string}`> { - return `/docs-llm/${page.slugs.join("/")}.md`; + return `/docs-llm/${page.slugs.join("/")}${LLM_MDX_SUFFIX}`; } export function getDocsMdxSlug( @@ -33,7 +35,7 @@ export function getDocsMdxSlug( // add md extension const last = slugs.pop(); - slugs.push(`${last}.md`); + slugs.push(`${last}${LLM_MDX_SUFFIX}`); return slugs; } @@ -44,7 +46,7 @@ export function getDocsPageFromMdxUrl( const slugs = [...slug]; if (slugs.length > 0) { const s = slugs.pop(); - if (s) slugs.push(s.replace(".md", "")); + if (s) slugs.push(s.replace(LLM_MDX_SUFFIX, "")); } console.log(slugs); return source.getPage(slugs); From cbb1fc851c785441a9cdf3a84378ccb89744967b Mon Sep 17 00:00:00 2001 From: Philipp Molitor Date: Tue, 21 Oct 2025 20:38:27 +0200 Subject: [PATCH 14/24] external link handling and styling --- src/app/docs/[[...slug]]/page.tsx | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/src/app/docs/[[...slug]]/page.tsx b/src/app/docs/[[...slug]]/page.tsx index 7e18305..def8108 100644 --- a/src/app/docs/[[...slug]]/page.tsx +++ b/src/app/docs/[[...slug]]/page.tsx @@ -1,9 +1,9 @@ import path from "node:path"; -import type { Metadata } from "next"; +import type { Metadata, Route } from "next"; import Link from "next/link"; import { notFound } from "next/navigation"; -import { Fragment } from "react"; +import { type ComponentPropsWithoutRef, Fragment } from "react"; import { DocsBody, @@ -13,7 +13,7 @@ import { EditOnGitHub, } from "fumadocs-ui/page"; -import { DotIcon } from "lucide-react"; +import { DotIcon, ExternalLink } from "lucide-react"; import { getDocsMdxPath, getDocsPageImage, source } from "@/lib/content"; import { DynamicLucideIcon } from "@/components/DynamicLucideIcon"; @@ -81,15 +81,33 @@ export default async function Page(props: PageProps<"/docs/[[...slug]]">) {
- + { + a: ({ href, ...props }: ComponentPropsWithoutRef<"a">) => { const found = source.getPageByHref(href ?? "", { dir: path.dirname(page.path), }); - if (!found) return ; + // link is not a docs page + if (!found) { + const isExternal = + href?.match(/^https?:\/\//) && !href?.includes(SITE_BASE_URL); + + return ( + + + {isExternal && ( + + )} + + ); + } + const pageHref = found.hash ? `${found.page.url}#${found.hash}` : found.page.url; From 821ab2b6a190478b7a8ed7330925dd16c9a91e61 Mon Sep 17 00:00:00 2001 From: Philipp Molitor Date: Tue, 21 Oct 2025 20:39:10 +0200 Subject: [PATCH 15/24] inline fuma theme and improve docs image handling --- src/app/global.css | 58 ++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 56 insertions(+), 2 deletions(-) diff --git a/src/app/global.css b/src/app/global.css index e89a34d..ff110d1 100644 --- a/src/app/global.css +++ b/src/app/global.css @@ -1,7 +1,6 @@ /** biome-ignore-all lint/suspicious/noUnknownAtRules: tailwindcss */ @import "tailwindcss"; -@import "fumadocs-ui/css/neutral.css"; @import "fumadocs-ui/css/preset.css"; @import "tw-animate-css"; @@ -10,6 +9,61 @@ @apply min-h-[calc(100dvh-(var(--spacing)*14)-var(--fd-banner-height))]; } +.dark .docs-body img { + @apply bg-white; +} + +::selection { + @apply bg-fd-primary; +} + +/* Fumadocs variables */ + +@theme { + --color-fd-background: hsl(0, 0%, 96%); + --color-fd-foreground: hsl(0, 0%, 3.9%); + --color-fd-muted: hsl(0, 0%, 96.1%); + --color-fd-muted-foreground: hsl(0, 0%, 45.1%); + --color-fd-popover: hsl(0, 0%, 98%); + --color-fd-popover-foreground: hsl(0, 0%, 15.1%); + --color-fd-card: hsl(0, 0%, 94.7%); + --color-fd-card-foreground: hsl(0, 0%, 3.9%); + --color-fd-border: hsla(0, 0%, 80%, 50%); + --color-fd-primary: hsl(0, 0%, 9%); + --color-fd-primary-foreground: hsl(0, 0%, 98%); + --color-fd-secondary: hsl(0, 0%, 93.1%); + --color-fd-secondary-foreground: hsl(0, 0%, 9%); + --color-fd-accent: hsla(0, 0%, 82%, 50%); + --color-fd-accent-foreground: hsl(0, 0%, 9%); + --color-fd-ring: hsl(0, 0%, 63.9%); +} + +.dark { + --color-fd-background: hsl(0, 0%, 7.04%); + --color-fd-foreground: hsl(0, 0%, 92%); + --color-fd-muted: hsl(0, 0%, 12.9%); + --color-fd-muted-foreground: hsla(0, 0%, 70%, 0.8); + --color-fd-popover: hsl(0, 0%, 11.6%); + --color-fd-popover-foreground: hsl(0, 0%, 86.9%); + --color-fd-card: hsl(0, 0%, 9.8%); + --color-fd-card-foreground: hsl(0, 0%, 98%); + --color-fd-border: hsla(0, 0%, 40%, 20%); + --color-fd-primary: hsl(0, 0%, 98%); + --color-fd-primary-foreground: hsl(0, 0%, 9%); + --color-fd-secondary: hsl(0, 0%, 12.9%); + --color-fd-secondary-foreground: hsl(0, 0%, 92%); + --color-fd-accent: hsla(0, 0%, 40.9%, 30%); + --color-fd-accent-foreground: hsl(0, 0%, 90%); + --color-fd-ring: hsl(0, 0%, 54.9%); + --color-fd-overlay: hsla(0, 0%, 0%, 0.2); +} + +.dark #nd-sidebar { + --color-fd-muted: hsl(0, 0%, 16%); + --color-fd-secondary: hsl(0, 0%, 18%); + --color-fd-muted-foreground: hsl(0, 0%, 72%); +} + /* Accent colors for the docs */ :root { @@ -21,7 +75,7 @@ .dark { --doc-color-lib: hsl(141, 53%, 53%); --doc-color-mcu: hsl(250 100% 80%); - --doc-color-printer: #fff383; + --doc-color-printer: hsl(54, 100%, 76%); --doc-color-ui: hsl(217, 91%, 60%); } .doc-accent-lib { From 2fb3ed0f55394296398e949139011d509c9d0f7e Mon Sep 17 00:00:00 2001 From: Philipp Molitor Date: Tue, 21 Oct 2025 20:42:16 +0200 Subject: [PATCH 16/24] fix build --- src/app/docs/[[...slug]]/page.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/app/docs/[[...slug]]/page.tsx b/src/app/docs/[[...slug]]/page.tsx index def8108..e61388a 100644 --- a/src/app/docs/[[...slug]]/page.tsx +++ b/src/app/docs/[[...slug]]/page.tsx @@ -108,9 +108,9 @@ export default async function Page(props: PageProps<"/docs/[[...slug]]">) { ); } - const pageHref = found.hash - ? `${found.page.url}#${found.hash}` - : found.page.url; + const pageHref = ( + found.hash ? `${found.page.url}#${found.hash}` : found.page.url + ) as Route; return ( From eafb8bf34734a5b963a875b733b39801677328fc Mon Sep 17 00:00:00 2001 From: Philipp Molitor Date: Tue, 21 Oct 2025 20:46:38 +0200 Subject: [PATCH 17/24] fix html layout error --- src/app/docs/[[...slug]]/page.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/app/docs/[[...slug]]/page.tsx b/src/app/docs/[[...slug]]/page.tsx index e61388a..578cbf8 100644 --- a/src/app/docs/[[...slug]]/page.tsx +++ b/src/app/docs/[[...slug]]/page.tsx @@ -54,7 +54,7 @@ export default async function Page(props: PageProps<"/docs/[[...slug]]">) { {page.data.description} {(page.data.authors?.length ?? 0) > 0 && ( -

+

Written by
{page.data.authors?.map((author, i) => ( @@ -64,7 +64,7 @@ export default async function Page(props: PageProps<"/docs/[[...slug]]">) { ))}
-

+
)} From 7f92d3a67ed37084338c89ab151268d73f82e6e8 Mon Sep 17 00:00:00 2001 From: Philipp Molitor Date: Tue, 21 Oct 2025 20:56:12 +0200 Subject: [PATCH 18/24] fix it again --- src/app/docs/[[...slug]]/page.tsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/app/docs/[[...slug]]/page.tsx b/src/app/docs/[[...slug]]/page.tsx index 578cbf8..090d544 100644 --- a/src/app/docs/[[...slug]]/page.tsx +++ b/src/app/docs/[[...slug]]/page.tsx @@ -54,17 +54,17 @@ export default async function Page(props: PageProps<"/docs/[[...slug]]">) { {page.data.description} {(page.data.authors?.length ?? 0) > 0 && ( -
+ Written by -
+ {page.data.authors?.map((author, i) => ( {i > 0 && } {author} ))} -
-
+ + )} From 41b92b8223b088d92c8217fabb0d53686f9e8361 Mon Sep 17 00:00:00 2001 From: Philipp Molitor Date: Tue, 21 Oct 2025 21:30:48 +0200 Subject: [PATCH 19/24] improve margin of top header --- src/app/docs/[[...slug]]/page.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/docs/[[...slug]]/page.tsx b/src/app/docs/[[...slug]]/page.tsx index 090d544..b79507b 100644 --- a/src/app/docs/[[...slug]]/page.tsx +++ b/src/app/docs/[[...slug]]/page.tsx @@ -50,7 +50,7 @@ export default async function Page(props: PageProps<"/docs/[[...slug]]">) { tableOfContent={{ style: "clerk" }} > {page.data.title} - + {page.data.description} {(page.data.authors?.length ?? 0) > 0 && ( From 5946a5be91bc36e5ab49c0ab78875c80720f0883 Mon Sep 17 00:00:00 2001 From: Philipp Molitor Date: Tue, 21 Oct 2025 22:06:34 +0200 Subject: [PATCH 20/24] fix search mime type --- src/app/api/{search => search.json}/route.ts | 0 src/components/StaticSearchDialog.tsx | 1 + 2 files changed, 1 insertion(+) rename src/app/api/{search => search.json}/route.ts (100%) diff --git a/src/app/api/search/route.ts b/src/app/api/search.json/route.ts similarity index 100% rename from src/app/api/search/route.ts rename to src/app/api/search.json/route.ts diff --git a/src/components/StaticSearchDialog.tsx b/src/components/StaticSearchDialog.tsx index cb3146c..5d5087f 100644 --- a/src/components/StaticSearchDialog.tsx +++ b/src/components/StaticSearchDialog.tsx @@ -30,6 +30,7 @@ export function StaticSearchDialog(props: SharedProps) { type: "static", initOrama, locale, + from: "/api/search.json", }); return ( From e3cb5e9c2c1ffd4ec701603f34f68cd9782cdcbd Mon Sep 17 00:00:00 2001 From: YanceyA Date: Sat, 18 Oct 2025 22:10:38 +1300 Subject: [PATCH 21/24] Inital commit with bulk of Aether overview, architecture, hardware, builds and such. --- content/docs/lib/index.mdx | 88 +++++++++++++++++++++++++++++++++++++- 1 file changed, 86 insertions(+), 2 deletions(-) diff --git a/content/docs/lib/index.mdx b/content/docs/lib/index.mdx index 6963520..5fea6f6 100644 --- a/content/docs/lib/index.mdx +++ b/content/docs/lib/index.mdx @@ -4,5 +4,89 @@ description: The Aether framework for building motion control applications in Ru icon: House --- -## What is Aether? -Aether is a framework for building motion control applications in Rust. It provides a set of components and tools for building motion control applications. +## Overview + +Aether is a Rust-based framework for high‑performance motion control. It is both a set of composable libraries and a host runtime that coordinates real‑time control across heterogeneous devices. The same building blocks power domain solutions like Aether Printer (3D printing) while remaining usable as standalone crates in other robotics and montion control contexts. + +- Libraries compose into applications and can be used independently. +- The system can combine EtherCAT devices, Mesa cards, and “AetherMCU” boards in one installation. +- Components emphasize determinism, tight real‑time loops, and low overhead. + +## Goals + +- Be the obvious choice for robot motion control tasks. +- Meet hard real‑time constraints (e.g., EtherCAT cycle times) while keeping higher‑level logic responsive. +- Enable zero‑copy, low‑overhead interfaces between controller and core. +- Provide modular crates with stable surfaces and compile‑time enforced versioning where linked. +- Support device discoverability and simple configuration of devices through well‑defined descriptors. +- Log relevant metrics to reproduce exact machine state and motion paths. +- To be a modern Rust based etherCAT capable LinuxCNC replacement. + +## Architecture + +- Core and Controller + - Core: hard real‑time. Executes motion schedules and device I/O within strict cycle budgets. + - Controller: soft real‑time. Feeds the core; if it falls behind, the core safely waits for new commands. + - Linking: prefer in‑process linking (controller + core in Rust) to avoid serialization and enable direct data sharing. + +- Planner and Motion Queues + - Planner accepts long sequences (e.g., G‑code), enforces machine limits, and produces motion segments. + - Motion queues flow from planner to core; the core marks execution and exposes how much is committed for replanning. + - Control modes (e.g., position follower) sample from movement queues; the planner can update or replace segments. + +- Interfaces and Versioning + - Keep controller↔core communication low‑overhead; link for compile‑time API guarantees. + - Introduce explicit serialization only when a stable external interface is required. + - Thin controller patterns allow wrappers (e.g., PyO3 or FFI) without compromising real‑time boundaries. + +- Scope and Discoverability + - Keep the real‑time path strictly EtherCAT to limit scope and ensure determinism. + - Integrate non‑real‑time pieces on the controller side. + - Use existing EtherCAT XML descriptors and add higher‑level descriptors when needed; the UI should identify connected hardware and map it to functions. + +### High‑Level Diagram + + CTRL[Controller - soft RT]\n CTRL --> PLAN[Planner + Motion Queue]\n PLAN --> CTRL\n CTRL --> CORE[Core - hard RT]\n CORE --> EC[EtherCAT Network]\n EC --> DEV[AetherMCU / Mesa / EtherCAT Devices]"} /> + +## Hardware & Protocols + +- Device Model + - Treat microcontroller nodes like EtherCAT devices. + - Use a register‑based protocol for MCUs to align with established fieldbus patterns and support protocol evolution. + +- Boards and Drivers + - Focus on a curated set of BSPs (e.g., BTT Kraken, then Octopus) rather than a large hardware matrix. + - Prefer driver “direct mode” where possible; use very high effective microstepping on the device while keeping host communication compact. + +- Packaging and Updates + - Aether Printer is distributable as a packaged binary. + - MCU updates depend on the platform (e.g., DFU on some boards; some EtherCAT devices may not be updated in the field). + - Minimize firmware churn by decoupling host releases from MCU firmware where feasible. + +## Aether Is Not: + +- Tied to vendor lock‑in or C++‑centric stacks. +- Locked into recompiling MCU firmwares in lockstep with host releases; the system should discover and configure compatible devices. +- Aiming for plug‑and‑play on arbitrary boards in early phases; curated BSPs keep complexity in check. +- Chasing the extreme MCU flexibility approach; prioritize predictable, high‑performance hardware compositions. +- On a fixed public timeline; quality and correctness come first. + +## What You Can Build + +Aether is a launchpad for motion‑centric projects — from hobby robots to production‑grade machines. Here are a few ways to put it to work: + +- 3D printers with precision and insight + - Build on Aether Printer to drive multi‑axis printers at high control rates. + - Run drivers in direct modes with very high effective microstepping while keeping host communication compact. + - Capture deterministic logs so you can reproduce exact print states, compare paths, and debug confidently. + +- Robotics, CNC, and pick‑and‑place + - Compose planners and control modes for arms, gantries, and routers. + - Re‑plan motion on the fly when sensors, cameras, or external systems provide late‑arriving inputs. + - Keep hard real‑time in the core while pushing iterative logic to a responsive controller. + +## Where It Fits + +- Aether provides the motion control substrate for robotics and machines that benefit from deterministic timing, EtherCAT networking, and modular composition. +- For 3D printing, Aether Printer integrates these pieces into an end‑to‑end firmware stack. +- Bridging to other ecosystems is possible via modules on the real‑time side without bending the core architecture. From d358228fb32ecbb013f128ef855240896529e12b Mon Sep 17 00:00:00 2001 From: YanceyA Date: Sun, 19 Oct 2025 09:44:58 +1300 Subject: [PATCH 22/24] Add accordian style FAQ --- content/docs/lib/index.mdx | 75 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/content/docs/lib/index.mdx b/content/docs/lib/index.mdx index 5fea6f6..c22ba17 100644 --- a/content/docs/lib/index.mdx +++ b/content/docs/lib/index.mdx @@ -90,3 +90,78 @@ Aether is a launchpad for motion‑centric projects — from hobby robots to pro - Aether provides the motion control substrate for robotics and machines that benefit from deterministic timing, EtherCAT networking, and modular composition. - For 3D printing, Aether Printer integrates these pieces into an end‑to‑end firmware stack. - Bridging to other ecosystems is possible via modules on the real‑time side without bending the core architecture. + +## Frequently Asked Questions + +
+ What is Aether? How do “Aether Printer” and “AetherMCU” fit in? +

+ Aether is the project and the set of libraries for motion control applications. + Aether Printer is the 3D‑printer firmware built on that base. + AetherMCU is the reference MCU implementation. +

+
+ +
+ How is Aether different from Klipper or Marlin? +

+ Aether draws a hard boundary between host and MCU (both process and license). It favors board‑specific MCU builds over one generic firmware and avoids re‑flashing MCUs in lock‑step with host releases. On the wire, AetherMCU speaks a register‑based (fieldbus‑style) protocol rather than ad‑hoc commands. + Aether is a ground up redesign using current state of the art hardware and software methods. +

+
+ +
+ What hardware will be supported first? +

+ Initial target is the BTT Octopus with TMC5160s for initial release, then broader board coverage. The goal is to ship something that prints well on common, capable hardware and expand from there. +

+
+ +
+ Will I need to update MCU firmware often? +

+ No. Aether explicitly avoids frequent MCU updates tied to host changes. Occasional updates may happen, but device behavior should remain stable across controller versions. +

+
+ +
+ Does Aether require EtherCAT? What’s the communication model? +

+ An AetherMCU instance will be treated like an EtherCAT‑style device: deterministic cycles, register‑mapped IO, and descriptor‑based discovery/config. EtherCAT is first‑class, and bridging modules can be used where needed—no hard lock‑in. +

+
+ +
+ Can I reuse existing Klipper MCUs or accessories within Aether Printer? +

+ Direct reuse of a Klipper MCU isn’t planned. Some accessories that speak Klipper protocols may be bridged or re‑targeted, but the preference is Aether‑native or EtherCAT‑style devices for clean discovery/config and timing guarantees. +

+
+ +
+ What performance targets are you aiming for? +

+ On a Pi 5, the target control cycle is around 500 μs, with room to go lower using kernel/driver tuning. On MCUs, timer hardware (e.g., repetition counters) enables step rates far beyond typical host‑bit‑banged approaches. +

+
+ +
+ How do device discovery and configuration work? Is hot‑plug planned? +

+ Devices describe their resources (EtherCAT‑style). Discovery aims to be robust, but not everything is auto‑detectable—there is always a safe “not detected” fallback with manual configuration. Hot‑plug is planned where feasible; real‑time safety wins if there’s a trade‑off. +

+
+ +
+ Which advanced features are in scope soon? +

+ Real‑time capabilities: resonance compensation, live encoder feedback and lag detection (including extruder), closed‑loop/servo control, and a modern motion planner (aligned with ideas pioneered in Prunt). For 3D printers an MPC temperature control library will ship via a Rust port of the existing Marlin/Klipper work. +

+
+ +
+ When will it be ready? +

+ When it’s good. Near‑term: reach Klipper/Marlin‑parity on targeted hardware; then land the more ambitious features. Quality and correctness drive the schedule. +

+
From 9df2a71bc0304bef7ca573e5b5a1b2341c75c11d Mon Sep 17 00:00:00 2001 From: Philipp Molitor Date: Sun, 19 Oct 2025 18:08:22 +0200 Subject: [PATCH 23/24] use advanced components --- content/docs/lib/index.mdx | 189 +++++++++++++++---------------------- 1 file changed, 75 insertions(+), 114 deletions(-) diff --git a/content/docs/lib/index.mdx b/content/docs/lib/index.mdx index c22ba17..dd522aa 100644 --- a/content/docs/lib/index.mdx +++ b/content/docs/lib/index.mdx @@ -4,7 +4,20 @@ description: The Aether framework for building motion control applications in Ru icon: House --- -## Overview +import { Callout } from "fumadocs-ui/components/callout"; +import { Cards, Card } from "fumadocs-ui/components/card"; +import { Accordion, Accordions } from 'fumadocs-ui/components/accordion'; + +import { CpuIcon, LightbulbIcon, PackageOpenIcon } from "lucide-react"; + + + ## This documentation is in its very early stages. [!toc] [#alpha-warning] + We are still working on the alpha release of Aether.
+ Expect things to change and break frequently as we continue to develop the project. +
+ + +## Overview [#overview] Aether is a Rust-based framework for high‑performance motion control. It is both a set of composable libraries and a host runtime that coordinates real‑time control across heterogeneous devices. The same building blocks power domain solutions like Aether Printer (3D printing) while remaining usable as standalone crates in other robotics and montion control contexts. @@ -12,7 +25,8 @@ Aether is a Rust-based framework for high‑performance motion control. It is bo - The system can combine EtherCAT devices, Mesa cards, and “AetherMCU” boards in one installation. - Components emphasize determinism, tight real‑time loops, and low overhead. -## Goals + +## Goals [#goals] - Be the obvious choice for robot motion control tasks. - Meet hard real‑time constraints (e.g., EtherCAT cycle times) while keeping higher‑level logic responsive. @@ -22,56 +36,68 @@ Aether is a Rust-based framework for high‑performance motion control. It is bo - Log relevant metrics to reproduce exact machine state and motion paths. - To be a modern Rust based etherCAT capable LinuxCNC replacement. -## Architecture -- Core and Controller - - Core: hard real‑time. Executes motion schedules and device I/O within strict cycle budgets. - - Controller: soft real‑time. Feeds the core; if it falls behind, the core safely waits for new commands. - - Linking: prefer in‑process linking (controller + core in Rust) to avoid serialization and enable direct data sharing. +## Architecture [#architecture] -- Planner and Motion Queues - - Planner accepts long sequences (e.g., G‑code), enforces machine limits, and produces motion segments. - - Motion queues flow from planner to core; the core marks execution and exposes how much is committed for replanning. - - Control modes (e.g., position follower) sample from movement queues; the planner can update or replace segments. +### Core and Controller -- Interfaces and Versioning - - Keep controller↔core communication low‑overhead; link for compile‑time API guarantees. - - Introduce explicit serialization only when a stable external interface is required. - - Thin controller patterns allow wrappers (e.g., PyO3 or FFI) without compromising real‑time boundaries. +- Core: hard real‑time. Executes motion schedules and device I/O within strict cycle budgets. +- Controller: soft real‑time. Feeds the core; if it falls behind, the core safely waits for new commands. +- Linking: prefer in‑process linking (controller + core in Rust) to avoid serialization and enable direct data sharing. -- Scope and Discoverability - - Keep the real‑time path strictly EtherCAT to limit scope and ensure determinism. - - Integrate non‑real‑time pieces on the controller side. - - Use existing EtherCAT XML descriptors and add higher‑level descriptors when needed; the UI should identify connected hardware and map it to functions. +### Planner and Motion Queues -### High‑Level Diagram +- Planner accepts long sequences (e.g., G‑code), enforces machine limits, and produces motion segments. +- Motion queues flow from planner to core; the core marks execution and exposes how much is committed for replanning. +- Control modes (e.g., position follower) sample from movement queues; the planner can update or replace segments. - CTRL[Controller - soft RT]\n CTRL --> PLAN[Planner + Motion Queue]\n PLAN --> CTRL\n CTRL --> CORE[Core - hard RT]\n CORE --> EC[EtherCAT Network]\n EC --> DEV[AetherMCU / Mesa / EtherCAT Devices]"} /> +### Interfaces and Versioning -## Hardware & Protocols +- Keep controller↔core communication low‑overhead; link for compile‑time API guarantees. +- Introduce explicit serialization only when a stable external interface is required. +- Thin controller patterns allow wrappers (e.g., PyO3 or FFI) without compromising real‑time boundaries. -- Device Model - - Treat microcontroller nodes like EtherCAT devices. - - Use a register‑based protocol for MCUs to align with established fieldbus patterns and support protocol evolution. +### Scope and Discoverability -- Boards and Drivers - - Focus on a curated set of BSPs (e.g., BTT Kraken, then Octopus) rather than a large hardware matrix. - - Prefer driver “direct mode” where possible; use very high effective microstepping on the device while keeping host communication compact. +- Keep the real‑time path strictly EtherCAT to limit scope and ensure determinism. +- Integrate non‑real‑time pieces on the controller side. +- Use existing EtherCAT XML descriptors and add higher‑level descriptors when needed; the UI should identify connected hardware and map it to functions. -- Packaging and Updates - - Aether Printer is distributable as a packaged binary. - - MCU updates depend on the platform (e.g., DFU on some boards; some EtherCAT devices may not be updated in the field). - - Minimize firmware churn by decoupling host releases from MCU firmware where feasible. +### High‑Level Diagram [#high-level-diagram] -## Aether Is Not: +```mermaid +flowchart TD + UI[Aether UI] --> CTRL[Controller - soft RT] + CTRL --> PLAN[Planner + Motion Queue] + PLAN --> CTRL + CTRL --> CORE[Core - hard RT] + CORE --> EC[EtherCAT Network] + EC --> ETHERCAT_DEV[EtherCAT Devices] + EC --> MESA[Mesa] + EC --> AETHERMCU[AetherMCU] +``` -- Tied to vendor lock‑in or C++‑centric stacks. -- Locked into recompiling MCU firmwares in lockstep with host releases; the system should discover and configure compatible devices. -- Aiming for plug‑and‑play on arbitrary boards in early phases; curated BSPs keep complexity in check. -- Chasing the extreme MCU flexibility approach; prioritize predictable, high‑performance hardware compositions. -- On a fixed public timeline; quality and correctness come first. -## What You Can Build +## Hardware & Protocols [#hardware-protocols] + + + }> + - Treat microcontroller nodes like EtherCAT devices. + - Use a register‑based protocol for MCUs to align with established fieldbus patterns and support protocol evolution. + + }> + - Focus on a curated set of BSPs (e.g., BTT Kraken, then Octopus) rather than a large hardware matrix. + - Prefer driver “direct mode” where possible; use very high effective microstepping on the device while keeping host communication compact. + + }> + - Aether Printer is distributable as a packaged binary. + - MCU updates depend on the platform (e.g., DFU on some boards; some EtherCAT devices may not be updated in the field). + - Minimize firmware churn by decoupling host releases from MCU firmware where feasible. + + + + +## What you can build [#what-you-can-build] Aether is a launchpad for motion‑centric projects — from hobby robots to production‑grade machines. Here are a few ways to put it to work: @@ -85,83 +111,18 @@ Aether is a launchpad for motion‑centric projects — from hobby robots to pro - Re‑plan motion on the fly when sensors, cameras, or external systems provide late‑arriving inputs. - Keep hard real‑time in the core while pushing iterative logic to a responsive controller. -## Where It Fits + +## Where it fits [#where-it-fits] - Aether provides the motion control substrate for robotics and machines that benefit from deterministic timing, EtherCAT networking, and modular composition. - For 3D printing, Aether Printer integrates these pieces into an end‑to‑end firmware stack. - Bridging to other ecosystems is possible via modules on the real‑time side without bending the core architecture. -## Frequently Asked Questions - -
- What is Aether? How do “Aether Printer” and “AetherMCU” fit in? -

- Aether is the project and the set of libraries for motion control applications. - Aether Printer is the 3D‑printer firmware built on that base. - AetherMCU is the reference MCU implementation. -

-
- -
- How is Aether different from Klipper or Marlin? -

- Aether draws a hard boundary between host and MCU (both process and license). It favors board‑specific MCU builds over one generic firmware and avoids re‑flashing MCUs in lock‑step with host releases. On the wire, AetherMCU speaks a register‑based (fieldbus‑style) protocol rather than ad‑hoc commands. - Aether is a ground up redesign using current state of the art hardware and software methods. -

-
- -
- What hardware will be supported first? -

- Initial target is the BTT Octopus with TMC5160s for initial release, then broader board coverage. The goal is to ship something that prints well on common, capable hardware and expand from there. -

-
- -
- Will I need to update MCU firmware often? -

- No. Aether explicitly avoids frequent MCU updates tied to host changes. Occasional updates may happen, but device behavior should remain stable across controller versions. -

-
- -
- Does Aether require EtherCAT? What’s the communication model? -

- An AetherMCU instance will be treated like an EtherCAT‑style device: deterministic cycles, register‑mapped IO, and descriptor‑based discovery/config. EtherCAT is first‑class, and bridging modules can be used where needed—no hard lock‑in. -

-
- -
- Can I reuse existing Klipper MCUs or accessories within Aether Printer? -

- Direct reuse of a Klipper MCU isn’t planned. Some accessories that speak Klipper protocols may be bridged or re‑targeted, but the preference is Aether‑native or EtherCAT‑style devices for clean discovery/config and timing guarantees. -

-
- -
- What performance targets are you aiming for? -

- On a Pi 5, the target control cycle is around 500 μs, with room to go lower using kernel/driver tuning. On MCUs, timer hardware (e.g., repetition counters) enables step rates far beyond typical host‑bit‑banged approaches. -

-
- -
- How do device discovery and configuration work? Is hot‑plug planned? -

- Devices describe their resources (EtherCAT‑style). Discovery aims to be robust, but not everything is auto‑detectable—there is always a safe “not detected” fallback with manual configuration. Hot‑plug is planned where feasible; real‑time safety wins if there’s a trade‑off. -

-
- -
- Which advanced features are in scope soon? -

- Real‑time capabilities: resonance compensation, live encoder feedback and lag detection (including extruder), closed‑loop/servo control, and a modern motion planner (aligned with ideas pioneered in Prunt). For 3D printers an MPC temperature control library will ship via a Rust port of the existing Marlin/Klipper work. -

-
- -
- When will it be ready? -

- When it’s good. Near‑term: reach Klipper/Marlin‑parity on targeted hardware; then land the more ambitious features. Quality and correctness drive the schedule. -

-
+ +## What Aether is Not [#what-aether-is-not] + +- Tied to vendor lock‑in or C++‑centric stacks. +- Locked into recompiling MCU firmwares in lockstep with host releases; the system should discover and configure compatible devices. +- Aiming for plug‑and‑play on arbitrary boards in early phases; curated BSPs keep complexity in check. +- Chasing the extreme MCU flexibility approach; prioritize predictable, high‑performance hardware compositions. +- On a fixed public timeline; quality and correctness come first. From f8684eee01b49f39941b186f6b034dd96c963db9 Mon Sep 17 00:00:00 2001 From: Philipp Molitor Date: Sun, 19 Oct 2025 18:08:36 +0200 Subject: [PATCH 24/24] add faq as a seperate page --- content/docs/lib/faq.mdx | 50 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 content/docs/lib/faq.mdx diff --git a/content/docs/lib/faq.mdx b/content/docs/lib/faq.mdx new file mode 100644 index 0000000..38bc06e --- /dev/null +++ b/content/docs/lib/faq.mdx @@ -0,0 +1,50 @@ +--- +title: Frequently Asked Questions +description: Everything essential you need to know about Aether. +icon: HelpCircle +--- + + + + Aether is the project and the set of libraries for motion control applications. + Aether Printer is the 3D‑printer firmware built on that base. + AetherMCU is the reference MCU implementation. + + + + Aether draws a hard boundary between host and MCU (both process and license). It favors board‑specific MCU builds over one generic firmware and avoids re‑flashing MCUs in lock‑step with host releases. On the wire, AetherMCU speaks a register‑based (fieldbus‑style) protocol rather than ad‑hoc commands. + Aether is a ground up redesign using current state of the art hardware and software methods. + + + + Initial target is the BTT Octopus with TMC5160s for initial release, then broader board coverage. The goal is to ship something that prints well on common, capable hardware and expand from there. + + + + No. Aether explicitly avoids frequent MCU updates tied to host changes. Occasional updates may happen, but device behavior should remain stable across controller versions. + + + + An AetherMCU instance will be treated like an EtherCAT‑style device: deterministic cycles, register‑mapped IO, and descriptor‑based discovery/config. EtherCAT is first‑class, and bridging modules can be used where needed—no hard lock‑in. + + + + Direct reuse of a Klipper MCU isn't planned. Some accessories that speak Klipper protocols may be bridged or re‑targeted, but the preference is Aether‑native or EtherCAT‑style devices for clean discovery/config and timing guarantees. + + + + On a Pi 5, the target control cycle is around 500 μs, with room to go lower using kernel/driver tuning. On MCUs, timer hardware (e.g., repetition counters) enables step rates far beyond typical host‑bit‑banged approaches. + + + + Devices describe their resources (EtherCAT‑style). Discovery aims to be robust, but not everything is auto‑detectable—there is always a safe "not detected" fallback with manual configuration. Hot‑plug is planned where feasible; real‑time safety wins if there's a trade‑off. + + + + Real‑time capabilities: resonance compensation, live encoder feedback and lag detection (including extruder), closed‑loop/servo control, and a modern motion planner (aligned with ideas pioneered in Prunt). For 3D printers an MPC temperature control library will ship via a Rust port of the existing Marlin/Klipper work. + + + + When it's good. Near‑term: reach Klipper/Marlin‑parity on targeted hardware; then land the more ambitious features. Quality and correctness drive the schedule. + +