Author diagrams

Use every 1.3 primitive deliberately

Exhaustive families, variants, options, semantic ports, and canonical orientations.

Every family that has a direction defaults to orientation=right. A node that looks the same in every direction, such as junction, rejects the option outright. Aliases are still accepted, but the names in these tables are the ones the compiler emits. An alias is rewritten to its canonical terminal before anything downstream sees it, so these are the names a host must key on. Every kind accepts a declaration without a label, and such a part draws its designator alone. Each kind also has a datasheet on this site, printed from the compiler's own description of it.

Sources, connectivity, switching, and instruments

Kind type variants Stable ports
source voltage-dc, voltage-ac, voltage-pulse, current-dc, current-ac, battery, vcvs, vccs, ccvs, cccs negative, positive; dependent sources add control-positive, control-negative
junction, testpoint — node
connector — in, out
power vcc, vdd, vss, positive, negative in
switch spst, spdt, pushbutton, relay in, out; SPDT: common, normally-open, normally-closed; relay: coil1, coil2
protection fuse, breaker in, out
amplifier opamp, comparator, instrumentation positive, negative, out, v+, v-
resonator crystal, ceramic in, out
meter voltmeter, ammeter in, out
load lamp, motor, speaker, buzzer in, out

In 1.3.1 and later, a battery's long plate marks positive. Voltage sources (voltage-dc, vcvs, ccvs) place + at positive and − at negative; current-source arrows (current-dc, vccs, cccs) point from positive to negative, following SPICE's through-source convention. The source aliases are in = negative and out = positive. These drawings are corrected in every orientation; terminal coordinates and connections are unchanged. Patch migration notes explain how to update stored SVGs.

connector:J7 "12 V" at (90, 150) #slate
protection:FU7 "fuse" at (270, 150) #amber [type=fuse]
switch:K7 "relay" at (470, 150) #cyan [type=relay]
meter:V7 "V" at (670, 150) #purple [type=voltmeter]
load:M7 "fan" at (870, 150) #emerald [type=motor]
testpoint:TP7 at (470, 330) #cyan

J7.out -> FU7.in #slate [line]
FU7.out -> K7.in #amber [line]
K7.out -> V7.in #cyan [line]
V7.out -> M7.in #emerald [line marker-end=arrow]
K7.coil1 -> TP7.node #cyan [ortho]
compiled by @schemd/core → shown in the rail

A relay is two circuits in one symbol. in and out carry the load, and coil1 and coil2 carry the control that closes it, so a relay never needs a second component to show what switches it. The relay above switches the fan, and its coil1 terminal is brought out to a test point. That test point carries no label, because the designator already names it.

Passives and semiconductor variants

Passives share in and out, and diodes expose anode and cathode. A transistor is controlled at base for a BJT and at gate for a FET or IGBT. Its other terminals are collector and emitter, or drain and source.

Kind Variants
resistor fixed, variable, rheostat, potentiometer, thermistor, ldr
capacitor fixed, variable, polarized
inductor fixed, coupled, transformer
diode standard, schottky, zener, led, photodiode, varactor, scr, triac
transistor npn, pnp, nmos, pmos, njfet, pjfet, nigbt, pigbt
port optional width=1..256; in, out
ground signal, earth, chassis; in
resistor:RH7 "rheostat" at (100, 150) #amber [type=rheostat]
capacitor:CV7 "variable" at (290, 150) #cyan [type=variable orientation=down]
inductor:TX7 "transformer" at (480, 150) #purple [type=transformer]
diode:DV7 "varactor" at (670, 150) #blue [type=varactor]
transistor:QG7 "p-IGBT" at (860, 150) #emerald [type=pigbt orientation=up]
compiled by @schemd/core → shown in the rail

A variant changes the symbol and never the port contract. A rheostat and a fixed resistor are both wired from in to out. Swapping one for the other is therefore a one-word edit, with no rewiring.

Logic, sequential blocks, and explicit buses

The classical gates are and, or, not, nand, nor, xor and xnor. They use indexed in1..inN and out1..outN, and they accept standard=ieee|iec.

