diff --git a/README.md b/README.md
deleted file mode 100644
index 686beb25..00000000
--- a/README.md
+++ /dev/null
@@ -1,28 +0,0 @@
-# BOS README
-***
-## What is Docker?
-### What does it do?
-Basically, Docker lets you package an application
-into a container that can be distributed as images to
-run on other platforms. For example, let's say you have
-an application that works on your computer, but not on
-the server you want to eventually run it on. Docker
-solves that. It lets you package an application and
-the environment it needs to run on into a bundle that
-can then be run anywhere.
-
-## Docker commands you need to know
-### How to pull images using docker pull
-run `docker pull ghcr.io/frc971/bos/orin:latest`.
-
-This will pull a docker image for you to use on your computer.
-
-### How to run the container on your computer
-To run the docker container on your computer,
-run the following commands in the terminal:
-```bash
- docker run --privileged --network host --name orin -it ghcr.io/frc971/bos/orin:latest
- docker exec -it orin /bin/bash
-```
-This will run the docker container on your computer within a
-contained environment that simulates an ORIN.
diff --git a/docs/README.md b/docs/README.md
new file mode 100644
index 00000000..ac7b544c
--- /dev/null
+++ b/docs/README.md
@@ -0,0 +1,23 @@
+# BOS Documentation
+
+This folder contains project-level docs for the BOS codebase.
+
+## Contents
+
+- [Architecture Overview](architecture.md)
+- [Build and Run](build-and-run.md)
+- [Scripts Reference](scripts.md)
+- [Testing Guide](testing.md)
+
+## Quick Start
+
+```bash
+./scripts/build.sh
+```
+
+Primary executables are built from `src/`:
+
+- `main_bot_main`
+- `second_bot_main`
+- `unambiguous_first`
+- `unambiguous_second`
diff --git a/docs/architecture.md b/docs/architecture.md
new file mode 100644
index 00000000..acc6af3e
--- /dev/null
+++ b/docs/architecture.md
@@ -0,0 +1,88 @@
+# Architecture Overview
+
+## High-Level Flow
+
+The runtime system is built around a vision and localization pipeline:
+
+1. Camera modules capture frames.
+2. AprilTag detectors produce per-frame detections.
+3. Solvers estimate robot pose from detections.
+4. Position senders publish results to NetworkTables (and optional simulation outputs).
+5. Pathing and controller logic consume localization output and publish control intents.
+
+## Source Tree Map
+
+### `src/camera`
+
+- Camera interfaces and implementations (`cv`, `uvc`, disk replay).
+- Frame production wrappers (`CameraSource`, `MultiCameraSource`).
+- Optional CSCore streaming and frame writing utilities.
+- Camera constants loading from JSON.
+
+### `src/localization`
+
+- AprilTag detector interface and implementations:
+ - OpenCV ArUco AprilTag
+ - 971 GPU AprilTag
+ - NVIDIA VPI AprilTag
+- Pose solvers:
+ - `SquareSolver` (single tag)
+ - `MultiTagSolver` (multi-tag)
+ - `JointSolver` (multi-camera optimization)
+ - `UnambiguousEstimator` (ambiguity resolution and fusion)
+- Main localization loop (`run_localization`).
+- Publishers and receivers for position data.
+
+### `src/pathing`
+
+- BFS grid pathfinding.
+- Spline generation.
+- Control loop integration for command publication.
+
+### `src/yolo` and `src/gamepiece`
+
+- TensorRT-based YOLO wrapper.
+- Gamepiece pipeline built on top of camera + yolo + localization utilities.
+
+### `src/utils`
+
+- Shared cross-cutting helpers:
+ - logging
+ - timers
+ - transforms
+ - NetworkTables utility helpers
+ - JSON constant handling
+
+### `src/calibration`
+
+- Intrinsics calibration tools.
+- Frame display and focus calibration binaries.
+
+### `src/test`
+
+- `unit_test`: solver and pathing focused tests.
+- `integration_test`: end-to-end and subsystem executable tests.
+
+## Top-Level Binaries
+
+Defined in `src/CMakeLists.txt`:
+
+- `main_bot_main`
+- `second_bot_main`
+- `unambiguous_first`
+- `unambiguous_second`
+
+## Dependency Snapshot
+
+Major linked dependencies across modules:
+
+- OpenCV
+- Eigen3
+- WPILib (`wpilibc`, `wpiutil`, `ntcore`)
+- libuvc
+- NVIDIA VPI
+- TensorRT / CUDA (`nvinfer`, `nvinfer_plugin`, `cudart`)
+- 971 AprilTag
+- abseil
+- nlohmann/json
+- GoogleTest
diff --git a/docs/build-and-run.md b/docs/build-and-run.md
new file mode 100644
index 00000000..66f1f5bb
--- /dev/null
+++ b/docs/build-and-run.md
@@ -0,0 +1,47 @@
+# Build and Run
+
+## Prerequisites
+
+You can get set up in two ways:
+
+1. Get access to the build server over Tailscale.
+2. Build your own BOS Docker container from `https://github.com/frc971/bos-docker`.
+
+Also ensure CUDA binaries are on your shell `PATH` by adding this to your `~/.zshrc` or `~/.bashrc`:
+
+```bash
+export PATH="/usr/local/cuda-12.6/bin:$PATH"
+```
+
+If you are using the build server or the BOS Docker container, required toolchains and dependencies are already provided.
+
+## Build
+
+Use the project build script instead of running CMake manually:
+
+```bash
+./scripts/build.sh
+```
+
+Optional named build directory:
+
+```bash
+./scripts/build.sh --name=mybuild
+```
+
+## Main Runtime Binaries
+
+After building, these are the primary app entry points:
+
+- `main_bot_main`
+- `second_bot_main`
+- `unambiguous_first`
+- `unambiguous_second`
+
+## Calibration Tools
+
+Built in `src/calibration`:
+
+- `intrinsics_calibrate`
+- `frame_shower`
+- `focus_calibrate`
diff --git a/docs/scripts.md b/docs/scripts.md
new file mode 100644
index 00000000..4d6df4ed
--- /dev/null
+++ b/docs/scripts.md
@@ -0,0 +1,102 @@
+# Scripts Reference
+
+This document describes the scripts under `scripts/` and when to use them.
+
+## Build and Static Analysis
+
+### `scripts/build.sh`
+
+- Main build entrypoint.
+- Initializes submodules.
+- Creates `/bos/constants` when running outside `/bos`.
+- Configures a Release Ninja build with clang-tidy disabled.
+
+Usage:
+
+```bash
+./scripts/build.sh
+./scripts/build.sh --name=mybuild
+```
+
+### `scripts/clang_tidy_build.sh`
+
+- Build helper with clang-tidy enabled.
+- Uses `build/` as the output directory.
+- Usually used for CI checks rather than day-to-day local builds.
+
+Usage:
+
+```bash
+./scripts/clang_tidy_build.sh
+```
+
+## Test Execution
+
+### `scripts/run_tests.sh`
+
+- Runs all executable files in `build/src/test/unit_test`.
+- Returns non-zero if any test fails.
+
+Usage:
+
+```bash
+./scripts/run_tests.sh
+```
+
+## Deploy and Remote Sync
+
+### `scripts/copy_to_bin.sh`
+
+- Collects built executables from `build/src` into `bin/`.
+- Also copies `.so` and `.a` artifacts from `build/` into `bin/`.
+
+Usage:
+
+```bash
+./scripts/copy_to_bin.sh
+```
+
+### `scripts/deploy.sh`
+
+- Builds project, stages binaries into `bin/`, then rsyncs `bin/` and `constants/` to remote `/bos`.
+- Optional remote service restart (`bos.service`).
+
+Usage:
+
+```bash
+./scripts/deploy.sh nvidia@10.99.71.11
+./scripts/deploy.sh nvidia@10.99.71.11 true
+```
+
+### `scripts/remote_deploy.sh`
+
+- Like `deploy.sh`, but lets you pass a custom remote shell command (for jump-host/tunnel setups).
+- Current workflow uses a reverse tunnel through the build server.
+
+Usage:
+
+```bash
+ssh -R 9000:localhost:22 root@build-server
+./scripts/remote_deploy.sh "ssh -J charlie@localhost:9000" "nvidia@10.9.71.11"
+```
+
+### `scripts/upload_navgrid.sh`
+
+- Copies a local navgrid file into the running `orin` Docker container.
+- Then deploys to `nvidia@10.99.71.11` without restart.
+
+Usage:
+
+```bash
+./scripts/upload_navgrid.sh
+```
+
+### `scripts/upload_public_key.sh`
+
+- Uploads local `~/.ssh/id_ed25519.pub` and appends it to remote `authorized_keys`.
+
+Usage:
+
+```bash
+./scripts/upload_public_key.sh nvidia@10.99.71.11
+```
diff --git a/docs/testing.md b/docs/testing.md
new file mode 100644
index 00000000..6ec3dabc
--- /dev/null
+++ b/docs/testing.md
@@ -0,0 +1,32 @@
+# Testing Guide
+
+## Test Layout
+
+Tests live under `src/test`:
+
+- `src/test/unit_test`: GoogleTest-based unit tests.
+- `src/test/integration_test`: integration executables for subsystems and end-to-end checks.
+
+## Build Tests
+
+Tests are part of the normal project build. Use the project build script:
+
+```bash
+./scripts/build.sh
+```
+
+If you use a named build directory, keep that same directory when running tests:
+
+```bash
+./scripts/build.sh --name=mybuild
+```
+
+## Run Tests
+
+Use the test runner script instead of running test binaries manually:
+
+```bash
+./scripts/run_tests.sh
+```
+
+This script runs executable tests in `build/src/test/unit_test` and returns a failing exit code if any test fails.