diff --git a/boards.txt b/boards.txt
index ccb32b95da3..6c197120d33 100644
--- a/boards.txt
+++ b/boards.txt
@@ -50361,3 +50361,60 @@ cyobot_v2_esp32s3.menu.ZigbeeMode.zczr.build.zigbee_mode=-DZIGBEE_MODE_ZCZR
 cyobot_v2_esp32s3.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api.zczr -lzboss_stack.zczr -lzboss_port.remote
 
 ##############################################################
+
+kodedot.name=kode dot
+
+kodedot.bootloader.tool=esptool_py
+kodedot.bootloader.tool.default=esptool_py
+
+kodedot.upload.tool=esptool_py_nomerge
+kodedot.upload.tool.default=esptool_py_nomerge
+kodedot.upload.tool.network=esp_ota
+
+kodedot.upload.maximum_size=8388608
+kodedot.upload.maximum_data_size=327680
+kodedot.upload.flags=
+kodedot.upload.extra_flags=
+kodedot.upload.use_1200bps_touch=false
+kodedot.upload.wait_for_upload_port=false
+kodedot.upload.speed=921600
+
+kodedot.upload.erase_cmd=
+
+kodedot.serial.disableDTR=false
+kodedot.serial.disableRTS=false
+
+kodedot.build.tarch=xtensa
+kodedot.build.bootloader_addr=0x0
+kodedot.build.target=esp32s3
+kodedot.build.mcu=esp32s3
+kodedot.build.core=esp32
+kodedot.build.variant=kodedot
+kodedot.build.board=KODE_DOT
+
+kodedot.build.usb_mode=1   
+kodedot.build.cdc_on_boot=1   
+kodedot.build.msc_on_boot=0
+kodedot.build.dfu_on_boot=0
+
+kodedot.build.f_cpu=240000000L
+
+kodedot.build.flash_offset=0x400000
+kodedot.build.flash_size=16MB
+kodedot.build.flash_freq=80m
+kodedot.build.flash_mode=dio
+
+kodedot.build.partitions=kodedot_partitions
+
+kodedot.build.psram_type=qspi
+kodedot.build.defines=
+
+kodedot.build.loop_core=-DARDUINO_RUNNING_CORE=1
+kodedot.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=1
+
+kodedot.recipe.hooks.objcopy.postobjcopy.3.pattern=
+kodedot.recipe.hooks.objcopy.postobjcopy.3.pattern_args=
+
+kodedot.recipe.output.save_file={build.project_name}.ino.bin
+
+##############################################################
diff --git a/platform.txt b/platform.txt
index 65be05b3bf4..f2287c390ab 100644
--- a/platform.txt
+++ b/platform.txt
@@ -330,3 +330,17 @@ tools.dfu-util.cmd=dfu-util
 tools.dfu-util.upload.params.verbose=-d
 tools.dfu-util.upload.params.quiet=
 tools.dfu-util.upload.pattern="{path}/{cmd}" --device {vid.0}:{pid.0} -D "{build.path}/{build.project_name}.bin" -Q
