Skip to the content
PCBKitNew board
2 layers145 × 100 mmShowerController, the printed circuit board in 3D

Convert KiCad PCB designs into CNC GCode for isolation-engraving traces on copper-clad board and drilling through-holes — entirely in the browser.

Size
145 × 100 mm
Copper layers
2
Thickness
1.6 mm
Parts
22
Nets
70
Pads
139
Tracks, vias
217, 24
Routed
Yes
KiCad
KiCad 6 (file 20211014)
Created
27 Jul 2026
Updated
5 Nov 2026

Overview

ShowerController is an open-source printed circuit board by grserwe, from the grserwe/KiCadToGCodeSvelte repository on GitHub. It is a 2-layer board of 145 × 100 mm with 22 parts on 70 nets, routed with 217 tracks and 24 vias.

It is built around the L7805 and TXS0108EPW. Its parts include 6 ICs, 5 connectors and 2 capacitors. It belongs with the ESP32 boards of this library.

Main components

2

README

README.md

KiCadToGCode (SvelteKit)

Live at kicadtogcode.com — free, no sign-up, and your design never leaves your browser.

Convert KiCad PCB designs into CNC GCode for isolation-engraving traces on copper-clad board and drilling through-holes — entirely in the browser. This app replaced the original Blazor version (grserwe/KiCadToGCode) on the same domain.

