PCB design — tscircuit
UnreviewedDesign and generate complete PCB circuit boards using tscircuit (React/TypeScript). Use when the user asks to create a PCB, circuit board, schematic, breakout board, Arduino/ESP32 shield, sensor modul
name: pcb-design
description: Design and generate complete PCB circuit boards using tscircuit (React/TypeScript). Use this skill whenever the user asks to create a PCB, circuit board, schematic, breakout board, Arduino/ESP32 shield, sensor module, or any electronics hardware project. Also trigger when the user mentions tscircuit, KiCad export, Gerber files, or wants to go from an idea to a manufacturable board. Even casual requests like "make me a board for..." or "I need a PCB that..." should trigger this skill. Covers component selection, placement, routing, and export to fabrication files.
PCB Design Skill — tscircuit
Generate complete, routable PCB designs from high-level user descriptions using tscircuit, an open-source React/TypeScript electronics toolchain.
When to Use
- User asks to design a PCB, circuit board, or electronic module
- User wants a breakout board, shield, sensor module, or dev board
- User mentions tscircuit, KiCad, Gerber, or fabrication files
- User describes a circuit functionally ("I need something that reads temperature and displays it")
- User asks to modify or iterate on an existing tscircuit design
Philosophy
The user is likely an EE or maker who wants to go from idea to board fast. The goal is to produce a complete, working tscircuit project — not just a snippet. That means:
- Correct schematic connectivity — every pin that needs a connection gets one
- Proper component selection — realistic footprints, appropriate values, decoupling caps
- Thoughtful placement — components positioned with
pcbX/pcbYso the autorouter succeeds - Manufacturable output — the design should export to Gerbers and be orderable
Workflow
Step 1: Research Reference Designs
Before writing any circuit, research the manufacturer's recommended minimum viable circuit for every key IC. Do not guess component values — extract them from official sources.
For each core IC in the design:
- Find the manufacturer's hardware design guide — most MCU vendors publish one (e.g., Raspberry Pi's "Hardware Design with RP2350", Espressif's "ESP32 Hardware Design Guidelines", ST's "Getting Started with STM32" app notes)
- Download official reference design files — many manufacturers provide KiCad/Altium/Eagle files for their minimal/evaluation boards (e.g., Raspberry Pi publishes Minimal-KiCAD.zip with exact component values)
- Read the dev board schematic — the manufacturer's evaluation board (e.g., Pico 2, ESP32-DevKitC, Nucleo) is the gold standard for "known working circuit"
- Extract exact component values — capacitor values, inductor specs, resistor values, crystal load caps, and part numbers all come from these sources
- Cross-reference with community designs — Adafruit, SparkFun, and other open-source boards validate the manufacturer's recommendations
What to extract for each IC:
- Power supply requirements (all voltage domains, current draw)
- Decoupling capacitor values and placement (per-pin requirements)
- Internal regulator/SMPS external component requirements (inductors, feedback resistors, filter networks)
- Clock/oscillator circuit (crystal frequency, load cap calculation, damping resistors)
- Reset and boot mode circuits
- Any mandatory pull-ups/pull-downs
- Recommended part numbers for critical components (inductors, crystals, flash)
Where to search:
datasheets.raspberrypi.com— RP2040/RP2350 familyespressif.com/documentation— ESP32 familyst.com/resource— STM32 familyti.com— TI MCUs and power ICs- Manufacturer GitHub repos for KiCad/design files
- Web search: "[chip] hardware design guide", "[chip] minimal circuit schematic", "[dev board] schematic PDF"
Focus on the components that make the chip actually function — power, clock, flash, reset. Don't worry about connectors, LEDs, or application-specific peripherals until the core circuit is solid.
Step 2: Write Design Intent (.pdi)
Before writing any EDA-specific code, create a design intent file (design-intent.pdi) in the project folder. This is a structured, tool-agnostic representation that captures every component, its pin-level associations, and spatial grouping.
See full format spec: references/design-intent-format.md
The .pdi file must specify:
- Every power pin of the main IC with its net assignment
- Every decoupling cap tied to the specific pin it serves (not just "IOVDD" — say "decouples U1.pin22 (IOVDD)")
- Functional groups with
near U1.pin##..##placement constraints - Every connection — which pin connects to which component
- A verification checklist at the bottom confirming completeness
Structure:
board <width> x <height>
U1: <part> <package> @ center
pin## (FUNCTION) → net.<name>
...
# Per-pin decoupling
C##: <value> <footprint> decouples U1.pin## (<function>)
# Spatial groups
group <name> near U1.pin##..## {
<ref>: <value> <footprint> <connection_spec>
}
Key connection specs:
decouples <pin_ref>— bypass cap on a power pinfrom <pin/net> to <pin/net>— component in a signal pathbetween <net> and GND— component across power and groundin_series from <pin> to <pin>— series insertion (e.g., damping resistor)
After writing, verify:
- Every power pin has a decoupling cap or is documented as shared
- Every IC has power + decoupling accounted for
- Every group has a
nearclause for placement - Total BOM count matches expectation
- All values sourced from reference design (Step 1)
Then visualize by generating an interactive viewer (PCB layout + schematic as HTML in AHDV) so the user can review the design before any EDA code is written.
Step 3: Understand the Full Design
From the user's request and your reference design research, determine:
- Core ICs — microcontroller, sensors, drivers, regulators
- Interfaces — USB, I2C, SPI, UART, GPIO headers
- Power — voltage rails, regulation needs, battery vs USB power
- Form factor — board dimensions, mounting holes, connector placement
- Constraints — must-have features, pin assignments, specific parts
If the user's request is ambiguous, make reasonable EE decisions and state your assumptions clearly. Don't over-ask — design something solid and let the user iterate.
Step 4: Set Up the Project
Scaffold a complete tscircuit project using the template script. This creates all config files, dependencies, and VS Code integration:
PROJECT_NAME="esp32-bme280-board" # descriptive kebab-case name
bash /mnt/skills/user/pcb-design/scripts/scaffold.sh /home/claude/$PROJECT_NAME $PROJECT_NAME
This generates:
<project-name>/
.gitignore
.npmrc ← points @tsci scope to tscircuit registry
bunfig.toml ← disables lockfile
package.json ← scripts: dev, build, start (tsci dev -p 3024)
tscircuit.config.json ← entrypoint config
tsconfig.json ← TypeScript config with JSX support
index.tsx ← placeholder (you'll replace this)
.vscode/
settings.json ← disables auto-detection noise
tasks.json ← "Start Dev Server", "Update Dependencies" tasks
After scaffolding, immediately run bun update --latest (the script does this automatically) to ensure all tscircuit dependencies are at the latest version.
Then replace index.tsx with the actual circuit design.
Step 5: Design the Circuit
Read references/tscircuit-elements.md for the full element reference, and references/common-circuits.md for design pattern examples. Key principles:
Every design needs:
- A
<board>root element with explicitwidthandheight - Named components following standard EE refdes conventions
- Explicit
pcbX/pcbYplacement for all components <trace>elements connecting all required pins- Decoupling capacitors near every IC power pin (100nF ceramic, 0402 or 0603)
- Pull-up/pull-down resistors where the datasheet or protocol requires them (e.g., I2C needs pull-ups)
Component naming conventions:
- U1, U2... for ICs
- R1, R2... for resistors
- C1, C2... for capacitors
- L1, L2... for inductors
- D1, D2... for diodes/LEDs
- J1, J2... for connectors/headers
- SW1, SW2... for switches
- Q1, Q2... for transistors
Placement strategy:
- Place the main IC at or near center (0, 0)
- Group related components near their IC
- Keep decoupling caps within 2-3mm of their IC's power pins
- Place connectors at board edges
- Leave ~2mm clearance from board edges
- Space components enough for the autorouter (minimum ~2mm between unrelated parts)
Step 6: Deliver to User
Create a complete, self-contained project folder and present it. The user should be able to download the folder, run bun update --latest && bun run start, and see their board.
- Copy source files only from
/home/claude/<project-name>/to/mnt/user-data/outputs/<project-name>/— never copynode_modules/(it's 400MB+ and the user will runbun update --latestthemselves) - Write a
README.mdin that folder containing:- Project name and one-line description
- Design assumptions (voltages, interfaces, component choices)
- Bill of Materials summary (component, value, footprint, quantity)
- How to run:
bun update --latest, thenbun run start - Pin mapping / net summary for the user's firmware
- Any known limitations or things the user should verify
- Use
present_filesto share the key output files (index.tsx, README.md) with the user
Example delivery commands:
# Create output directory with .vscode subfolder
mkdir -p /mnt/user-data/outputs/esp32-bme280-board/.vscode
# Copy source files ONLY — never use cp -r on the project root (leaks node_modules)
for f in package.json tsconfig.json tscircuit.config.json bunfig.toml .npmrc .gitignore index.tsx README.md; do
cp "/home/claude/esp32-bme280-board/$f" "/mnt/user-data/outputs/esp32-bme280-board/$f"
done
cp /home/claude/esp32-bme280-board/.vscode/*.json /mnt/user-data/outputs/esp32-bme280-board/.vscode/
The output folder will contain:
/mnt/user-data/outputs/esp32-bme280-board/
.gitignore
.npmrc
bunfig.toml
package.json
tscircuit.config.json
tsconfig.json
index.tsx ← the actual circuit design
README.md ← design notes, BOM, instructions
.vscode/
settings.json
tasks.json
⚠️ Never include node_modules/ in the output. The user installs dependencies themselves with bun update --latest.
tscircuit Quick Reference
Core Elements
// Board — root container, everything goes inside
<board width="50mm" height="40mm">
{/* components and traces */}
</board>
// Resistor — non-polar, 2 pins: pin1/pin2 (aliases: pos/neg)
<resistor name="R1" resistance="10k" footprint="0402" pcbX={5} pcbY={3} />
// Capacitor — 2 pins: pin1/pin2 (aliases: pos/neg for polarized)
<capacitor name="C1" capacitance="100nF" footprint="0402" pcbX={2} pcbY={1} />
// LED — 2 pins: anode(pos)/cathode(neg)
<led name="LED1" footprint="0603" color="green" pcbX={10} pcbY={0} />
// Diode
<diode name="D1" footprint="sot23" pcbX={0} pcbY={5} />
// Generic IC via <chip> — the workhorse element
<chip
name="U1"
footprint="soic8"
pinLabels={{
pin1: "VCC", pin2: "OUT", pin3: "NC", pin4: "GND",
pin5: "TRG", pin6: "THR", pin7: "DIS", pin8: "RST"
}}
connections={{ // shorthand for traces
VCC: "net.VCC",
GND: "net.GND",
}}
pcbX={0} pcbY={0}
/>
// Pin header — for GPIO breakout, programming, etc.
<pinheader name="J1" pinCount={6} pitch="2.54mm" pcbX={-20} pcbY={0} />
// Traces — connect pins together
<trace from=".R1 > .pin1" to=".U1 > .OUT" /> // direct pin-to-pin
<trace from=".C1 > .pin1" to="net.GND" /> // connect to named net
Footprint Strings
| Type | Examples |
|---|---|
| Passives | 0402, 0603, 0805, 1206 |
| SOIC | soic8, soic14, soic16, soic16_w7mm_p0.8mm |
| QFP/TQFP | qfp32, qfp48, tqfp32, tqfp48 |
| QFN | qfn20, qfn24, qfn32, qfn24_w6_h6_p0.8mm |
| BGA | bga9, bga16, bga16_p2mm |
| TSSOP/SSOP | tssop8, tssop16, tssop20, ssop8 |
| SOT | sot23, sot23_5, sot223 |
| DIP | dip8, dip14, dip16, dip8_wide |
| Pin rows | pinrow4, pinrow8, pinrow10 |
| TO packages | to92, to220 |
| Stampboard | stampboard (for module-style packages) |
Trace Addressing
".ComponentName > .pinLabel" — by label (preferred when pinLabels are set)
".ComponentName > .pin1" — by pin number
"net.VCC" — named power net
"net.GND" — ground net
"net.SDA" — named signal net
Reusable Subcomponents
import type { CommonLayoutProps } from "tscircuit"
interface RegProps extends CommonLayoutProps {
name: string
}
export const AMS1117_3V3 = (props: RegProps) => (
<chip
footprint="sot223"
pinLabels={{ pin1: "GND", pin2: "VOUT", pin3: "VIN" }}
{...props}
/>
)
Board Options
<board
width="50mm"
height="40mm"
layers={4} // 2 (default) or 4 layer stackup
defaultTraceWidth="0.25mm"
minTraceWidth="0.15mm"
autorouter="auto-cloud" // use for >50 traces
borderRadius="2mm" // rounded corners
>
Critical Design Rules
Always research before designing. Every IC has specific power supply requirements, decoupling needs, and support circuitry. The datasheet and manufacturer's reference design are the source of truth — not generic rules of thumb. Download official design files when available.
Use datasheet-specified decoupling. The generic "100nF per VCC pin" is a starting point, but many ICs specify exact values per pin. For example, RP2350B needs 100nF per IOVDD pin, but 4.7µF for DVDD and specific RC filtering on VREG_AVDD. Always check the datasheet.
Internal regulators need exact external components. Many modern MCUs (RP2350, STM32, nRF52) have internal switching regulators that require specific inductors, capacitors, and feedback networks. These values are NOT interchangeable — use exactly what the datasheet specifies (e.g., RP2350 needs a 3.3µH polarized inductor with ≤250mΩ DCR).
I2C buses need pull-ups. Add 4.7kΩ resistors on SDA and SCL to VCC. Lower values (2.2k) for faster buses or longer traces.
Use net-based traces for power. Connect all power pins via
net.VCC/net.GNDrather than chaining direct traces. This lets the autorouter find optimal paths.Size the board generously for simple designs. It's easier to shrink a working board than to debug a cramped one. Start with plenty of room.
Reset and enable pins matter. Check the datasheet for recommended pull-up values — they vary by chip (e.g., RP2350 uses 1kΩ on RUN, ESP32 uses 10kΩ on EN with an RC filter).
Crystal/oscillator placement. Keep crystals within 5mm of the MCU, with load capacitors placed symmetrically. Always calculate load cap values from the crystal's specified load capacitance: C_load = 2 × (C_crystal_load - C_stray). Include a series damping resistor if the datasheet recommends one (e.g., RP2350 uses 1kΩ).
USB connector placement. Put USB connectors at the board edge with the receptacle flush or slightly overhanging. USB D+/D- lines may need series resistors (e.g., RP2350 uses 27Ω).
Module footprints. ESP32-WROOM, ESP32-S3, and similar WiFi/BLE modules use a castellated pad footprint. In tscircuit, use
stampboardas a working placeholder — it gives you the right pin count and general shape. For production, import the exact footprint from the tscircuit registry (@tsci/username.esp32-wroom) or use a KiCad footprint (footprint="kicad:RF_Module/ESP32-WROOM-32"). Note this clearly in the README as a pre-production step.
Project Specific Instructions
tscircuit uses bun, so the correct command to run the dev server is bun run start, not npm run dev or npm start.
Critical: Always run bun update --latest immediately after scaffolding a project. This ensures all tscircuit packages are at the latest version. The scaffold script does this automatically, but if it fails (e.g., in a restricted network environment), remind the user to run it manually.
When writing README files or explaining next steps to the user, always use:
# First time setup (in the project directory)
bun update --latest # update all tscircuit dependencies to latest
# Launch dev server with live PCB/schematic/3D preview
bun run start
Other useful tscircuit CLI commands:
tsci export gerber # export Gerber fabrication files
tsci export bom # export Bill of Materials
tsci export pnp # export Pick-and-Place file
Reference Files
references/tscircuit-elements.md— Detailed element API reference (read for unfamiliar elements)references/common-circuits.md— Complete design patterns: power, MCU, sensors, USB, LEDs