diff --git a/docs/badge/firmware.rst b/docs/badge/firmware.rst
new file mode 100644
index 0000000000000000000000000000000000000000..af3299b6e34e77d96988f45f9989eb872db4e94e
--- /dev/null
+++ b/docs/badge/firmware.rst
@@ -0,0 +1,171 @@
+Firmware
+========
+
+Introduction
+------------
+
+The flow3r badge firmware is composed of a number of parts:
+
+ESP-IDF
+	The ESP-IDF is the SDK provided by Espressif for its ESP32 series of
+	devices. This SDK is written in C and heavily based around FreeRTOS.
+
+flow3r-bsp
+	The lowest layer of our own code, the Board Support Package is the driver
+	layer for interacting with the badge hardware. It's implemented as a
+	standard ESP-IDF components, so you can use it in your own ESP-IDF based
+	projects to quickly create fully custom experiences for the badge.
+
+micropython
+	Micropython is a interpreter for a subset of the Python programming
+	language. It runs as a FreeRTOS task and provides the main runtime for
+	flow3r-specific code, including user (your own!) applications. This is the
+	main subsystem you'll be interacting with when developing applications.
+
+.. _st3m:
+
+st3m
+	st3m (pronounced: stem) is the main framework and standard library for code
+	running on the badge. Its implementation is split into a C part (another
+	ESP-IDF component) and Micropython code (which lives in ``/flash/sys``).
+
+Filesystem
+----------
+
+The badge has a single UNIX-like filesystem. This filesystem is visible to both
+C and Micropython software:
+
++------------+---------------+------------------------------------+
+| Mountpoint | Filesystem    | Description                        |
++============+===============+====================================+
+| ``/flash`` | FAT32         | 10MiB partition on internal Flash. |
+|            | with WL [#WL]_| Contains st3m Python code in sys/. |
++------------+---------------+------------------------------------+
+| ``/sd``    | FAT32         | External SD card, if available.    |
++------------+---------------+------------------------------------+
+
+.. _partition:
+
+SPI Flash Partitions
+--------------------
+
+This is the SPI flash partition layout we use:
+
++--------------+--------+---------------------------------------+
+| Name         | Size   | Description                           |
++==============+========+=======================================+
+| n/a          | 32KiB  | Bootloader (``bootloader.bin``).      |
++--------------+--------+---------------------------------------+
+| ``nvs``      | 24KiB  | Non-Volatile Storage.                 |
++--------------+--------+---------------------------------------+
+| ``phy_init`` | 4KiB   | Unused PHY data partition.            |
++--------------+--------+---------------------------------------+
+| ``factory``  | 5.9MiB | Main badge firmware (``flow3r.bin``). |
++--------------+--------+---------------------------------------+
+| ``vfs``      | 10MiB  | FAT32 filesystem (with [#WL]_ layer). |
++--------------+--------+---------------------------------------+
+
+Accessing files from a PC
+------------------------------------
+
+If the badge is running correctly, you can access the filesystem over the micropython REPL:
+
+::
+
+	$ mpremote
+	MicroPython c48f94151-dirty on 1980-01-01; badge23 with ESP32S3
+	Type "help()" for more information.
+	>>> import os
+	>>> os.listdir('/')
+	['flash']
+	>>> os.listdir('/flash/sys')
+	['main.py', 'st4m', '.sys-installed']
+	>>> 
+
+	$ mpremote ls :flash/sys
+	ls :flash/sys
+	           0 main.py
+	           0 st4m
+	           0 .sys-installed
+
+
+You can also put the badge into :ref:`Disk Mode` to make it appear as a USB pendrive
+on your PC. However, only one of the two FAT32 block devices (internal flash
+partition or SD card) can be mounted at once.
+
+Startup
+-------
+
+The badge boot process is the following:
+
+1. The ESP32S3 ROM starts. If the BOOT0 (the left shoulder button) is pressed
+   down, it will boot into serial mode, from which esptool.py can be used to
+   flash_ the firmware.
+
+2. The ESP32S3 ROM loads and executes the second stage bootloader from SPI
+   Flash. The bootloader is currently a stock ESP-IDF bootloader, but this will
+   likely change.
+
+3. The bootloader loads the partition table definition from SPI flash, loads and
+   runs the ``factory`` partition_ from SPI flash.
+
+4. The badge firmware starts and the display shows 'Starting...'
+
+5. The badge firmware initializes (ie. formats) the FAT32 filesystem on the internal flash if necessary. The filesystem is then mounted on ``/flash``.
+
+6. The badge firmware checks if the badge has a ``/flash/sys/.sys-installed`` file. If not, st3m_ Micropython files are extracted there.
+
+7. The badge starts Micropython which then loads ``/flash/sys/main.py``.
+
+
+
+Recovery
+--------
+
+If you brick your badge by corrupting or messing up the files on the internal
+flash partition, you can always recover by somehow getting the badge into disk
+mode, mounting the internal flash partition and then removing all files and
+directories. Then, unmount the badge. After rebooting, the system partition will
+be restored to a stock state by the badge firmware.
+
+:ref:`Disk Mode` can be started from the main firmware, either from the menu or
+by pressing buttons as indicated in various crash screens.
+
+If the above is not possible, you can also start a limited Disk Mode from the
+:ref:`Bootloader`. The :ref:`Bootloader` can also be used to reflash the badge
+firmware `partition`_ in case it got corrupted.
+
+However, if something's really broken, you will have to perform a low-level
+flash via the ESP32 BootROM - see below.
+
+.. _flash:
+
+Flashing (low-level)
+--------------------
+
+To perform a low-level flash which will reset the entire badge state to a known
+state, you have to first put it into bootrom mode by starting it up with the
+left shoulder button held. The badge screen will stay off, but when connected
+over USB it should show up as an ``Espressif USB/JTAG bridge``.
+
+Compared to recovery modes above, this options requires the use of specialized
+software.
+
+Then use ``esptool.py`` (available from most Linux distribution package
+managers), download a release (TODO: link) and run the following:
+
+::
+
+	esptool.py \
+		-p /dev/ttyACM0 -b 460800 \
+		--before default_reset --after no_reset \
+		--chip esp32s3 write_flash -e \
+		--flash_mode dio --flash_size 16MB --flash_freq 80m \
+		0x0 bootloader.bin \
+		0x8000 partition-table.bin \
+		0x10000 flow3r.bin
+
+This will erase the entire internal SPI flash, and then program the bootloader,
+partition table and main firmware.
+
+.. [#WL] Wear leveling, to protect internal flash from death by repeat sector write.
diff --git a/docs/badge/programming.rst b/docs/badge/programming.rst
new file mode 100644
index 0000000000000000000000000000000000000000..e2328ea688602361fd4d34c9250358ea03092cc9
--- /dev/null
+++ b/docs/badge/programming.rst
@@ -0,0 +1,117 @@
+Programming
+===========
+
+The main programming interface and language for the flow3rbadge is Python. More
+exactly, it's `Micropython <https://micropython.org/>`_, which is a fairly
+sizeable subset of Python that can run on microcontrollers.
+
+Good news: if you've ever used Micropython on an ESP32, then you probably
+already have all the tools required to get started. However, while the tools to
+program the badge might be the same as for stock Micropython on ESP32, our APIs
+are quite different.
+
+The :ref:`st3m` framework is the main Python codebase you'll be writing against.
+Instead of using standard Micropython libraries like ``machine`` or low level
+display drivers, you'll be writing applications that implement st3m classes like
+:py:class:`Responder` or :py:class:`Application`.
+
+But, enough intro for now, let's get started.
+
+Accessing the badge
+-------------------
+
+When the badge runs (for example, when you see the main menu), you can connect
+it to a PC and it should appear as a serial device. On Linux systems, this
+device will be usually called ``/dev/ttyACM0``.
+
+You can then use any terminal emulator program (like picocom, GNU screen, etc)
+to access the badge's runtime logs. Even better, get `mpremote
+<https://docs.micropython.org/en/latest/reference/mpremote.html>`_, as it has
+extra features that make file transfer to Micropython a breeze.
+
+After connecting your badge and making sure it runs:
+
+::
+
+	$ mpremote
+	Connected to MicroPython at /dev/ttyACM0
+	Use Ctrl-] or Ctrl-x to exit this shell
+	[... logs here... ]
+
+The badge will continue to run. Now, if you press Ctrl-C, you will interrupt the
+firmware and break into a Python REPL (read-eval-print-loop) prompt:
+
+::
+
+	Traceback (most recent call last):
+	  File "/flash/sys/main.py", line 254, in <module>
+	  [... snip ...]
+	KeyboardInterrupt: 
+	MicroPython c48f94151-dirty on 1980-01-01; badge23 with ESP32S3
+	Type "help()" for more information.
+	>>> 
+
+The badge's display will now switch to 'In REPL' to indicate that software
+execution has been interrupted and that the badge is waiting for a command over
+REPL.
+
+Congratulations! You can now use your badge as a calculator:
+
+::
+
+	>>> 5 + 5
+	10
+
+But that's not super interesting. Let's try to turn on some LEDs:
+
+::
+
+	>>> import leds
+	>>> leds.set_rgb(0, 255, 0, 0)
+	>>> leds.update()
+
+The LED right next to the USB connector should light up red. You can continue
+experimenting with different APIs (like :py:mod:`leds`, :py:mod:`audio`, etc).
+
+Transferring files over REPL
+----------------------------
+
+You can also access the filesystem over the same Micropython serial port:
+
+::
+
+	$ mpremote
+	MicroPython c48f94151-dirty on 1980-01-01; badge23 with ESP32S3
+	Type "help()" for more information.
+	>>> import os
+	>>> os.listdir('/')
+	['flash']
+	>>> os.listdir('/flash/sys')
+	['main.py', 'st4m', '.sys-installed']
+	>>> 
+
+	$ mpremote ls :flash/sys
+	ls :flash/sys
+	           0 main.py
+	           0 st4m
+	           0 .sys-installed
+
+.. _disk mode:
+
+Disk Mode
+---------
+
+For larger file transfers (eg. images, sound samples, etc.) you can put the
+badge into Disk Mode by selecting ``Settings -> Disk Mode`` in the badge's menu.
+
+You can then select whether to mount the 10MiB internal flash or SD card (if
+present) as a pendrive. The selected device will then appear as a pendrive on
+your system, and will stay until it is ejected. The serial connection will
+disconnect for the duration of the badge being in disk mode.
+
+Disk Mode can also be enabled when the badge is in :ref:`Bootloader mode`.
+
+Writing Applications
+--------------------
+
+TODO
\ No newline at end of file
diff --git a/docs/badge/sdcard.rst b/docs/badge/sdcard.rst
deleted file mode 100644
index 6161139ac11e73b975a699b5fa2d931e7fbe832d..0000000000000000000000000000000000000000
--- a/docs/badge/sdcard.rst
+++ /dev/null
@@ -1,18 +0,0 @@
-SD Card
--------
-
-There's a microSD card slot on the inner side of the badge.
-
-There's no first-class firmware support for it yet, but you can mount it in the
-micropython VFS with:
-
-.. code-block:: python
-
-   import machine, os
-   sdcard = machine.SDCard(clk=47, cmd=48, d0=21)
-   os.mount(sdcard, "/sd")
-
-Filesystem support is provided by `FatFs
-<http://elm-chan.org/fsw/ff/00index_e.html>` which claims to support
-FAT16/32/exFAT. TODO: test
-
diff --git a/docs/badge/usage.rst b/docs/badge/usage.rst
new file mode 100644
index 0000000000000000000000000000000000000000..cb542676014327e535fac181e3c491bd9d108a1c
--- /dev/null
+++ b/docs/badge/usage.rst
@@ -0,0 +1,4 @@
+Usage
+=====
+
+TODO
\ No newline at end of file
diff --git a/docs/index.rst b/docs/index.rst
index 7f9ccbd05350bfb683549f84cd7b4e4662a9e7f8..2a0948b0f51d2a0bc6caf0ea7dbb5d8d566c1cfa 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -11,8 +11,10 @@ Welcome to flow3r's documentation!
    :caption: The badge:
 
    badge/hardware_specs.rst
+   badge/usage.rst
+   badge/programming.rst
+   badge/firmware.rst
    badge/badge_link.rst
-   badge/sdcard.rst
 
 .. toctree::
    :maxdepth: 1