Kind type variants Stable special ports
buffer plain, tristate, tristate-inverter, schmitt, schmitt-inverter in1, out1; tri-state adds enable
logic high, low, unknown, high-z out
clock — out
flipflop sr-latch, d-latch, d, jk, t q, nq, preset; each variant's own inputs (below)
mux mux, demux indexed data ports, select, enable
encoder, decoder — indexed inputs/outputs
register — in, in2…, out, out2…, clock, enable, clear; width
counter — indexed output, clock, enable, clear
adder half, full indexed inputs/outputs
comparator — in1, in2, gt, eq, lt
bus tap, splitter, joiner bus, tap, or indexed branches; width=2..256

Every terminal of a digital block has a slot of its own. Data inputs sit on the left and outputs on the right. Clock, enable and select sit below, preset and clear above, and each one has a lead drawn to it. Every block except buffer, logic and clock accepts fit=wires, which lines its left and right terminals up with their wires. A flip-flop accepts only the letters of its own variant:

Variant Inputs Below Above
d d clock preset, clear
t t clock preset, clear
jk j, k clock preset
sr-latch s, r enable preset
d-latch d clock preset

j on a D flip-flop is rejected with its line. In 0.8 it was drawn on the first input, on top of d.

port:PULSE "pulses" at (80, 130) #blue
buffer:SH7 "clean" at (280, 130) #cyan [type=schmitt]
counter:CT7 "count" at (500, 150) #amber
port:LIM "limit" at (80, 330) #amber
comparator:CM7 "N = limit" at (760, 250) #purple
port:DONE "batch done" at (1040, 250) #emerald

PULSE.out -> SH7.in1 #blue [digital ortho]
SH7.out1 -> CT7.clock #cyan [digital ortho]
CT7.out1 -> CM7.in1 #amber [digital ortho]
LIM.out -> CM7.in2 #amber [digital ortho]
CM7.eq -> DONE.in #emerald [digital ortho marker-end=arrow]
compiled by @schemd/core → shown in the rail

A comparator publishes three answers, gt, eq and lt, where a single boolean would hide the direction. A datapath that cares which way a threshold was crossed therefore needs no second gate. Here the batch signal follows eq, so it rises when the count reaches the limit.

Named gates, two-track CNOT, multi-track operators, and classical results

The single-qubit shells are hadamard, qgate, xgate, ygate, zgate, sgate, sdg, tgate, tdg, sx, phase, rx, ry, rz and ugate. They use in and out, and qgate accepts parameter, phase and matrix detail rows.

Kind Stable ports and options
cnot control rail in1, out1; target rail in2, out2; legacy aliases in, out, control, target remain accepted; fit=wires
measure in, out, classical
reset in, out
prepare out
control in, out, control; control=positive, negative, or classical
swap, cz, cphase, toffoli, controlled, barrier, delay indexed inN, outN, controlN, targetN; bounded wires, controls, targets; fit=wires; the vertical terminal on the lowest rail faces down
classical-bit in, out
classical-register in, out, width=2..256

cnot always owns exactly two continuous qubit rails. A composed circuit should use the indexed through-ports. control and target address the marker locations, for compatibility and for interaction metadata. initial and final belong to UML state and activity diagrams, and they do not mark quantum state boundaries. A quantum rail starts with prepare and ends with measure, or with a system port when it stays unmeasured.

prepare:P0 "|+\rangle" at (80, 120) #blue
prepare:P1 "|1\rangle" at (80, 280) #blue
cphase:CP7 "CP" at (400, 200) #purple [fit=wires]
measure:MX7 "M_x" at (680, 120) #cyan
classical-bit:CB7 "c_0" at (880, 120) #emerald

P0.out -> CP7.in1 #blue [quantum ortho]
P1.out -> CP7.in2 #blue [quantum ortho]
CP7.out1 -> MX7.in #purple [quantum ortho]
MX7.classical -> CB7.in #cyan [classical line marker-end=arrow]
compiled by @schemd/core → shown in the rail

The rails are indexed and continuous. inN enters, outN leaves, and the operator sits across all of them. measure is the only place where a quantum rail becomes classical. Hence its classical port feeds the classical bit, while its out would carry the qubit onwards.

