diff --git a/README.md b/README.md
index a06939e2b..5e57cb94f 100644
--- a/README.md
+++ b/README.md
@@ -4,7 +4,7 @@ Tool for automatic executables porting to Linux and Windows.
Includes a [relinker](core/relinker) that converts executable to the target system's native format and implementations of [system prx libraries](core/libs/prx) suitable for dynamic linking. No emulation or separate runtime process.
-[Usage](docs/user/USAGE.md), [Build instructions](docs/dev/BUILD.md), [Technical debt of the project](docs/dev/TechnicalDebt.md), [code style conventions](docs/dev/CONVENTIONS.md), [contributing](CONTRIBUTING.md)
+[Usage](docs/user/USAGE.md), [Build instructions](docs/dev/BUILD.md), [Architecture](docs/dev/ARCHITECTURE.md), [Technical debt of the project](docs/dev/TechnicalDebt.md), [code style conventions](docs/dev/CONVENTIONS.md), [contributing](CONTRIBUTING.md)
## Status
diff --git a/docs/dev/ARCHITECTURE.md b/docs/dev/ARCHITECTURE.md
new file mode 100644
index 000000000..1a617546a
--- /dev/null
+++ b/docs/dev/ARCHITECTURE.md
@@ -0,0 +1,69 @@
+# Architecture
+
+How a PS5 executable becomes a native Linux or Windows program. Nothing is emulated: the converted executable runs as a normal process and calls native implementations of the system libraries.
+
+## Overview
+
+```mermaid
+flowchart LR
+ subgraph input["PS5 game"]
+ elf["input.elf"]
+ mods["sce_module/*"]
+ end
+
+ subgraph relinker["relinker (core/relinker)"]
+ direction TB
+ intel["--to-intel:
lower AMD-only instructions
(codegen)"]
+ pipeline["RelinkerPipeline:
read imports by NID,
check syscalls, filter unused NIDs,
build SysV dynamic section"]
+ guest["GuestModuleBuilder:
convert bundled modules"]
+ patcher["LinuxElfPatcher / WindowsPePatcher"]
+ intel -.-> pipeline --> guest --> patcher
+ end
+
+ subgraph build["build (core/libs)"]
+ direction TB
+ prx["core/libs/prx/*
shared libraries"]
+ nid["nid_patcher:
rename exports to their NIDs"]
+ prx --> nid
+ end
+
+ subgraph out["Native program"]
+ app["app.elf / app.exe"]
+ app0["app0/sce_module/*"]
+ libs["libs/*.prx"]
+ end
+
+ elf --> intel
+ mods --> guest
+ patcher --> app
+ guest --> app0
+ nid --> libs
+ app -- "OS loader binds imports by NID" --> libs
+ app0 -- "OS loader binds imports by NID" --> libs
+```
+
+- [`core/relinker/main.cpp`](../../core/relinker/main.cpp) runs the steps in this order. `--to-intel` is optional, see [USAGE.md](../user/USAGE.md).
+- Each library in [`core/libs/prx`](../../core/libs/prx) builds as a shared library. After the build, `nid_patcher` ([`core/libs/nid`](../../core/libs/nid)) renames every export to its NID, computed from the function name. `APS5_EXPORT("", func)` sets the NID directly when the name is unknown.
+
+## Graphics
+
+```mermaid
+flowchart LR
+ game["Game:
command buffers"] --> submit["libSceAgcDriver/Submit
DCB / ACB"]
+ submit --> pm4["Execution/Pm4:
state, draws,
dispatches"]
+ pm4 -- "shader + state" --> cache{"Compiled variant
in memory or
on disk?"}
+ cache -- yes --> vk
+ cache -- no --> dec
+
+ subgraph recompiler["core/shader/recompiler"]
+ dec["RdnaDecoder"] --> cf["ControlFlow:
graph + structurize"]
+ cf --> tr["Translation:
RDNA to IR"]
+ tr --> opt["Optimization:
SSA, resources,
bindings"]
+ opt --> spv["SpirvBackend:
emit SPIR-V"]
+ end
+
+ spv --> vk["libSceAgcDriver/Graphics:
Vulkan pipeline"]
+```
+
+- [`Recompiler.cpp`](../../core/shader/recompiler/Recompiler.cpp) runs the stages in this order. With `ANYPS5_ENABLE_SPIRV_TOOLS`, the SPIR-V is also validated and optimized with SPIRV-Tools.
+- `ShaderRecompiler::Recompile` keeps compiled variants in memory, and `ShaderDiskCache` stores them on disk so later runs reuse them.