diff --git a/DoxygenLayout.xml b/DoxygenLayout.xml
new file mode 100644
index 000000000..67497e83f
--- /dev/null
+++ b/DoxygenLayout.xml
@@ -0,0 +1,269 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/include/ghostty/vt.h b/include/ghostty/vt.h
index 7815ebb81..ebb41e300 100644
--- a/include/ghostty/vt.h
+++ b/include/ghostty/vt.h
@@ -327,6 +327,63 @@ typedef struct {
* Utilities for encoding key events into terminal escape sequences,
* supporting both legacy encoding as well as Kitty Keyboard Protocol.
*
+ * ## Basic Usage
+ *
+ * 1. Create an encoder instance with ghostty_key_encoder_new()
+ * 2. Configure encoder options with ghostty_key_encoder_setopt().
+ * 3. For each key event:
+ * - Create a key event with ghostty_key_event_new()
+ * - Set event properties (action, key, modifiers, etc.)
+ * - Encode with ghostty_key_encoder_encode()
+ * - Free the event with ghostty_key_event_free()
+ * - Note: You can also reuse the same key event multiple times by
+ * changing its properties.
+ * 4. Free the encoder with ghostty_key_encoder_free() when done
+ *
+ * ## Example
+ *
+ * @code{.c}
+ * #include
+ * #include
+ * #include
+ *
+ * int main() {
+ * // Create encoder
+ * GhosttyKeyEncoder encoder;
+ * GhosttyResult result = ghostty_key_encoder_new(NULL, &encoder);
+ * assert(result == GHOSTTY_SUCCESS);
+ *
+ * // Enable Kitty keyboard protocol with all features
+ * ghostty_key_encoder_setopt(encoder, GHOSTTY_KEY_ENCODER_OPT_KITTY_FLAGS,
+ * &(uint8_t){GHOSTTY_KITTY_KEY_ALL});
+ *
+ * // Create and configure key event for Ctrl+C press
+ * GhosttyKeyEvent event;
+ * result = ghostty_key_event_new(NULL, &event);
+ * assert(result == GHOSTTY_SUCCESS);
+ * ghostty_key_event_set_action(event, GHOSTTY_KEY_ACTION_PRESS);
+ * ghostty_key_event_set_key(event, GHOSTTY_KEY_C);
+ * ghostty_key_event_set_mods(event, GHOSTTY_MODS_CTRL);
+ *
+ * // Encode the key event
+ * char buf[128];
+ * size_t written = 0;
+ * result = ghostty_key_encoder_encode(encoder, event, buf, sizeof(buf), &written);
+ * assert(result == GHOSTTY_SUCCESS);
+ *
+ * // Use the encoded sequence (e.g., write to terminal)
+ * fwrite(buf, 1, written, stdout);
+ *
+ * // Cleanup
+ * ghostty_key_event_free(event);
+ * ghostty_key_encoder_free(encoder);
+ * return 0;
+ * }
+ * @endcode
+ *
+ * For a complete working example, see example/c-vt-key-encode in the
+ * repository.
+ *
* @{
*/
@@ -949,6 +1006,48 @@ void ghostty_key_encoder_setopt(GhosttyKeyEncoder encoder, GhosttyKeyEncoderOpti
* @param out_len Pointer to store the number of bytes written (may be NULL)
* @return GHOSTTY_SUCCESS on success, GHOSTTY_OUT_OF_MEMORY if buffer too small, or other error code
*
+ * ## Example: Calculate required buffer size
+ *
+ * @code{.c}
+ * // Query the required size with a NULL buffer (always returns OUT_OF_MEMORY)
+ * size_t required = 0;
+ * GhosttyResult result = ghostty_key_encoder_encode(encoder, event, NULL, 0, &required);
+ * assert(result == GHOSTTY_OUT_OF_MEMORY);
+ *
+ * // Allocate buffer of required size
+ * char *buf = malloc(required);
+ *
+ * // Encode with properly sized buffer
+ * size_t written = 0;
+ * result = ghostty_key_encoder_encode(encoder, event, buf, required, &written);
+ * assert(result == GHOSTTY_SUCCESS);
+ *
+ * // Use the encoded sequence...
+ *
+ * free(buf);
+ * @endcode
+ *
+ * ## Example: Direct encoding with static buffer
+ *
+ * @code{.c}
+ * // Most escape sequences are short, so a static buffer often suffices
+ * char buf[128];
+ * size_t written = 0;
+ * GhosttyResult result = ghostty_key_encoder_encode(encoder, event, buf, sizeof(buf), &written);
+ *
+ * if (result == GHOSTTY_SUCCESS) {
+ * // Write the encoded sequence to the terminal
+ * write(pty_fd, buf, written);
+ * } else if (result == GHOSTTY_OUT_OF_MEMORY) {
+ * // Buffer too small, written contains required size
+ * char *dynamic_buf = malloc(written);
+ * result = ghostty_key_encoder_encode(encoder, event, dynamic_buf, written, &written);
+ * assert(result == GHOSTTY_SUCCESS);
+ * write(pty_fd, dynamic_buf, written);
+ * free(dynamic_buf);
+ * }
+ * @endcode
+ *
* @ingroup key
*/
GhosttyResult ghostty_key_encoder_encode(GhosttyKeyEncoder encoder, GhosttyKeyEvent event, char *out_buf, size_t out_buf_size, size_t *out_len);