cnot is the two-track case of the same rule, and the one most often written wrongly. It owns exactly two continuous rails. The control enters at in1 and leaves unchanged at out1; the target enters at in2 and leaves at out2. The legacy names control and target still resolve to the marker positions. A composed circuit should still use the indexed through-ports, because the netlist and the full-mode metadata carry those terminals. The rails sit 18 units apart unless fit=wires is written, and with it they sit on the qubits, as below.

prepare:HC "|1\rangle" at (100, 100) #blue
prepare:HT "|1\rangle" at (100, 270) #blue
cnot:CX at (460, 185) #purple [fit=wires]
port:HOC "control out" at (790, 100) #emerald
port:HOT "target out" at (790, 270) #emerald

HC.out -> CX.in1 #blue [quantum ortho]
HT.out -> CX.in2 #blue [quantum ortho]
CX.out1 -> HOC.in #purple [quantum ortho]
CX.out2 -> HOT.in #purple [quantum ortho marker-end=arrow]
compiled by @schemd/core → shown in the rail

Structural, deployment, activity, state, and interaction nodes

The UML catalogue has three groups.

  • The structural kinds are class, interface, provided-interface, required-interface, enumeration, datatype, object, component, component-port, artifact, node, device, execution, system, package and note.
  • The behavioural kinds are actor, usecase, state, action, decision, merge, fork, join, activity-final, flow-final, object-node, send-signal, receive-signal and partition.
  • The interaction and state kinds are lifeline, activation, destruction, fragment, interaction, gate, found, lost, choice, state-junction, history, entry, exit, terminate, region, initial and final.

Sized rectangular nodes accept a bounded width and height. Class-like nodes also accept stereotype, attributes and operations. Their ports are left, right, top and bottom.

The relations are association, dependency, generalization, realization, aggregation, composition, message, synchronous, asynchronous, return, control-flow, object-flow, assembly, delegation, transition, include and extend.

lifeline:CI7 "CI runner" at (220, 270) #cyan [width=170 height=400]
lifeline:PG7 "Pages host" at (620, 270) #amber [width=170 height=400]
artifact:ST7 "site/" at (880, 420) #emerald [width=170 height=80]

CI7.right90 -> PG7.left90 #cyan [line synchronous label="deploy(1.3.0)"]
PG7.left180 -> CI7.right180 #amber [line return dashed label="200 OK"]
CI7.right270 -> PG7.left270 #cyan [line asynchronous label="invalidate cache"]
ST7.left -> PG7.right350 #emerald [ortho dependency label="build output"]
compiled by @schemd/core → shown in the rail

A lifeline exposes leftNN and rightNN, which place a port exactly NN units below its top edge. That is how three messages sit at three exact heights without a layout engine deciding for us, and how the build output meets the host at 350 units.

Read the same facts as data

Every table on this page can also be read from the compiler. Since 1.3, @schemd/core/schema exports SCHEMATIC_COMPONENT_SCHEMAS, which gives each kind its family and its options. Each option carries a type, and the type says what the option accepts:

Type What it states
enum the accepted values and the default
integer, number the range, the default, and any default that depends on the kind's type
text the shortest and longest value
pins the most pins per side, the pattern a pin name must match, and the names it may not take
rows the most rows and the longest row

A kind that needs one of several options lists them in requiresOneOf, as an IC does with its four sides. A pair that cannot appear together is listed in conflicts, as fit and orientation are.

Ports depend on options, so they are never listed by hand. describeComponentPorts(kind, options) asks the parser for the terminals a part has with those options, and a bad option throws the same SchematicSyntaxError a document would.

import { describeComponentPorts } from '@schemd/core/schema';

describeComponentPorts('switch', { type: 'spdt' });
// ['common', 'normally-open', 'normally-closed']

The schema is not a second source of truth that can drift. A test in the compiler probes the parser for every kind and option: each declared value must compile, each value just past a declared bound must fail, each undeclared option must fail, and each declared default must draw exactly what leaving the option out draws. The component datasheets on this site are printed from the same data.