Design a Custom ESP32 Board in KiCad + Order from JLCPCB

Build a custom ESP32-S3 development board from scratch using KiCad 9 and order assembled PCBs from JLCPCB. This step-by-step tutorial covers schematic entry with an ESP32-S3-WROOM module, USB-C power and programming, PCB layout with antenna keep-out zones, and generating production-ready Gerber and assembly files.

Intermediate · 4 hours · 8 steps

What You Need

Reference design — study its schematic for proven ESP32-S3 circuit design

Step-by-Step Instructions

  1. Step 1 Install KiCad and Set Up the Project

    Download KiCad 9 from kicad.org — it is free and open-source, available for Windows, macOS, and Linux. Install the full package including the symbol and footprint libraries (roughly 4GB total download).

    Create a new project: File > New Project. Name it something descriptive like "esp32s3-custom-board". KiCad creates a .kicad_pro project file, a .kicad_sch schematic file, and a .kicad_pcb board file. Keep everything in a single directory.

    Install the JLCPCB Fabrication Toolkit plugin: open Plugin and Content Manager from the KiCad main window, search for "JLCPCB", and install it. This plugin will generate perfectly formatted Gerbers, BOM, and CPL files for JLCPCB ordering later. Also install the "Interactive HTML BOM" plugin — it generates a visual assembly guide that is invaluable for hand-soldering.

    Tip: Create a Git repository for your project directory from day one. KiCad files are text-based and diff well in version control. Commit after each major milestone (schematic complete, layout complete, DRC clean) so you can revert mistakes without starting over.
  2. Step 2 Create the Schematic: ESP32-S3-WROOM Module

    Open the schematic editor and place the ESP32-S3-WROOM-1 symbol from KiCad's built-in Espressif library. This module integrates the ESP32-S3 dual-core Xtensa LX7 processor, 16MB flash, 8MB PSRAM (on the -N16R8 variant), 40MHz crystal, and PCB antenna in an 18x25.5mm package.

    The module has 39 pins exposed as castellated pads. You need to connect: 3V3 (pin 2) to your regulated power supply, GND (pins 1, 40, 41) to ground, EN (pin 3) to a 10K pull-up to 3V3 with a reset button to ground, GPIO0 (pin 27) to a 10K pull-up to 3V3 with a boot button to ground, and GPIO19/GPIO20 (pins 13/14) to the USB-C connector's D-/D+ lines for USB programming via the built-in USB-Serial/JTAG peripheral.

    Add 100nF ceramic decoupling capacitors on the 3V3 pin — place at least two, one close to pin 2 and one close to pin 39. Add a 10uF bulk capacitor near the module as well. These capacitors prevent brownouts during WiFi transmit bursts, which draw 310mA peak current. Insufficient decoupling is the number-one cause of mysterious ESP32 resets.

    Tip: Download the official ESP32-S3-DevKitC-1 schematic from Espressif's GitHub as a reference. It shows the proven power filtering, USB, and bootstrap circuit that Espressif uses on their own development boards.
  3. Step 3 Add Power Regulation and USB-C Connector

    Place a USB-C connector symbol (use the USB_C_Receptacle_USB2.0 symbol from KiCad's Connector library for a 16-pin USB 2.0 type). Connect VBUS to your voltage regulator input, and D+/D- to the ESP32-S3's GPIO19/GPIO20 through 22-ohm series resistors (USB impedance matching). Add CC1 and CC2 pins with 5.1K pull-down resistors to GND — these tell the USB host that your device wants 5V power delivery.

    For the 5V-to-3.3V regulator, use an AMS1117-3.3 (SOT-223 package) or the more efficient AP2112K-3.3 (SOT-23-5). The AMS1117 is ubiquitous and costs $0.02 on LCSC; the AP2112K has lower dropout voltage (250mV vs 1.1V) and lower quiescent current (55uA vs 5mA), making it better for battery-powered designs. Connect a 10uF capacitor on the input and a 10uF capacitor on the output per the datasheet. Add a Schottky diode (SS34 or equivalent) on VBUS for reverse polarity protection if your board might also be powered via an external DC jack.

    Add a power LED: 3V3 through a 1K resistor to a green 0603 LED to GND. This confirms the regulator is working. Add a user-controllable LED on a free GPIO (e.g., GPIO48 which is often the built-in LED on ESP32-S3 devkits): GPIO through a 470-ohm resistor to a blue 0603 LED to GND.

    Tip: The ESP32-S3 draws up to 310mA during WiFi TX bursts and up to 500mA if using WiFi and Bluetooth simultaneously. Make sure your regulator can deliver at least 600mA continuous. The AMS1117 handles 1A, the AP2112K handles 600mA — both are sufficient.
  4. Step 4 Complete the Schematic and Run ERC

    Add any peripheral circuits your board needs. Common additions for a general-purpose ESP32-S3 board: a 2x20 pin header breaking out all available GPIOs (standard 2.54mm pitch, through-hole for durability), a Qwiic/STEMMA QT connector (JST-SH 4-pin, 1mm pitch) on the I2C bus (GPIO8 SDA, GPIO9 SCL with 4.7K pull-ups), and an SD card slot on the SPI bus (GPIO10-13) for data logging.

    Add net labels for all power rails: 5V_USB, 3V3, GND. Label signal nets with descriptive names: SDA, SCL, MOSI, MISO, SCK, CS_SD. This makes the schematic readable and the PCB layout much easier to follow.

    Assign footprints to every symbol: open Tools > Assign Footprints. The ESP32-S3-WROOM-1 uses the RF_Module:ESP32-S3-WROOM-1 footprint. Resistors and capacitors use 0603 (1608 metric) for hand solderability. The USB-C connector footprint must match the specific part you plan to use — verify pin-to-pad mapping against the component datasheet. This is the most common source of first-revision errors.

    Run Inspect > Electrical Rules Check. Fix every error. Common issues: unconnected power pins (add power flags), bidirectional pin conflicts on the USB data lines (add no-connect flags if intentional), and missing GND connections. A clean ERC with zero errors and zero warnings is the goal.

    Tip: KiCad's ERC sometimes flags ESP32 module pins as unconnected when they are internally connected inside the module (like multiple GND pins). These are safe to add "no-connect" flags to. But verify against the module's pin list first — do not blindly suppress warnings.
  5. Step 5 PCB Layout: Placement and Antenna Keep-Out

    Open the PCB editor and import the netlist from the schematic (Tools > Update PCB from Schematic). All component footprints appear in a cluster — you will arrange them manually.

    Draw the board outline on the Edge.Cuts layer. For a first custom board, 60x40mm gives adequate space for an ESP32-S3-WROOM module, USB-C connector, voltage regulator, and GPIO headers. The ESP32-S3-WROOM-1 module is 18x25.5mm — it will dominate the board.

    Place the ESP32-S3-WROOM module first. Critical rule: the antenna end of the module must overhang the board edge or have a ground-plane-free keep-out zone extending at least 15mm from the antenna. Copper (ground planes, traces, even other components) near the antenna detunes it and degrades WiFi range by 3-6dB — that is a 50-75% reduction in effective range. Place the module at the top edge of the board with the antenna extending beyond the board outline, or leave a 15x18mm copper-free rectangle in front of the antenna.

    Place the USB-C connector on the opposite edge from the antenna. Put the voltage regulator between the USB connector and the ESP32 module, with input capacitors near the USB power pins and output capacitors near the module's 3V3 pins. Place decoupling capacitors within 3mm of the module's power pins — closer is always better. GPIO headers go along the long edges.

    Tip: Use KiCad's 3D viewer (View > 3D Viewer) frequently during layout. It shows component heights and physical clearances that the 2D view hides. Verify the USB-C connector will be accessible after the board is enclosed, and that tall components do not interfere with header pins.
  6. Step 6 Route Traces and Add Ground Pour

    Set up design rules before routing: Track width 0.25mm (10mil) for signals, 0.5mm for power traces carrying over 200mA, 1.0mm for the main 5V and 3V3 power rail runs. Via size 0.6mm outer diameter with 0.3mm drill — this is within JLCPCB's standard capabilities. Clearance 0.15mm (6mil) minimum.

    Route the USB data lines first. D+ and D- traces must be the same length (within 0.5mm) and routed as a differential pair with 90-ohm differential impedance. On a standard 1.6mm FR4 2-layer board, 0.2mm traces with 0.15mm gap achieve approximately 90-ohm differential impedance. Keep USB traces short (under 50mm total), avoid vias, and do not route them near power traces or switching components.

    Route power traces next: VBUS from USB-C to the voltage regulator input, 3V3 from regulator output to the ESP32 module and all peripheral power pins. Use 0.5mm or wider traces for these. Then route all signal traces: I2C, SPI, GPIO breakouts. Use the back copper layer for crossing traces, placing vias where needed.

    After all traces are routed, add a ground pour on the back copper layer: Place > Add Filled Zone, select B.Cu layer, assign to GND net, click around the board outline. This creates a solid copper ground plane that provides excellent signal return paths and reduces EMI. Add a ground pour on the front layer too, around the ESP32 module area, to improve grounding — but keep it out of the antenna keep-out zone. Run Design Rules Check (DRC) and fix every violation.

    Tip: Route the antenna keep-out zone first by placing a rule area on both copper layers that prohibits copper fill. In KiCad: Place > Rule Area, select both F.Cu and B.Cu, check "Keep out copper fill" and "Keep out tracks". This prevents accidental ground pour or traces from creeping into the antenna zone during layout.
  7. Step 7 Generate Gerbers, BOM, and CPL for JLCPCB

    With a clean DRC (zero errors), generate manufacturing files. If you installed the JLCPCB Fabrication Toolkit plugin, click its icon in the toolbar. It generates a ZIP containing all Gerber layers, drill files, BOM, and CPL in JLCPCB's exact format — no manual configuration needed. The ZIP is saved in your project directory under a "production" subfolder.

    If generating manually: File > Fabrication Outputs > Gerbers. Select layers: F.Cu, B.Cu, F.Mask, B.Mask, F.Silkscreen, B.Silkscreen, Edge.Cuts. Check "Use Protel filename extensions" for maximum compatibility. Generate. Then File > Fabrication Outputs > Drill Files: Excellon format, millimeters, PTH and NPTH in separate files. ZIP all output files together.

    For assembly, the BOM must include LCSC part numbers for every component. Open the schematic editor, add an LCSC field to each component with the part number from lcsc.com (e.g., C14663 for a 100nF 0603 capacitor, C2040 for the ESP32-S3-WROOM-1-N16R8). The JLCPCB plugin reads these fields automatically. The CPL file contains X/Y coordinates and rotation for each component — the plugin generates this from the PCB layout.

    Verify files before uploading: open the Gerber ZIP in KiCad's Gerber Viewer (or jlcpcb.com's online viewer) and confirm all layers look correct. Check that the board outline is closed, pads are exposed through soldermask openings, and silkscreen text is readable.

    Tip: JLCPCB's component library distinguishes between "Basic" parts (no extra fee, always in stock) and "Extended" parts ($3 surcharge per unique extended part). The ESP32-S3-WROOM module, AMS1117-3.3, and common passives are Basic. Check the LCSC part page before finalizing your BOM to avoid surprise charges.
  8. Step 8 Upload to JLCPCB and Review the Order

    Go to jlcpcb.com and click "Quote Now." Upload your Gerber ZIP file. JLCPCB auto-detects board dimensions, layer count, and minimum trace/space. Verify the detected parameters: 2 layers, your board dimensions (e.g., 60x40mm), 1.6mm thickness, FR4, 1oz copper, HASL finish, green soldermask. The base price for 5 boards at these specs is $2.

    Scroll down to the SMT Assembly section and enable it. Select which side to assemble (typically top only for a first board). Upload your BOM and CPL files. JLCPCB's system matches your LCSC part numbers to their inventory and shows a component-by-component breakdown with prices and stock status. Review each line item — verify the correct package size, value, and orientation.

    The assembly preview shows a render of your board with all components placed. Check that component orientations are correct — the JLCPCB plugin handles rotation offsets automatically, but verify visually. Pin 1 indicators on ICs and polarity markers on capacitors should match the schematic. Assembly setup fee is $8, plus per-component costs (typically $0.001-0.01 per passive, $2-4 for the ESP32 module).

    Choose shipping: DHL Express (3-5 days, $15-20) or standard (7-12 days, $5-8). For US orders, budget an additional $8-15 for import duties under current tariff rules. Place the order. Production typically takes 1-3 days for the PCB plus 2-4 days for assembly. You will receive photos of the first assembled board for approval before they complete the full batch.

    Tip: Order 5-10 boards even if you only need one. The per-board cost is negligible, and having spares lets you rework or test destructively without waiting for another order. Assembly minimum is typically 5 boards — you cannot order assembly for just 1.