Features

  • Accepts a .kicad_pcb file (KiCad 4 through 10) or a zipped KiCad project
  • Isolation-routing GCode for top and bottom copper, tool-diameter/V-bit aware, multi-pass with stepover
  • Drill GCode grouped per drill size, plus registration holes for double-sided flip-over machining (bottom side mirrored about the vertical centerline)
  • Board cutout GCode: an end mill follows the Edge.Cuts outline (lines, arcs, circles, rectangles, polygons — chained into closed loops, with inner cutouts cut first) offset by the cutter radius, climb milling in depth passes, leaving holding tabs on the straight edges
  • All pad shapes: circle, oval, rect, roundrect (incl. chamfered), trapezoid, and custom polygon (e.g. hexagonal) pads; ground pads get thermal-relief gaps
  • SVG preview of both board sides: copper, engraving paths, drills, registration holes, zoom/pan
  • GCode viewer: replays each generated program the way a GRBL controller would, drawing cuts at the tool's real width, rapids, and plunges over the designed copper (mapped into machine coordinates), with a move-by-move step-through and checks for rapids with the tool down, inconsistent arcs, cutting with the spindle off, and missing feed rates or units
  • Configurable CNC settings (feeds, speeds, depths, origin, units), persisted in the browser
  • Clearance-aware minimum widths: thin traces and small pads are widened to your configured minimums (so copper doesn't peel during machining), capped automatically wherever copper on another net is too close — widening can never cause a short, and blocked spots are reported
  • Silkscreen SVG for laser marking: the top (and bottom) silkscreen drawings and text as a millimetre-sized SVG ready for LightBurn, with Print and Cut alignment targets on two drilled holes, plus the board outline and registration holes on their own colour/layer
  • All processing client-side in a Web Worker — your design never leaves your machine
  • Recoverable problems surface as warnings (oval slot holes, copper zones, curved traces, inner layers) instead of failures

How the toolpaths are made

  1. Parse — a character-level S-expression tokenizer reads the .kicad_pcb into a board model in board-local, Y-up millimeter coordinates. Legacy (module) and modern (footprint) dialects both supported.
  2. Offset — every track becomes two parallel lines at width/2 + tool radius; where tracks meet, the lines are mitered or joined by angular adjacency. A track that runs through a pad (a component lead sitting mid-track) is first split at that pad so both pieces end inside it.
  3. Pad isolation — circular pads become arcs with gaps where tracks enter; other shapes build an outline (lines + corner arcs, inflated exactly by the tool radius) and gaps are cut out as perimeter intervals.
  4. Emit — a greedy nearest-neighbour walk orders the segments, then the transform pipeline applies side mirroring, user flips, XY-zero placement, and unit conversion before writing GRBL-safe GCode (G0/G1/G2/G3, M3/M5).

Board cutout

The profile program (<board>-profile.txt) cuts the board free, so it runs last. The Edge.Cuts drawings are chained end to end into closed loops (endpoints within 0.05 mm join; circles and polygons are loops already), the largest loop is the board boundary and loops inside it are holes. Every loop is wound so the material is on its left — boundary counter-clockwise, holes clockwise — and then offset to its right by the cutter radius: straight edges shift, outward arcs grow, inward arcs shrink, convex corners get an arc around the vertex and concave corners are trimmed to the intersection. Holes are cut before the boundary. With the bottom side mirrored, the loop direction is reversed so the machine still climb mills.

The cut is made in depth passes (total depth ÷ depth per pass, in output units). On the passes below the tab top, the cutter lifts to the tab height over each tab, which are spread evenly along the straight edges and kept clear of the corners. A board with no closed outline is cut along the rectangle of its extents, with a warning; an inside curve tighter than the cutter is reported and cut as a cusp.

Silkscreen for the laser

The silkscreen output is an SVG, not GCode: LightBurn imports SVG and plans the laser job itself. The parser keeps every fp_*/gr_* drawing on F.SilkS, B.SilkS and Edge.Cuts (lines, arcs, circles, rectangles, polygons, in both the modern three-point and the KiCad 4/5 centre-and-angle arc dialects), placed with the same footprint transform the pads use. The SVG uses LightBurn's first three palette colours so each kind of geometry arrives on its own layer:

  • black — silk lines as centreline vectors (a diode laser's spot is about a silk line's width, so a single pass draws them at the right size)
  • blue — filled silk shapes, to be cut in Fill mode
  • red — the board outline and the registration holes, for aligning the burn to the milled board; set that layer's output off before burning

The bottom side is mirrored left-over-right (the face the laser sees), the same convention as the bottom isolation GCode. Silkscreen text (reference designators, labels) is parsed but not drawn yet — KiCad draws text with its own stroke font, which the engine doesn't carry — and a warning lists how many items were left out.

Roadmap (not yet supported)

  • Copper zones / filled pours
  • Curved (arc) traces
  • Inner layers (4+ layer boards)

Development

bash
npm install
npm run dev        # dev server
npm run test       # vitest unit tests
npm run check      # svelte-check / type-check
npm run lint       # prettier + eslint
npm run build      # production build (adapter-node)

Feedback form

"Send feedback" in the footer (and "Report a problem" next to the output) opens a dialog that emails the message to the developer. The user's PCB file is attached by default — they can untick it — and they may add screenshots or other files. The current settings and any warnings on screen go into the email body. POST /api/feedback receives the form and sends it with nodemailer over SMTP, rate-limited per client and guarded by a honeypot field; without SMTP credentials it logs the message in dev and answers 503 in production.

Configure with SMTP_HOST, SMTP_USER, SMTP_PASS (optionally SMTP_PORT, default 465), EMAIL_FROM and FEEDBACK_TO — see .env.example. Production uses Resend's SMTP relay with a sender on the verified kicadtogcode.com domain. The Dockerfile raises adapter-node's BODY_SIZE_LIMIT to 25 MB so attachments fit.

Usage counts

Anonymous, cookie-free counts go to GoatCounter: page views, plus three events, board-converted, sample-converted and output-downloaded. Regenerating after a settings change isn't counted. src/lib/analytics.ts only ever sends those fixed names, never anything from the board, including its name. Results are at grserwe.goatcounter.com.

The site code comes from PUBLIC_GOATCOUNTER_CODE, set in fly.toml. Without it nothing loads, and the note on the landing page saying what is counted disappears too. GoatCounter's script also ignores localhost, so local development never adds to the numbers.

Architecture

  • SvelteKit + TypeScript + Tailwind 4, adapter-node, no database, no auth. The only server code is src/routes/api/feedback/ and src/lib/server/email.ts.
  • The conversion engine is a pure, framework-free TS library in src/lib/engine/ (sexpr/ tokenizer → parser/ → model/ → geometry/ → toolpath/ → gcode/, plus profile/ for the board cutout and silkscreen/ for the laser SVG), runnable in the browser worker and in vitest.
  • Deployed on Fly.io via GitHub Actions (.github/workflows/deploy.yml): checks on every push/PR, deploy on master.

Parts

22
QtyValueFootprintReferences
4MountingHoleMountingHole:MountingHole_3.5mm_PadH1, H2, H3, H4
3RResistor_THT:R_Axial_DIN0411_L9.9mm_D3.6mm_P12.70mm_Horizontal4.7k1, 10k3, 10k4
2D1RelayG3:D1ShieldU6, U7
1.1ufCapacitor_THT:CP_Radial_D8.0mm_P2.50mmC2
1.22ufCapacitor_THT:CP_Radial_D8.0mm_P2.50mmC1
1CCapacitor_THT:CP_Radial_D8.0mm_P3.50mm100nf1
1CCapacitor_THT:CP_Radial_D8.0mm_P2.50mm10uf1
1ESP32S-DEVKITV1-30PinESP32:ESP32-DevKitV1-30PinU2
1L7805Package_TO_SOT_THT:TO-3P-3_VerticalU10
1LD33vPackage_TO_SOT_THT:TO-3P-3_VerticalU1
1Screw_Terminal_01x02TerminalBlock_Phoenix:TerminalBlock_Phoenix_MKDS-1,5-2_1x02_P5.00mm_HorizontalJ9
1Screw_Terminal_01x03TerminalBlock_Phoenix:TerminalBlock_Phoenix_MKDS-1,5-3_1x03_P5.00mm_HorizontalJ5
1Screw_Terminal_01x04TerminalBlock_Phoenix:TerminalBlock_Phoenix_MKDS-1,5-4_1x04_P5.00mm_HorizontalJ2
1Screw_Terminal_01x06TerminalBlock_Phoenix:TerminalBlock_Phoenix_MKDS-1,5-6_1x06_P5.00mm_HorizontalJ3
1Screw_Terminal_01x18G3:TerminalBlock_Phoenix_MKDS-1,5-16_1x16_P5.00mm_HorizontalJ1
1TXS0108EG3:DIP-20_512U3

Questions

How big is the ShowerController PCB?

It measures 145 × 100 mm and has 2 copper layers, 1.6 mm thick.

What parts does the ShowerController use?

22 parts, built around the L7805 and TXS0108EPW. The full list of its parts is on this page, with links to each part's symbol and footprint where PCBKit's library has them.

Where can I download the ShowerController KiCad files?

From the grserwe/KiCadToGCodeSvelte repository on GitHub, at the commit this page was made from: the board is static/samples/ShowerController.kicad_pcb. PCBKit opens the board in the browser, with nothing to install.

Can I use the ShowerController design in my own project?

Its repository states no licence, so its author keeps all rights: ask grserwe before reusing the design.

More from grserwe/KiCadToGCodeSvelte

1
  • 2 layers21.6 × 8.3 mmTopAndBottomLayer, the printed circuit board in 3D

    TopAndBottomLayer

    grserwe/KiCadToGCodeSvelte

    Convert KiCad PCB designs into CNC GCode for isolation-engraving traces on copper-clad board and drilling through-holes — entirely in the browser.

    2 parts

Similar boards

  • 2 layers67.3 × 74.5 mmVgm teensy, the printed circuit board in 3D

    Vgm teensy

    ldursw/vgm-player

    Hardware music player for YM2612 and SN76489

    41 parts7GPL-3.0
  • 4 layers68.6 × 53.3 mmIcezum, the printed circuit board in 3D

    Icezum

    FPGAwars/icezum

    :star2: IceZUM Alhambra: an Arduino-like Open FPGA electronic board

    218 parts357GPL-3.0
  • 2 layers94.5 × 74.4 mmAx58100-stm32-ethercat, the printed circuit board in 3D

    Ax58100-stm32-ethercat

    MetalMusings/MyOwnEtherCATDevice

    Documentation accompanying the "Make My Own EtherCAT device" video serie on Youtube.

    184 parts93
  • 4 layers80 × 100 mmBaseboard, the printed circuit board in 3D

    Baseboard

    NVIDIA-AI-IOT/my-jetson-nano-baseboard

    An open source Jetson Nano baseboard and tools to design your own.

    240 parts91
  • 4 layers80 × 73.8 mmESP32-Bit Pirate Dock, the printed circuit board in 3D

    ESP32-Bit Pirate Dock

    AndreiVladescu/ESP32-Bit-Pirate-Hardware

    Carrier breaker-board for the ESP32-S3 Devkit. Works great with the ESP32-Bit-Pirate firmware.

    49 parts85CERN-OHL-W-2.0
  • 4 layers42.8 × 36.8 mmDriver board, the printed circuit board in 3D

    Driver board

    blazer82/FT81x_Arduino_Driver

    FT81x on ST7701S Arduino Driver

    49 parts59MIT
  • 2 layers81.3 × 30.9 mmISABlaster, the printed circuit board in 3D

    ISABlaster

    scrapcomputing/ISABlaster

    A software-defined ISA card powered by a Raspberry Pi Pico

    24 parts53GPL-2.0
  • 4 layers29 × 50.3 mmToshiba hvac esp32, the printed circuit board in 3D

    Toshiba hvac esp32

    florianbrede-ayet/esphome-toshiba-hvac-controller

    ESPhome component & hardware to control Toshiba & Carrier HVAC units with WIFI interface

    7 parts38MIT