Importing from KiCad
pcbjs import footprint and pcbjs import board, kicadFootprint() and readFootprint() of @pcbjs/kicad: what each imports, the conventions applied and what a person refines after a board import. The frame, the back side and the Gerber differences between the two tools are in kicad.md.
Commands
sh
pcbjs import footprint <Lib:Name | file.kicad_mod> [-o lib/<name>.tsx] [--force]
pcbjs import board <file.kicad_pcb> [-o pcb.tsx] [--force]import footprintwrites onedefineFootprintmodule the project owns and edits: pads, graphics on every layer, text, keepouts, the courtyard and the model reference, with a header naming the source and its licence.Lib:Nameis looked up askicadFootprintdoes, below; a bareNamein every library.import boardwrites the board's files beside-o, replacing one only with--force.pcb.config.tsandtsconfig.jsongo to the nearest folder from-oup to the working folder with apackage.json, else beside-owith a new one;package.jsonandtsconfig.jsonare never replaced, and an existing config is kept, the entry and rules to add printed. It reads the.kicad_pro,.kicad_druand.kicad_schof the same name when they are there.- Both take KiCad 8 to 10 files, format 20240108 and newer, and most older ones.
Library footprints in code
tsx
import PCB, { nets } from '@pcbjs/core'
import { kicadFootprint } from '@pcbjs/kicad'
const SOIC8 = kicadFootprint('Package_SO:SOIC-8_3.9x4.9mm_P1.27mm', { pinNames: { 4: 'GND', 8: 'VCC' } })
const { IN, OUT, OUTB, GND, VCC } = nets()
const U1 = SOIC8('LM358').connect({ 1: OUT, 2: OUT, 3: IN, GND, 5: GND, 6: OUTB, 7: OUTB, VCC })
export default <PCB name="Amp"><rect layer="Edge.Cuts" x={0} y={0} w={20} h={15} /><U1 at="10 7.5" /></PCB>kicadFootprint(ref, { pinNames, prefix, value, model, footprints, silk })returns a factory used like the standard library's;silk: 'none'leaves out the footprint's silk, as stdlib.md has it. Its pins are the pad numbers in pad order, one pin per number;pinNamesrenames them by a list in pin order or a record keyed by pad number, and a pad namedNCis no pin. The prefix comes from the library and name,R_0603is R,SOICU.- The reference is
Lib:Name, a bareName, or a path to a.kicad_mod. Libraries are searched in this order: the.prettyfolders of the project root,lib/,footprints/andlib/footprints/;kicad.footprintsin pcb.config.ts;KICAD_FOOTPRINTS, a path list; the installed KiCad library, fromKICAD10_FOOTPRINT_DIRand its older names or the install folder. - A file is read once per path and content; an edited
.kicad_modapplies on the next compile. - The model line resolves
${KICAD10_3DMODEL_DIR},${KICAD9_3DMODEL_DIR},${KICAD8_3DMODEL_DIR}and the older names to the installed3dmodelsfolder, orkicad.modelsof the config, and${KIPRJMOD}to the project root, or in an import the folder of the.kicad_pcb, so the 3D view finds it without a copy. Amodeloption is relative to the file callingkicadFootprint. A.wrlthat is missing becomes the.stepbeside it.pcbjs model add <file> --ref U1 --writestill copies it intomodels/. readFootprint(textOrPath)returns the definition itself:defineFootprint(def.render, def.meta)makes the factory, anddef.elementslists the pads, graphics and text as data.
What a footprint import carries
- Pads of every type:
smd,thru_hole,np_thru_holeasnpth, andconnectas smd without paste. Shapescircle,rect,ovalandroundrect,roundrect_rratioasroundness, map one to one. A trapezoid, a chamfered rectangle, a pad whose copper is offset from its hole, and a custom pad, its anchor and primitives joined, becomeshape: 'custom'withpoints, see layout.md. - Drills, round and slotted; the pad's own rotation; its copper layers, a smd pad on
B.Cuincluded;solder_mask_marginasmaskExpansion; the pad's ownclearanceas itsclearance, see rules.md Overrides, 0 meaning none as in KiCad 8; a negativesolder_paste_marginaspasteShrinkandsolder_paste_margin_ratioaspasteRatio, a positive margin as a grownpastewindow; noF.Pasteaspaste: false;zone_connect0 and 2 asthermal: 'none'and'solid';thermal_bridge_angle, by default 45 on a round pad, asthermal: { angle: 45 }. Paste-only pads on a copper pad without paste of its own become itspastewindows, so a hand-solder land pastes only where KiCad does. - A padstack whose front shape differs from its inner and back shape is two pads of one number: the hole with the back shape on every layer, and the front shape on F.Cu. DRC treats pads of one footprint with one number as one pad.
fp_line,fp_arc,fp_circle,fp_rect,fp_polyandfp_curveon copper, silk, mask, paste, Fab, courtyard,Edge.Cutsand the user layers, with their widths and fills. Lines and arcs of one layer and width are joined into one path, arcs asAcommands that reach the Gerbers as arcs. Eco andUser.Nlayers go toCmts.User; adhesive and margin graphics are left out.- User
fp_textwith its size, glyph width, thickness, justification and rotation. The reference and value are drawn by pcbjs, see layout.md, Silk refs; text with a${…}variable is left out. - Keepout zones of a footprint as
keepoutelements;exclude_from_bomandexclude_from_pos_filesasbomandpos; the first shown model with its offset, scale and rotation. net_tie_pad_groupsasnetTieon the footprint, so a Kelvin shunt's sense tabs touch its current pads without a short, see layout.md Pads.- A board's pad pin functions and types become a comment beside the part's
.connect().
What a board import writes
| File | Holds |
|---|---|
pcb.tsx | <PCB> with the name, title, revision, the stackup and the net classes; the outline and cutouts as lines and arcs; every placement grouped by ref prefix; the text; then copper and <Art /> |
pcb.sch.ts | the nets, nets() keeping KiCad's names, +5V as P5V and /D6 as D6; one part per footprint named by its ref, with value, bom, pos, dnp and each pin's net in .connect() |
pcb.sourcing.ts | source() per set of equal fields: the footprints' fields with the .kicad_sch symbols' over them, MPN, Manufacturer, LCSC as MPN:LCSC and every field the project uses |
pcb.copper.tsx | pours with net, layer, clearance, priority, minimum width and connection; keepouts; each net's tracks as route() chains of straight .Z() segments with .neck(AS_DRAWN), .via() at a layer change and .vias(VIA) for the size; vias no chain passes through; track arcs as tracks with an A path |
pcb.art.tsx | the board's own silk, Fab and user graphics |
lib/<Name>.tsx | every footprint that is not the installed KiCad library's own, from the copy in the board, so local .pretty footprints and edited library ones keep the board's geometry; copies that differ only in element order, an outline's start, the courtyard, coordinates within 1 µm or pad zone connections make one module, from the copy with the tightest courtyard; a placement whose pads join pours otherwise gets a thermal map of them, <C3 thermal={{ 2: 'solid' }} /> |
lib/kicad.ts | kicadFootprint() for footprints whose pads, copper, mask, paste, silk and courtyard match the installed library |
pcb.config.ts | the entry and defineDefaultRules from the .kicad_pro and the board setup; each .kicad_dru rule as a comment saying what it became |
- Refs are KiCad's; one like
R1binds by its variable name; any other, such asJ_HR, gets.ref('J_HR'). - A chain starts and ends at a pin handle,
U1[3], where its end is a pad centre of a pin with one pad, and at a coordinate otherwise, with.net()when neither end is a pad. - Pads on a net named
unconnected-(…), or on none, connect toNC. - Every chain has
.neck(AS_DRAWN),{ length: 0 }, so pcbjs does not narrow KiCad's tracks at pads they are wider than, see routing.md; drop it on a chain you redo. exclude_from_bom,exclude_from_pos_filesand DNP, of board or symbol, are the part'sbom,posanddnp, or the placement's for a plain footprint.- A through-hole pad with
remove_unused_layerslists inlayersthe copper layers a track or zone joins it on in any placement, and the outer layers withkeep_end_layers. - Filled silk is written before the items of its layer inside it, so it never clears a glyph.
- Custom rules of the
.kicad_druwith one(min …)constraint ofclearance,hole_clearance,edge_clearanceortrack_widthmap onto overrides, see rules.md Overrides:- one footprint,
A.Parent == 'J1'orA.Reference == 'J1', B the same or nothing,A.Type == 'Pad'allowed:.rules({ … })on that part, one per alternative; A.NetClass == 'X', B the same or nothing: the clearance of class X;- every pair of one list of nets,
(A.NetName == 'P' || …) && (B.NetName == 'P' || …): a class of them named after the rule, unless one has a class; - a pad of a
Pad_Type, a footprint or any, against aB.Type: a part clearance by kind,{ track: 0.4 }, on every such part, unless one has pads of another type too; - a
TrackorViaof oneNetNameorNetClassagainst aB.Type: a clearance by kind on that net,.rules(), or class; aNetName,!=or other term on B is dropped, a stricter rule, as the comment says. B.Type == 'Pad' && B.Pad_Type == 'Through-hole'or'SMD'on the other side of either form scopes the clearance toward pads by type,{ pad: { tht: 0.5 } }; an'NPTH, mechanical'term is dropped.- Any other rule, such as a courtyard rule or one between two footprints, stays a comment in
pcb.config.tsand a note.
- one footprint,
- A footprint's own
clearancebecomes.rules({ clearance })on its part, orruleson a plain footprint; a custom rule on the same part merges, the larger per kind. - Rules:
clearanceis the larger of KiCad's minimum and the Default class; track width, edge and hole clearance, drills, annular rings, hole to hole andmaskExpansionmap one to one;silkMinWidthis the thinnest silk text or line, as KiCad checks text only;thermaltakes the most common zone relief and KiCad's minimum spokes.
Conventions applied
The frame, back side and text conventions an import applies are in kicad.md, Import conventions.
Not imported
.kicad_drurules that map onto no override; thermal gap and spoke width per pad or zone; the board's positive or ratio paste clearance. The notes and pcb.config.ts list them.- Mask-only pads,
duplicate_pad_numbers_are_jumpers, dimensions, images, groups, text boxes, tables and copper graphics' nets. Zone fills are recomputed. - A padstack with a third, inner shape takes its back shape on the inner layers.
After a board import
pcbjs check --fab. What remains are KiCad rules pcbjs does not carry, named in the notes, pairs where KiCad lowered one item's clearance but the other keeps the larger, or checks KiCad lacks, such as silk width on lines; settle each by a rule, a net class or a design change.- Rename the pins of the footprints you will connect by name, with
pinNamesonkicadFootprintornameon the pads of alib/module, then.connect()by name. - Replace routes you want redone with
.X()legs, and.lock()the ones to keep, see routing.md. - Swap
lib/footprints for standard library families where one fits, see stdlib.md. - Move the stackup and rules to a fab preset such as
@pcbjs/fab/JLCPCB/4-Layerwhen the board is ordered there, see fab.md.