Skip to content

This page is generated from docs/furniture.md — edit it there.

Furniture & Fixtures ​

furniture places a piece of furniture or a built-in fixture into a plan. Every catalogued kind draws a real plan symbol — a WC with a cistern and a seat, a bed with a headboard and pillows, a wardrobe with its hanging rail and hangers — in the same drawing vocabulary as the door arcs and window panes. Anything ArchLang doesn't know still renders as a labelled rectangle, which is the escape hatch for a piece the catalogue has no word for.

Where you put it matters to the soundness checks: the linter knows a WC should have its back to a wall, that a bath needs a wet fixture, and that a door leaf should not sweep across a basin.

This page covers the placement modes, the symbol catalogue, how a symbol is oriented and sized, the importable fixture library, and the lint rules that key off furniture. The one-line grammar lives in the language reference.

Three placement modes ​

A piece is positioned absolutely by its top-left corner, snapped against a wall so its back sits on the wall face, or anchored inside a room's box. The two non-absolute modes derive the piece's rotation for you.

ModeGrammarYou giveArchLang derives
Absolutefurniture <kind> at (x,y) size <w>x<h> [rotate 0|90|180|270] [in <room>]corner, footprint, optional quarter-turnnothing — what you write is what's drawn
Against wallfurniture <kind> against wall <ref> [segment <n>] [offset <mm>] [side left|right] [size <along>x<depth>] [in <room>]which wall, how far along, optionally a depththe position and the rotation, from the wall — plus the footprint, if the kind has one and you omit size
In a roomfurniture <kind> in <room> centered|anchor <a> [flush] [inset <mm>] size <w>x<h> [rotate …]which room, which corner/edge, footprintthe position from the room's box (or, with flush, from the backing wall's face), and — for a kind whose facing means something — the rotation from the wall the anchor names
arch
# Absolute: a bed in the top-left, turned a quarter turn so its head is on the left wall.
furniture bed at (4300,300) size 1500x2000 rotate 90 in r_bed

# Against a wall: a 600-mm-deep counter run 1800 mm long, snapped to the north wall,
# starting 300 mm in from the wall's start, sitting on the interior (room) side.
furniture counter against wall north offset 300 side left size 1800x600 in r_kitchen

# Against a wall with NO size: the catalogued footprint is used (a fridge is 600 along
# the wall by 650 deep), so the only numbers left are the ones this plan chooses.
furniture fridge against wall w_west offset 400 in r_kitchen