+
+## --------------------------------------------------------------------------
+## Custom tool for Kode Dot: esptool_py_nomerge
+## --------------------------------------------------------------------------
+tools.esptool_py_nomerge.path={runtime.tools.esptool_py.path}
+tools.esptool_py_nomerge.cmd=esptool
+tools.esptool_py_nomerge.cmd.windows=esptool.exe
+
+tools.esptool_py_nomerge.upload.protocol=serial
+tools.esptool_py_nomerge.upload.params.verbose=
+tools.esptool_py_nomerge.upload.params.quiet=
+
+tools.esptool_py_nomerge.upload.pattern_args=--chip {build.mcu} --port "{serial.port}" --baud {upload.speed} {upload.flags} --before default_reset --after hard_reset write_flash --flash_mode {build.flash_mode} --flash_freq {build.flash_freq} --flash_size {build.flash_size} {build.flash_offset} "{build.path}/{build.project_name}.bin" {upload.extra_flags}
+tools.esptool_py_nomerge.upload.pattern="{path}/{cmd}" {tools.esptool_py_nomerge.upload.pattern_args}
diff --git a/tools/partitions/kodedot_partitions.csv b/tools/partitions/kodedot_partitions.csv
new file mode 100644
index 00000000000..fd5c5ce4f06
--- /dev/null
+++ b/tools/partitions/kodedot_partitions.csv
@@ -0,0 +1,7 @@
+# Name,   Type, SubType, Offset,  Size, Flags
+nvs,      data, nvs,     0x9000,  0x6000,
+phy_init, data, phy,     0xf000,  0x1000,
+otadata,  data, ota,     0x10000, 0x2000,
+ota_0,  app,  ota_0, 0x20000, 0x3E0000,
+ota_1,  app,  ota_1,   0x400000, 0x800000,
+storage,  data, spiffs,  0xC00000, 0x400000,
\ No newline at end of file
diff --git a/variants/kodedot/custom_ota_override.cpp b/variants/kodedot/custom_ota_override.cpp
new file mode 100644
index 00000000000..f86daa0b526
--- /dev/null
+++ b/variants/kodedot/custom_ota_override.cpp
@@ -0,0 +1,5 @@
+extern "C" bool verifyRollbackLater() {
+    // Returning true prevents the OTA image from being marked as valid
+    // until you explicitly confirm it after the first boot.
+    return true;
+}
\ No newline at end of file
diff --git a/variants/kodedot/pins_arduino.h b/variants/kodedot/pins_arduino.h
new file mode 100644
index 00000000000..63847a538d9
--- /dev/null
+++ b/variants/kodedot/pins_arduino.h
@@ -0,0 +1,107 @@
+/*
+  ────────────────────────────────────────────────────────────────────────
+  KodeDot – ESP32-S3R8  Variant
+  Pin definition file for the Arduino-ESP32 core
+  ────────────────────────────────────────────────────────────────────────
+  * External 2 × 10 connector → simple aliases  PIN1 … PIN20
+  * On-board QSPI LCD 410×502 @40 MHz  (SPI3_HOST)
+  * micro-SD on SPI2_HOST
+  * Dual-I²C:  external (GPIO37/36)  +  internal-sensors (GPIO48/47)
+  * USB VID/PID 0x303A:0x1001
+*/
+
+#ifndef Pins_Arduino_h
+#define Pins_Arduino_h
+
+#include <stdint.h>
+#include <stdbool.h>
+
+/*──────────────── USB device descriptor ────────────────*/
+#define USB_VID 0x303A         // Espressif Systems VID
+#define USB_PID 0x1001         // Product ID: KodeDot-S3
+
+/*──────────────── UART0 (Arduino Serial) ────────────────*/
+static const uint8_t TX = 43;  // U0TXD – PIN16 on the 2×10 header
+static const uint8_t RX = 44;  // U0RXD – PIN18 on the 2×10 header
+
+/*──────────────── I²C buses ─────────────────────────────*/
+/* External expansion bus → header pins 11/13 */
+static const uint8_t SCL = 37; // GPIO37 – PIN12
+static const uint8_t SDA = 36; // GPIO36 – PIN14
+
+/* Internal sensor/touch bus (not on header) */
+#define INT_I2C_SCL 47         // GPIO47
+#define INT_I2C_SDA 48         // GPIO48
+
+/*──────────────── SPI2 – micro-SD ───────────────────────*/
+static const uint8_t SS   = 15; // SD_CS
+static const uint8_t MOSI = 16; // SD_MOSI
+static const uint8_t MISO = 18; // SD_MISO
+static const uint8_t SCK  = 17; // SD_CLK
+#define BOARD_HAS_SD_SPI
+#define SD_CS SS
+
+/*──────────────── QSPI LCD (SPI3_HOST) ─────────────────–
+ * Controller: ST7789 / 4-line SPI (no D/C pin)
+ * Resolution: 410×502 px, 16 bpp, RGB color-space
+ * Clock:      40 MHz
+ */
+#define BOARD_HAS_SPI_LCD
+#define LCD_MODEL             ST7789
+#define LCD_WIDTH             410
+#define LCD_HEIGHT            502
+
+#define LCD_HOST              SPI3_HOST
+#define LCD_SCK               35  // GPIO35  • QSPI_CLK
+#define LCD_MOSI              33  // GPIO33  • QSPI_IO0 (D0)
+#define LCD_IO1               34  // GPIO34  • QSPI_IO1 (D1)
+#define LCD_IO2               37  // GPIO37  • QSPI_IO2 (D2)
+#define LCD_IO3               36  // GPIO36  • QSPI_IO3 (D3)
+#define LCD_CS                10  // GPIO10
+#define LCD_RST                9  // GPIO09
+#define LCD_DC               -1   // not used in 4-line SPI
+/* Optional: back-light enable shares the NeoPixel pin */
+#define LCD_BL                 5  // GPIO05 (same as NEOPIXEL)
+
+/*──────────────── Analogue / Touch pads ────────────────*/
+static const uint8_t A0 = 11;  // PIN4  – GPIO11 / TOUCH11 / ADC2_CH0
+static const uint8_t A1 = 12;  // PIN6  – GPIO12 / TOUCH12 / ADC2_CH1
+static const uint8_t A2 = 13;  // PIN8  – GPIO13 / TOUCH13 / ADC2_CH2
+static const uint8_t A3 = 14;  // PIN10 – GPIO14 / TOUCH14 / ADC2_CH3
+static const uint8_t T0 = A0, T1 = A1, T2 = A2, T3 = A3;
+
+/*──────────────── On-board controls & indicator ─────────*/
+#define BUTTON_TOP        0      // GPIO00 – BOOT    • active-LOW
+#define BUTTON_BOTTOM     6      // GPIO06           • active-LOW
+#define NEOPIXEL_PIN      5      // GPIO05 – WS2812
+#define LED_BUILTIN       NEOPIXEL_PIN
+
+/*──────────────── JTAG (also on connector) ──────────────*/
+#define MTCK 39   // PIN11 – GPIO39
+#define MTDO 40   // PIN13 – GPIO40
+#define MTDI 41   // PIN15 – GPIO41
+#define MTMS 42   // PIN17 – GPIO42
+
+/*──────────────── 2×10 header: simple aliases ───────────
+   NOTE: power pins (1 = 5 V, 2 = 3 V3, 19/20 = GND) are **not**
+         exposed as GPIO numbers – they remain undefined here. */
+#define PIN3   1   // GPIO01 / TOUCH1 / ADC1_CH0
+#define PIN4  11   // GPIO11 / TOUCH11 / ADC2_CH0
+#define PIN5   2   // GPIO02 / TOUCH2 / ADC1_CH1
+#define PIN6  12   // GPIO12 / TOUCH12 / ADC2_CH1
+#define PIN7   3   // GPIO03 / TOUCH3 / ADC1_CH2
+#define PIN8  13   // GPIO13 / TOUCH13 / ADC2_CH2
+#define PIN9   4   // GPIO04 / TOUCH4 / ADC1_CH3
+#define PIN10 14   // GPIO14 / TOUCH14 / ADC2_CH3
+#define PIN11 39   // MTCK
+#define PIN12 37   // SCL  (external I²C)
+#define PIN13 40   // MTDO
+#define PIN14 36   // SDA  (external I²C)
+#define PIN15 41   // MTDI
+#define PIN16 43   // TX  (U0TXD)
+#define PIN17 42   // MTMS
+#define PIN18 44   // RX  (U0RXD)
+/* PIN1, PIN2, PIN19, PIN20 are power/ground and deliberately
+   left undefined – they are **not** usable as GPIO. */
+
+#endif /* Pins_Arduino_h */