Frequently Asked Questions

How big should the antenna keep-out zone be on an ESP32 board?

At least 15mm from the end of the ESP32-WROOM or ESP32-S3-WROOM module's antenna, clear of copper on all layers (top, bottom, and internal). Espressif's hardware design guidelines specify no ground plane, traces, or components in this zone. Violating it typically reduces WiFi range by 50-75% (3-6dB loss). The easiest approach is to extend the antenna past the board edge entirely.

Can I use a 2-layer PCB for a custom ESP32 board?

Yes, if you use an ESP32 module (WROOM or WROVER) rather than a bare chip. The module handles all RF routing internally on its own multi-layer substrate. Your 2-layer carrier board just needs standard power distribution, GPIO routing, and a ground pour on the back layer. A 4-layer board is only necessary for bare-chip ESP32 designs.

How much does JLCPCB assembly cost for 5 ESP32 boards?

For a typical custom ESP32-S3 board with 20-30 components: $8 assembly setup fee, $2-4 per board for the ESP32-S3-WROOM module, plus $0.50-1.00 per board for passives and the voltage regulator. Total assembly cost for 5 boards is roughly $25-40 on top of the $2 bare board cost. Add $15-20 for DHL shipping plus import duties.

What KiCad version should I use?

KiCad 9 (released late 2025) is the current stable version with improved routing tools, better 3D models, and a redesigned footprint editor. KiCad 8 is also fully supported and widely documented in tutorials. Avoid KiCad 5 or earlier — the file formats are incompatible and the workflow is significantly different.

Do I need to match USB trace impedance on a 2-layer board?

For USB Full Speed (12 Mbps), which is what the ESP32-S3's USB-Serial/JTAG interface uses, trace impedance matching is recommended but not strictly required for short runs under 50mm. Keep D+ and D- traces the same length within 0.5mm, add 22-ohm series resistors, and avoid routing near noise sources. USB High Speed (480 Mbps) requires strict 90-ohm differential impedance.

What is the difference between HASL and ENIG surface finish?

HASL (Hot Air Solder Leveling) coats pads with a thin solder layer — cheapest option, but pad surfaces are slightly uneven. ENIG (Electroless Nickel Immersion Gold) deposits a flat nickel-gold layer — better for fine-pitch components like QFN packages and produces more reliable solder joints. ENIG adds $3-5 to a JLCPCB order. For a first board with 0603 passives and modules, HASL is fine.

Can I route traces under the ESP32 module?

You can route signal traces on the bottom layer under the module, but avoid routing on the top layer where the module's ground pad sits. The module's exposed ground pad should connect to a solid ground plane via thermal vias (0.3mm drill, spaced 1.2mm apart in a grid). Do not route power traces under the module — keep the area under the module as clean ground plane.