# In a room: a WC on the bathroom's south edge — `rotate 180` (cistern to that wall) is
# derived, and `flush` puts its back on that wall's inner face (no thickness to work out).
furniture wc in r_bath anchor bottom flush size 400x700
  • rotate turns the footprint a whole quarter-turn about its centre (0, 90, 180, or 270 — any other value is E_FURN_ROTATE). It is exact integer geometry, so the output stays byte-stable.
  • against wall <ref> snaps the piece's back onto a wall named by id or kind.
    • segment <n> selects which leg of a multi-point wall (0-based) to sit against.
    • offset <mm> slides the piece along that segment from its start.
    • side left|right picks which face of the wall to sit on (relative to the segment's direction); when you also give in <room>, the interior side is inferred for you.
    • size may be omitted for any kind with a catalogued footprint (the "Footprint" column below) — it is read as along × depth, along the wall and into the room. A kind with no footprint and no size is E_FURN_SIZE.
    • The rotation is derived from the wall, so combining against with an explicit rotate is an error (E_FURN_AGAINST).
  • in <room> records the owning room (by id). A trailing in <room> doesn't move the piece — it lets the linter check the piece is actually inside that room and lets against infer the interior side. A non-existent id is E_FURN_ROOM. The leading form (in <room> centered\|anchor …) both positions and owns the piece.
  • flush measures the inset from the wall FACE. A room's rectangle runs along wall centerlines, so anchor bottom alone leaves the piece's back half a wall thickness inside the solid — which is why you would otherwise write inset 100 for a 200-mm wall you never named (W_FURNITURE_WALL_COLLISION if you forget). flush re-bases inset (default still 0) onto the inner face of the wall behind each anchored edge — centerline + thickness / 2, toward the room — so anchor bottom flush lands on the plaster and anchor bottom flush inset 50 sits 50 mm off it. It applies per edge and independently (a corner anchor can be flush on one edge only), an anchored edge with no wall behind it keeps the room-rectangle reference, and it needs an anchored edge at all: centered / anchor center is E_FURN_FLUSH. Write it before inset, whose reference it changes.
  • anchor <edge> also aims a piece. An anchor names the wall(s) the piece is pushed against, so for a kind whose facing means something the quarter-turn is derived — no rotate to work out by hand. It is derived only when the answer is unique (ADR 0005): the anchored edge must have a wall behind it, and the footprint's aspect must allow that edge to be the back (a 400 × 700 WC is 400 along the wall and 700 deep, so it can only back onto a horizontal edge). anchor bottom-left in a walled corner therefore still has one answer for that WC, while a square 600 × 600 counter in the same corner has two — so nothing is derived and W_FIXTURE_BACK_TO_ROOM asks you to pick. An explicit rotate always wins.

The symbol catalogue ​

Eighty-three families, a hundred and twenty-nine names with the aliases, and every one of them draws. The tables below are grouped by the room the pieces belong to.

Three columns need a word of explanation:

  • Footprint is the catalogued along × depth in millimetres — the size against wall uses when you omit size. A dash means the kind has none, so size is required there.
  • Facing says what ArchLang will do about which way the piece points. Derived means the symbol has an unmistakable back — a cistern, a tap, a nosing, a headboard, a wardrobe's door line — so an anchor can derive the quarter-turn and W_FIXTURE_BACK_TO_ROOM flags a piece against a wall that faces the wrong way. Symmetric means the symbol is drawn so that a quarter-turn changes nothing, so its facing carries no meaning and is neither derived nor checked. Free means the piece is drawn with a front but is arranged rather than installed — a sofa's back to the room is a room-divider layout, not a defect — so nothing is derived and nothing is warned about.
  • Wall marks the kinds that carry requiresWall, which means services and nothing else: supply, waste, venting, or hanging off the wall by definition. Those are the kinds W_FIXTURE_FLOATING applies to. A bookcase is not one of them — a library's stacks are free-standing runs mid-floor, which is what stacks are.

Bath ​

Kind (and aliases)SymbolFootprintFacingWall
wc · toileta rounded cistern across the back with its flush button, a four-centre oval bowl in front, the seat opening and two hinge ticks400 × 700derived✓
basin · lavatorya rounded vanity top with an inset four-centre oval bowl and its floor line, a tap and spout at the back and the waste — two bowls on a long enough slab600 × 450derived✓
showera rounded tray with its floor let into the rim, four falls running from the corners to the waste, and the waste — a ring with a disc in it900 × 900symmetric✓
bathtub · tub · batha rounded rim and an inset well whose foot end is a near half-circle and whose head end is nearly square, two taps on the head deck and the waste beside them1700 × 700derived✓
bidetan oval bowl with its rim, a small tap deck standing on the bowl's rear edge with its tap and jet, and the waste — a wc with no cistern400 × 700derived✓
urinala U bowl run to the wall face — square at the back, a semicircle at the front — with its rim, the flush plate across its back and the waste400 × 350derived✓
mirrorthe glass, with a run of 45° reflection ticks across it — one per four depths of length, three to twelve900 × 50derived✓

The tub is deliberately uneven — a deep deck at the tap end, a shallow rim at the foot, and a well that is nearly square at one end and round at the other — so the drawing says which end you get in at. lavatory is one of only two aliases that differ from their head (sink, which also counts as wet, is the other): it does not count as a wet fixture for W_ROOM_NO_FIXTURE, which has always been true of it, while basin does.

urinal is the only symbol in the catalogue drawn as a U against its wall, and that is the honest plan of it: a wall-hung urinal has no back — the wall is its back — so the top of the bowl is the wall face, with square back corners, and its bowl runs to the very back edge of its footprint, where every other bath fixture's bowl stands clear of it.

mirror and bidet are both requiresWall, for the two different reasons that flag covers. A bidet is plumbed. A mirror hangs off the wall by definition — the upper_cabinet case, not the plumbing one. Neither carries a zone that would let it stand in for a WC or a basin: bidet counts as a wet fixture, mirror deliberately does not, because a mirror over a console table does not make a room a bathroom.

Kitchen & utility ​

Kind (and aliases)SymbolFootprintFacingWall
kitchen_sink · sinkcounter slab, a centred rounded bowl with a waste, a tap ring with its spout at the back — two bowls from aspect 2, and a drainer board with four grooves on each side once the run leaves room for them; symmetric at every size800 × 600derived✓
counter · worktopslab with an upstand line near the back, a front-edge line near the front and a division tick at every 600 mm base-cabinet module boundary between them (none on a run shorter than two modules)600 × 600derived✓
stove · hob · cooktopslab with the glass hob plate, four burners as concentric rings — the large pair along the back, the small pair in front — and a row of four control knobs along the front600 × 600derived✓
fridge · refrigeratorcarcass, the door's face line across the front, the handle bar — and, by aspect, a vertical door split when it is a side-by-side600 × 650derived✓
ovencarcass, three control knobs on the back edge, and the door with its glass window and handle bar — plus four burners when the footprint is wide enough to be a range, its knobs moving to a rail under the hob—free
dishwashercarcass, the tub's inset panel with two rack rails, the control strip across the door, and the handle bar600 × 600derived✓
islandworktop, the line the seating overhang starts at along the front, and — by aspect — a hob plate with four burners or a sink bowl with its tap at one end—free
upper_cabinet · wall_cabinetthe outline, a door-face line across the front band and a door split at every 600 mm module boundary (none on a run shorter than two modules), drawn entirely dashed600 × 350derived✓
washer · washing_machinecarcass, the control strip across the back with its dial and button, and the door ring with a white porthole600 × 600derived✓
dryerthe same carcass, its dial on the centre line, an empty drum with a gasket ring inside it where the washer has its porthole, and the lint-filter slot across the front600 × 600derived✓
laundry_sink · laundry_tubslab with one deep bowl, the step down to its floor, its waste, and a tap ring with its spout600 × 500derived✓
water_heater · boilerthe cylinder in plan, its jacket ring, and two pipe stubs running back to the wall600 × 600derived✓
range_hoodthe hood outline with a fan ring, four blade radials and a hub ring, drawn entirely dashed900 × 500derived✓
microwavecarcass, the door frame and its glass window over the left three-quarters, and the keypad strip with three buttons on the right500 × 400derived
bar_counterthe worktop over the back of the footprint, the overhang line, and 1.2 stool seats per counter-depth of run, one to eight1800 × 600derived

washer and dryer are the same box at the same size and stand side by side in most utility rooms, so they are drawn to differ by shape: a glyph carries no text, so a letter is not available to tell them apart even if it were good drafting.

island is free-standing by definition — that is what makes it an island — so it needs no wall and has no single frontal clearance. It is no longer symmetric: the symbol gained a seating overhang along one side, which is a distinguishable front, so the catalog flag came off to keep the data true. Nothing observable changed with it — an island still derives no rotation and still never trips W_FIXTURE_BACK_TO_ROOM, because that needs requiresWall or directional and an island is neither. Seating round it is a stool, a separate kind with its own symbol; the stools drawn inside a bar_counter are a different piece with a different footprint.

Four symbols read their own footprint and draw a different appliance either side of a threshold, because the fixture word alone cannot tell them apart and inventing one answer would be wrong for half the plans that use it. A kitchen_sink at aspect 2 or over takes a second bowl, and whenever the bowls leave room — one bowl from about aspect 1.7, two from about 2.7 — a drainer board on each side (never a single trough — a bowl is at most 1.25 times as wide as it is deep); a fridge at aspect 1.4 or over splits its door down the width (a side-by-side) and below it draws one door; an oven at aspect 1.6 or over is a range and gains a hob; an island at aspect 1.8 or over takes a hob at one end rather than a sink. Give the piece an explicit size to choose.

range_hood is the second symbol here drawn entirely dashed, and it makes the convention the drawing's rather than one glyph's: a dashed outline means a thing above the cut plane — upper_cabinet, roof, void, the outdoor pergola and a garage door's projection all say the same. The two kitchen ones are told apart by what is inside: a cabinet's door line and splits run edge to edge, a hood's fan is a ring about the centre.

Bedroom ​

Kind (and aliases)SymbolFootprintFacingWall
bedmattress, headboard band at the head, one or two pillows, and the duvet with its turned-down band and one folded corner at the foot1500 × 2000derived
double_bedthe same drawing — two pillows from a mattress aspect of 0.6, so at their catalogued sizes both draw two1800 × 2000derived
nightstand · bedside_tablecarcass and the top's edge bevel, the lamp standing toward the back (a white shade with the bulb ring inside it), and the drawer front with its pull on the room side450 × 400derived
wardrobe · robe · closetcarcass, the door-front line near the front face, a divider between door bays, and in every bay the hanging rail at mid-depth (dashed — hidden inside the closed cabinet) with short hanger strokes across it1800 × 600derived
bunk_bedthe bed's frame and headboard band, the lower mattress with its pillow at the head, the upper bunk and its guard rail dashed over it, and the ladder at the foot1000 × 2000derived
crib · cotcarcass, the mattress inside it with its blanket and turned-down band, and the rail bars down both long faces700 × 1300derived
dresser · chest_of_drawerscarcass and, on the room side, a row of drawer fronts (one per 0.8 depths of width) each with its pull1200 × 500derived
vanity · dressing_tabletop, the mirror band dashed across the wall side, a drawer pedestal with its pull at each end, and the stool between them1200 × 500derived

None of these carries requiresWall — a bed needs no pipe — but all eight are directional, because the symbol has a back worth turning toward a wall. That is what lets anchor top derive rotate 0 for a bed and put its headboard where you meant it.

The wardrobe is drawn the way a joiner's plan draws one. Its door bays are a fraction rule read off the footprint — one per 0.875 depths of width, so a 1800 × 600 robe gets three 600 mm doors — and each bay holds its own dashed rail (above the cut plane and behind a closed door, the one thing a dash means) with a run of hanger strokes across it, three to five a bay. Nothing else in the piece is dashed, and the counts depend on the footprint alone, never on the pen.

Living & dining ​

Kind (and aliases)SymbolFootprintFacingWall
sofa · couchrounded body, an arm at each end running the full depth, and a row of back and seat cushions — one per 0.62 depths of seat, up to four—free
armchairthe sofa construction with one cushion and broader arms—free
coffee_tablehard top with softly eased corners and a white inset panel (the glass or tray) a tenth of the short side in; no legs — they are under the top—symmetric
tv_unitcarcass, the door splits and one pull per door on the room side, and the television standing on its back edge — a slim panel on a foot plate1500 × 450derived
tablehard top and one bevel line just inside it — exactly the dining_table's top, without the chairs; no legs — they are under the top—symmetric
dining_tablethe table inside a chair-zone band, with the chairs tucked under it—symmetric
chaira rounded upholstered seat and a pill-ended backrest bar along the rear edge—free
stool · barstoola round white seat and the footrest ring standing proud of it at the full footprint — two concentric true circles about the footprint centre—symmetric
benchslab with its board joints running lengthwise along whichever axis is longer—free
fireplacethe chimney breast against the wall, the hearth slab in front of it, and the splayed firebox cut into the breast's room face, with its grate1200 × 400derived
radiatora shallow slab with its fins ticked across the depth inside the casing, at a clamped pitch1000 × 100derived
sideboard · buffetcarcass, the door splits along the run, and one pull per door on the room edge1600 × 450derived
loveseat · sofa_2the sofa construction with its cushion count pinned at two seats, whatever the footprint1500 × 850free
chaisethe sofa construction with one arm (the left) and the other end open: a row of back cushions and one long seat cushion you lie along1600 × 800free
tva slim panel on the room face and the wall bracket behind it — not the tv_unit, which is a carcass1200 × 80derived
coat_racka round base, the pole, and four hook arms on the diagonals, each ending in a knob400 × 400symmetric
shoe_cabinetslim carcass, the door splits, and a long finger-pull along the front of each door800 × 300derived
sofa_l · corner_sofathe sofa construction round an L: the back run along the rear edge, the return down the left, a square corner seat, an arm at each free end, and the fourth quadrant left as open floor2600 × 1600free
rug · carpeta woven body with a border band inside it and a fringe off each short end (all four on a square rug) — unfilled, and the only symbol drawn entirely in the detail pen—symmetric
piano · grand_pianoa grand: the keyboard across the back, the straight bass side down the right, a round tail, the concave bent side and the treble shoulder (tangent arcs throughout) with the lid line inside; a bench in front of the keys when the footprint is at least 1.3 widths deep—free

sofa, armchair, chair, bench, sofa_l, loveseat and chaise are deliberately free: seating is arranged, not installed, so ArchLang neither derives a rotation for them nor warns when one faces the room. tv_unit, tv, sideboard and shoe_cabinet are the exception — each is directional (each has a front) but still carries no services, so floating one as a room divider raises nothing.

A loveseat is a sofa with its cushion count pinned. Both draw from one construction, so the pair cannot drift apart; what separates them is the number of seats, which is the fact the two words actually carry. A sofa reads the length of its seat and draws three cushions on a 2000 × 900 footprint; a loveseat draws two on any footprint.

A tv and a tv_unit are different kinds, not synonyms. A media console is 450 mm deep and a wall-mounted panel is 80, so a plan that draws the first where the second belongs has taken 370 mm of walkway away. Both are directional, and the symbols differ: the console has a carcass, door splits and pulls on the room side, and a television standing on its back edge; the mounted panel is a slim slab on the room face and the bracket behind it, and nothing else.

fireplace and radiator are not requiresWall, and both are genuinely serviced. That flag means the piece cannot work without a wall behind it, and neither of these can be flagged without warning on a normal drawing: a radiator is as often fed from the floor as from the wall and lives under a window, and a free-standing stove in the middle of a room is a plan someone drew on purpose. Both are directional instead, which is the claim the drawing can back: a fireplace's firebox opens onto the room with its hearth in front of it, and a radiator's fins run across it, from the back toward the front.

sofa_l's return is always on the LEFT, and there is no right-handed twin — but place … mirror now draws one. A sofa_l_r category was rejected rather than forgotten: it would put the fix in the vocabulary, where every future handed symbol would need its own twin. So a reflecting instance frame hands the glyph its own chirality instead, in frame.ts — the one place the handed rules are flipped — and the symbol is drawn as its own mirror image. Turn it with rotate where a quarter-turn is what you want; reach for place … mirror when you want the mirror-image piece.

Handedness is DERIVED from the drawing, not declared per family. Sixteen of the 83 shipped families have no vertical mirror axis (bed, desk, bathtub, island, washer, microwave, mirror, chaise, reception_desk, piano, sofa_l, bicycle, motorcycle, mailbox, ev_charger, double_bed) at their catalogued footprints (1000 × 600 for the five that have none). Handedness is a property of the drawing rather than of the family, though: counter, fridge, upper_cabinet, bicycle and motorcycle are handed at some footprints and symmetric at others — the first three because their detail is tiled by aspect, the bikes because they are drawn along their own long axis — which a per-family flag simply cannot express. A symbol that has a mirror axis renders byte-identical whether its instance was reflected or not, at every footprint; see src/elements/glyph-chirality.ts and test/glyph-chirality.test.ts.

Its footprint is the whole bounding rectangle, empty quadrant included, which is what every furniture rule measures — so a coffee table tucked inside the L raises W_FURNITURE_OVERLAP even though nothing touches. That is a known cost of having one shape seam rather than five: teaching the overlap rule about the L and leaving the clearance rule, the wall-collision rule and the two walkability grids on the box would make the drawing and the lint disagree in a way nothing tests.

A piano carries no footprint on purpose, so furniture piano against wall <id> is E_FURN_SIZE. That form derives the rotation from the wall under the back-on-top rule, and a piano's back-on-top is its keyboard — so the one thing it could derive is the one orientation a piano is never in. Place it with at (x,y) and a rotate, which is how it goes on a drawing anyway.

Office & misc ​

Kind (and aliases)SymbolFootprintFacingWall
desktop with its edge bevel and the modesty panel across its back, the drawer pedestal on the right drawn dashed (it is under the top), and the monitor standing at the back—free
office_chaira rounded white seat, a crescent back of two true arcs, an armrest each side, and the five-star base dashed under the seat—free
bookshelf · bookcase · shelfcarcass, the back panel, a divider between bays and a block of three book spines in each bay, read from the footprint's own long axis; stood on end it is a double-sided stack — the back panel is the long centre line and books stand on both sides900 × 300derived
plant · plantera scalloped crown of eight lobes, alternately long and short as a tree's are, filled with the planting tint, over the pot ring, with eight ribs and the stem—symmetric
carbody rounded at both ends, the bonnet and boot panels, the windscreen and rear window as white trapezoids with the roof between them, a pillar line each side, and a wing mirror each side — inside the footprint—free
sun_lounger · loungerframe and three white cushion panels — the raised back with its headrest at the head end, the seat, and the leg rest—free
meeting_tablea long eased top inside a chair band, with the dining_table chairs tucked under it, backrests out — up to six a side and one at each end2400 × 1200symmetric
reception_deskan L counter — a run along the back with a return down the left, its corners filleted but the reflex corner left sharp — the transaction ledge on the visitor faces, a nosing on each staff face, and the chair inside the L2400 × 900derived
filing_cabinetnarrow carcass and the top's edge bevel, three drawer lines across it, and the pull on the front edge450 × 600derived
lockera run of narrow doors at a clamped count, the door-front line near the front face, and a pull on each door1200 × 450derived
pool_tablethe rail, the cushion band inside it, the cloth, and six pockets — four at the corners, two on the long rails2500 × 1400symmetric
treadmillframe, the console at the wall end with its display, the two side platforms, and the belt between them as a stadium800 × 1800derived

A sun_lounger is aimed at the sun, and ArchLang has no sun model — the site layer names an aspect, not a daylight measurement — so nothing here derives which way it points and nothing warns about it. Say so with rotate.

The six commercial kinds take the drawing out of a house. Two things about them are decided rather than obvious. meeting_table follows dining_table's rule that the footprint includes its chairs — the dimension a plan needs to check is the one you cannot pull a chair out of — so a 2400 mm table is authored as roughly 3000 mm of footprint; it is drawn with an eased top, which is what tells it from the square-topped dining table at a glance. And treadmill carries the largest clearanceMm in the catalogue, 900 mm, because the run-off space behind a user is the one thing a gym plan can be wrong about in a way that matters; dresser, vanity and filing_cabinet carry 600, for a drawer or a chair.

car earns its place for the same reason bench does: it is drawn on real plans (a carport, a driveway, a garage) and a model asked for one will write the word whether or not the catalogue knows it. Its long axis is the driving direction, drawn top-to-bottom like every other symbol's depth, so rotate 90 parks it across a garage.

Outdoor ​

Twenty-one families for what a site plan draws once the drawing leaves the building. They live in their own module (src/elements/glyphs-outdoor.ts), drawn in the indoor symbols' line language (outline in the symbol ink, detail in the fine pen, true curves), and follow one rule the indoor tables do not: planting is a canopy that masks the ground — the tree, the conifer, the shrub and the hedge are each one closed outline filled with the lawn tint, so the ground hatch under them is painted out and the crown reads as one mass.

Kind (and aliases)SymbolFootprintFacingWall
tree · deciduous_treea canopy scalloped into sixteen lobes and filled with the lawn tint (it masks the ground hatch under it), eight forked branches and the trunk—symmetric
conifer · pinea sixteen-point needled star canopy (notched to 0.6 of the crown) in the lawn tint, eight spokes and the tree's trunk—symmetric
shrub · busha closed cloud of eight equal lobes in the lawn tint, with a smaller cloud of foliage inside—symmetric
hedgeONE continuous band in the lawn tint, both faces scalloped and both ends rounded, with the hidden stem line dashed down its middle, and no box2000 × 600free
bbq · grill · barbecuea gas grill: the firebox with its barred grate, a shelf each side, and three control knobs on the front1200 × 600derived
outdoor_table · patio_tablethe dining table's language — the top inside a chair band, chairs tucked under it — round with four chairs when near-square, rectangular with chairs down the sides otherwise, and the parasol hole—symmetric
outdoor_chair · patio_chairthe dining chair's seat and backrest with an arm down each side and slat joints across the seat—free
umbrella · parasolan eight-panel canopy sagging between its ribs, the ribs, and the pole—symmetric
bicycle · bikefrom above: two narrow tyres in line, the frame between them, the saddle, the handlebar across the front tyre, and the cranks with their pedals—free
motorcyclefrom above: the two tyres (the rear wider), the body narrowing to tail and headstock over them, the seat, the tank, and the handlebar with its mirrors—free
hot_tub · spathe rounded shell, the water, the moulded bench round a sunken footwell, and a seat division mid-side—symmetric
swing · swing_setthe top beam, an A-frame splaying to two feet at each end, and two seats hung on their chains—free
trampolinethe padded frame, the mat, and twenty-four springs across the narrow band between them—symmetric
bin · wheelie_binthe body, its lid, the handle along the hinged back edge, and the grip at the front600 × 700derived
mailbox · letterboxthe box with its flap, and the flag beside it400 × 300derived
ev_chargerthe pedestal against the back edge with its display, and the cable — a true arc — with its plug400 × 300derived
pergolathe overhead frame and a rafter grid, dashed and unfilled, on four solid posts—symmetric
sandpit · sandboxthe timber frame, a plain sand field, and a corner seat board in each corner—symmetric
fire_pitthe stone surround with its joints, the fire bowl, four logs and the embers—symmetric
shed · garden_shedthe walls with a pair of doors swung in from the front, the floor, and a dashed roof ridge2400 × 1800derived
clothesline · washing_linea T-post at each end of the run with four lines strung between the arms—free

Nothing out here carries requiresWall, and that is a decision. The flag means services — supply, waste, venting, or hanging off a wall by definition — and W_FIXTURE_FLOATING's own remedy line says "supply/waste/venting runs in the wall". Two kinds tempt you to set it anyway and both are wrong: a hot_tub is genuinely plumbed and is still set down on a deck and fed from below, so a tub in the middle of a terrace is the normal arrangement; an ev_charger is genuinely wired and is as often on a free-standing bollard as on a wall. Outdoors the wall is the exception.

bbq is the only outdoor kind with a frontal clearance (900 mm — the standing room a cook needs at an open grill). The hot tub deliberately has none: it is symmetric, so it has no front to measure one from. The barbecue's back is the top edge, this module's convention — the knobs are on the bottom, where the cook stands, so the top is the edge that goes against a wall or fence.

The shrub and the hedge are each one closed loop of arcs — no straight run and no box (a box around a hedge makes it read as a tray), and no gap between the arcs, which is what lets them carry the lawn tint.

The dashed marks follow one convention every time — above the cut plane or hidden, the rule upper_cabinet follows indoors and the one roof and void ship: the pergola's frame and rafters (its posts are cut, so they are solid), the shed's roof ridge, and the hedge's stem line under its foliage.

The five directional kinds (bbq, bin, mailbox, ev_charger, shed) are the ones you would write against wall or anchor about, and with the hedge (a run, 2000 × 600) they are the six that carry a footprint — so furniture shed against wall fence needs no size. outdoor_chair is deliberately free, for the reason every other seat in the catalogue is: seating is arranged, not installed.

How a symbol is drawn ​

Two tones, two pens. A symbol's OUTLINE is drawn with the thin pen in a derived symbol ink — furnitureStroke mixed three sevenths of the way toward the wall ink, so it reads at 4.5:1 or better on the room fill in every shipped theme — and its DETAIL (cushion joints, pillows, burners, drains) with the finest pen, 0.13 mm on a sheet, in furnitureStroke itself. Stairs, lifts and escalators follow the same two tones, but every line of them is the thin pen. On the plan, style furniture { stroke "#…" } sets the detail tone and the outline follows it in the same hue, and a named colour (stroke "teal") is used for both; the legend's swatches are drawn in the plan's theme and do not pick up a style furniture override. The labelled rectangle of an uncatalogued word is not a symbol and keeps furnitureStroke.

Back on top. Every symbol is drawn with the side that goes against a wall along the top edge of its footprint, then quarter-turned about the footprint centre. So rotate 0 faces the back north, 90 east, 180 south, 270 west. Orient by the wall the piece sits against, or let against wall / in <room> anchor <edge> do it for you.

A drawn symbol ignores its label. A label reaches the drawing only through the labelled-rectangle fallback — that is, only for a kind the catalogue does not know. Writing furniture bed … label "Bed" is harmless but inert: the word stays in the source and in archlang describe --json, and no text appears in the SVG. The fallback is the escape hatch, and it is deliberate: an uncatalogued word (furniture hammock at … label "Hammock") still draws a rectangle with its name in it, which is how you annotate something ArchLang has no symbol for.

A rug is an UNDERLAY, and it is the only kind that is. An underlay lies flat on the floor: furniture stands on it and people walk over it. The drawing honours that in two ways, and four rules read the same fact — every one of them declining a check rather than adding one.

  • It is drawn first, under every other piece of furniture, whatever order the statements are in: a rug written after the sofa standing on it renders exactly as if it had been written before, so the sofa's body covers the rug's lines instead of the lines running across the seat. Two rugs keep their own order.
  • It is drawn with no fill at all — the only floor-level symbol that is (upper_cabinet and range_hood, above the cut, are the others) — so it hides nothing even where no piece stands on it, and every line of it is in the detail pen: it has no outline-weight edge, so it reads as a floor finish, subordinate to the furniture's outlines.
  • A piece standing on it is not an overlap. W_FURNITURE_OVERLAP skips an underlay-and-not-an-underlay pair. Two rugs overlapping each other still warn — one rug half over another is a drawing mistake, and nothing about walking on them says otherwise.
  • It never blocks a fixture's use-space. A rug reaching under the basin is not what W_FURN_CLEARANCE is about; you stand on it.
  • It never blocks a route. Both walkability models — the whole-plan circulation grid behind archlang describe --json's circulation block and the per-room flood fill behind W_ROOM_NO_CLEAR_PATH — drop it before they inflate anything by a body radius, so a rug across the only way into a room does not seal that room off.

W_FURNITURE_WALL_COLLISION deliberately still applies: what you can walk on has no bearing on whether it is drawn inside the plaster. The door rules (W_SWING_OBSTRUCTED, W_DOORWAY_BLOCKED) do not yet know about underlays either, so a rug in a doorway is still reported today.

Several symbols read their own footprint and change what they draw (fridge, oven, island, kitchen_sink and outdoor_table too); two worth spelling out follow. No branch looks at the category word, because the shape is the honest datum:

  • basin draws two bowls, at the quarter points, once the slab is at least 2.2 times as wide as it is deep — the vanity convention. Below that it draws one, centred.
  • bed / double_bed draw two pillows once the mattress aspect (w / h) reaches 0.6, and one below it. On a 2000-long bed that falls at exactly the conventional 1200 mm single/double split, so furniture bed … size 1500x2000 draws the double it plainly is and a double_bed squeezed to 900 draws the single it has become.

A dashed outline means ABOVE THE CUT PLANE, or HIDDEN inside a closed piece. A floor plan is a horizontal section, so anything that sits above the cut is drawn dashed — present, but not cut — and unfilled, so whatever it overhangs still reads through it. upper_cabinet is dashed in its entirety because a wall cabinet hangs above the counter; a bunk_bed's upper deck is dashed for the same reason, and drawing it solid would claim the room has two mattresses of floor area; a vanity's mirror band is dashed because the mirror stands on the table. A part of a piece is dashed on the same terms: a wardrobe's hanging rail (above the cut, behind its closed doors), a desk's drawer pedestal (under the top) and an office_chair's five-star base (under the seat) are drawn dashed over the surface that hides them. It is the same convention roof, void and the outdoor pergola and shed ridge follow, through one shared dashedPattern() helper. There is no syntax for saying "draw this piece above the cut plane" — a kind is dashed because of what it is.

dining_table's footprint includes its chairs. furniture dining_table … size WxH declares the whole eating zone: the table is the inner rectangle inside a chair-zone band, and the seats are drawn in that band. That is the dimension a plan needs to check — a table you cannot pull a chair out of is not a table that fits — so a 1200 mm table is authored as roughly 2400 mm of footprint. Each long side seats one chair per 2.2 band depths of table, up to four, and each end seats one; a chair is tucked under the top by 30% of its depth, so the seats meet the table rather than float beside it. A square table seats one a side — the four-seater — and stays the same drawing under a quarter-turn.

The ASCII plan shows none of this. archlang compile -f txt (and archlang preview --ascii) reduces each piece to a single uppercase letter at its centre — the first letter of its category — because a character grid has no room for a symbol. The CLI turns on the annotate metadata the text backend needs to recover a category, so this works out of the box; a library caller passing a Scene built without compile(src, { annotate: true }) gets no marker at all for a drawn piece.

Sizes: catalogued footprints and the fixture library ​

The Footprint column above is what against wall uses when you omit size, so the common case has no numbers in it at all:

arch
furniture fridge       against wall w_west offset 400  in r_kitchen
furniture stove        against wall w_west offset 1200 in r_kitchen
furniture kitchen_sink against wall w_west offset 2000 in r_kitchen

The other placement modes always need an explicit size — an at (x,y) or in <room> piece has no wall to tell along from depth, so there is no unique answer to derive (E_FURN_SIZE).

Two importable libraries package the standard pieces at typical residential sizes, for when you would rather call a component than write a footprint:

arch
import "lib/fixtures.arch": wc, basin, shower, bathtub, kitchen_sink, counter, fridge
import "lib/furniture.arch": bed, double_bed, sofa, desk, wardrobe

wc(6200, 4600)
basin(5200, 4450)
shower(6000, 5000)
LibraryComponents
lib/fixtures.archwc 400 × 700 · basin 600 × 450 · shower 900 × 900 · bathtub 1700 × 700 · kitchen_sink 800 × 600 · counter 600 × 600 · fridge 600 × 650
lib/furniture.archbed 1500 × 2000 · double_bed 1800 × 2000 · nightstand 450 × 400 · wardrobe 1800 × 600 · sofa 2000 × 900 · sofa_l 2600 × 1600 · rug 2000 × 1400 · armchair 900 × 850 · coffee_table 1100 × 600 · tv_unit 1500 × 450 · dining_table 2400 × 2000 · desk 1400 × 700 · bookshelf 900 × 300 · piano 1500 × 1500 · sun_lounger 700 × 1900 · stove 600 × 600 · washer 600 × 600

Imports need a filesystem, so they work from the CLI and the library but not in the browser playground — the flagship examples/studio.arch uses inline furniture for exactly this reason. examples/furnished-flat.arch is the worked example: a two-bedroom flat furnished with twenty-nine of the thirty-six kinds across all five domains, archlang validate --strict clean.

Furnishing empty rooms — archlang finish ​

archlang finish plan.arch furnishes the rooms that hold no furniture, then completes the sheet (--only furnish runs the first step alone). It is an explicit source transform (ADR 0025): compile never adds a piece. The room's use comes from uses, else from its label. A room with several uses gets the union, the wall fixtures first. The table describes the rooms of a dwelling.

Room usePieces, in the order they are placed
bedroombed 1500 × 2000, then 900 × 2000 · wardrobe 1800 × 600, then 1200 × 600 (optional)
livingsofa 2000 × 900, then 1600 × 900 · coffee_table 1000 × 600 (optional)
diningdining_table 1800 × 1500, then 1400 × 1300
officedesk 1400 × 700, then 1200 × 600 · office_chair 500 × 500 (optional)
kitchenkitchen_sink · stove · fridge (optional)
bathwc · basin · bathtub or shower (optional)
wcwc · basin

Sizes are along the wall × into the room, in mm; a piece with no size uses its catalogued footprint. A room of any other use (hall, circulation, entry, storage, garage, utility) or of no known use is left alone: utility does not say laundry, and a plant room carries the tag too. A room larger than 100 m² is not a dwelling room; it is named in unresolved and left as it is.

A use's wall fixtures form one run: the stove next to the sink, the fridge next to the stove, on one wall. A use whose required pieces cannot be placed together is left out whole and named in unresolved.

  • Fill only. A room gains pieces only when nothing stands on its floor and nothing is declared in it. A piece stands on a room's floor when its footprint reaches it; a piece declared in another room must reach more than 100 mm onto it, the overhang W_FIXTURE_WRONG_ROOM allows at a wall. Nothing authored is moved, resized or deleted.
    • A room that holds some pieces but lacks one its use requires (a living room with a lamp and no sofa) is named in unresolved with the missing pieces, and is not filled. A piece that does the job counts: a double_bed for a bed, and a urinal for a wc in any wet room, a dwelling bathroom included.
    • A room whose only pieces are declared in it but stand outside it is named in unresolved as holding no piece on its floor, with W_FIXTURE_WRONG_ROOM, and is not filled: fix the piece's position or its in first.
  • Relative placement. A services fixture is written against wall <id> offset …; a free-standing piece in <room> anchor … flush size WxH rotate …. Never at (x,y).
  • Never worse. A room's pieces are kept only when the plan still compiles and raises no diagnostic it did not have. Otherwise the next position is tried. When a required piece has no position, the room is left empty and named in unresolved with the code that blocked it. An optional piece that does not fit is left out.
  • Scope. Rectangular rooms of single-storey plans. A polygon room, and a plan with level blocks, are reported in unresolved and left as they are.

Furniture-aware lint rules ​

Placing fixtures meaningfully lets archlang lint reason about habitability. The furniture and fixture rules (each documented in the error catalog):

CodeFlags
W_FIXTURE_FLOATINGa services fixture — plumbed, vented, or hung off the wall (WC, basin, shower, bath, sink, counter, stove, fridge, dishwasher, washer, dryer, upper cabinet) — placed away from any wall
W_FIXTURE_BACK_TO_ROOMa piece that is against a wall but faces the wrong way — its back (cistern, tap, nosing, headboard, wardrobe door line, bookshelf's open face) turned to the room. Carries a rotate fix when one edge is unambiguously the back. Arranged seating never trips it
W_FIXTURE_WRONG_ROOMa piece declared in <room> whose footprint does not sit on that room's floor (100 mm of overhang is allowed — a room edge is a wall centreline)
W_FURNITURE_OVERLAPtwo pieces overlapping by more than 1 mm on both axes — except an underlay and a piece standing on it (a sofa on a rug), which is the arrangement
W_FURN_CLEARANCEa fixture's frontal use-space blocked by free-standing furniture (an underlay never counts as the blocker)
W_ROOM_NO_FIXTUREa bath / WC / kitchen room with none of the relevant fixtures
W_SWING_OBSTRUCTEDa door leaf or swing arc sweeping onto a fixture

These are advisory — facts and warnings, never an auto-arranger (see ADR 0005). See Analysis: describe & lint for the full rule set and profiles.