Bungalow (site + doors) — an ArchLang floor plan example
A single-storey bungalow whose whole layout follows one stated fact: the street is south and the garden north.
This plan compiles to 8 rooms, 102 m² of floor area and 7 windows; every room is reachable from the entrance.
The source
This is the whole plan. The drawing above is what the compiler produced from it — nothing was drawn by hand.
# A single-storey suburban bungalow — the ORIENTATION-AND-OPENINGS example (v1.25).
#
# The plot fronts the street on the SOUTH and the garden on the NORTH, in the southern
# hemisphere. That one fact decides the whole layout, so the plan states it:
#
# site { street south hemisphere south }
#
# `site` draws nothing. It names five directions on `arch describe --json --select site`:
# `street` (S), `back` (N — the garden), `equator_side` (N, because south of the equator
# the equator lies northward), `sunrise_side` (E) and `sunset_side` (W). Here `back` and
# `equator_side` are the SAME side, which is exactly why the house turns away from the
# road: the living room and both bedrooms take the north facade, and the service band —
# entry, hall, bath, laundry, kitchen — is stacked along the street. One advisory lint
# rule reads it, `W_ROOM_NOT_EQUATOR_FACING`; leave a bedroom with nothing but its east
# window and it will say so.
#
# These are DRAFTING HEURISTICS FOR AN ASPECT, not a daylight measurement. ArchLang has
# no sun model, no latitude and no date, so `equator_side` says which way a window looks
# and nothing whatever about how much light comes through it.
#
# The other half of the plan is the door KINDS. A leaf is not always hinged, and the
# three non-default kinds here are each where a builder would actually put one:
#
# sliding the garden door — the full-height slider onto the deck
# pocket the bath, off a 1500 mm corridor: no leaf in the hall, none in the bath
# bifold the laundry, folding into its own opening rather than over the machines
#
# A non-hinged leaf sweeps nothing, so `doorSwing()` returns null for all three and
# `W_SWING_OBSTRUCTED` cannot apply to them — only the two bedroom doors, which take the
# default `hinged` by writing no kind at all, carry a swing arc.
plan "Bungalow" {
units mm
# `grid 50` because every partition here is 100 thick and the plan is set out in
# half-metres. It used to be a WORKAROUND as well: a fixture placed `flush` against a
# 100 partition lands on a half-thickness (…50) coordinate, and the resolver used to
# grid-snap that DERIVED coordinate like an authored one, so `grid 100` rounded it back
# INTO the wall and raised `W_FURNITURE_WALL_COLLISION` on a correct plan. A derived
# coordinate is no longer snapped, so the grid is free again — these numbers are
# unchanged, and so is every byte this file draws.
grid 50
paper A3 landscape
scale 1:100
north up
dims auto all
schedule rooms
site { street south hemisphere south }
# ---- shell + structure ----------------------------------------------------
# `w_spine` runs the full width and divides the garden band from everything behind it;
# `w_service` does the same for the street band. Both are named because the doors below
# are placed `on` them by RUN DISTANCE from the wall's first point, and because
# `W_POCKET_RUN` measures the panel's cavity along one named segment.
wall id=shell exterior thickness 200 { (0,0) (12000,0) (12000,8500) (0,8500) close }
wall id=w_bed1 partition thickness 100 { (6000,0) (6000,4800) }
wall id=w_bed2 partition thickness 100 { (9000,0) (9000,4800) }
wall id=w_spine partition thickness 100 { (0,4800) (12000,4800) }
wall id=w_kitchen partition thickness 100 { (3000,4800) (3000,8500) }
wall id=w_service partition thickness 100 { (3000,6300) (12000,6300) }
wall id=w_bath partition thickness 100 { (5800,6300) (5800,8500) }
wall id=w_laundry partition thickness 100 { (8000,6300) (8000,8500) }
# ---- rooms ----------------------------------------------------------------
# Garden band (north): the rooms people sit and sleep in, every one of them on the
# equator-facing facade. Street band (south): the rooms that do not need it.
room id=r_living at (0,0) size 6000x4800 label "Living / Dining" uses living dining
room id=r_bed1 at (6000,0) size 3000x4800 label "Bedroom 1" uses bedroom
room id=r_bed2 at (9000,0) size 3000x4800 label "Bedroom 2" uses bedroom
room id=r_kitchen at (0,4800) size 3000x3700 label "Kitchen" uses kitchen
room id=r_hall at (3000,4800) size 9000x1500 label "Hall" uses hall circulation
room id=r_bath at (3000,6300) size 2800x2200 label "Bath" uses bath
room id=r_laundry at (5800,6300) size 2200x2200 label "Laundry" uses utility
room id=r_entry at (8000,6300) size 4000x2200 label "Entry" uses entry
# ---- doors: one kind per situation ----------------------------------------
# The front door is on the street facade, and it is the only exterior hinged leaf.
door id=d_front at (10000,8500) width 1000 wall shell hinge left swing in
# The garden door. A slider is what a deck opening actually is, and it is why the
# living room can open this far to the north without a leaf eating the floor.
# `slide left` runs the panel back toward the wall's start — onto the solid pier
# between this opening and the window, not across the glass.
door id=d_garden sliding at (4800,0) width 2000 wall shell slide left
# Bedrooms keep the default: `hinged` is what you get by writing no kind at all, and
# these two are the only doors in the plan with a swing arc to obstruct.
door id=d_bed1 on w_spine at 7500 width 800 hinge left swing in
door id=d_bed2 on w_spine at 10500 width 800 hinge right swing in
# The bath. A hinged leaf here has nowhere good to go: outward it blocks a 1500 mm
# corridor, inward it fouls the basin. A pocket door answers both, and `slide` is not
# cosmetic here — `w_service` is walked west to east, so `slide right` drives the panel
# into the 2200 mm of solid wall between this jamb and the laundry door. `slide left`
# would aim it at the corner instead, where the run is 500 mm against the 850 mm an
# 800 mm panel needs, and `W_POCKET_RUN` would report it 350 mm short.
door id=d_bath pocket on w_service at 900 width 800 slide right
# The laundry, one room further along the same wall. A bifold folds into its own
# opening, so it swings neither into the corridor nor over the machines.
door id=d_laundry bifold on w_service at 3900 width 800
# Cased openings: circulation needs no leaf.
opening id=o_kitchen at (1500,4800) width 2400 wall w_spine
opening id=o_living at (4500,4800) width 1400 wall w_spine
opening id=o_pantry at (3000,5550) width 900 wall w_kitchen
opening id=o_entry at (10000,6300) width 1200 wall w_service
# ---- windows --------------------------------------------------------------
# North first: every habitable room gets the equator-facing aspect, which is what keeps
# `W_ROOM_NOT_EQUATOR_FACING` quiet. Then the ends, then the street side.
window id=n_living at (900,0) width 1400 wall shell
window id=n_bed1 at (7500,0) width 1600 wall shell
window id=n_bed2 at (10500,0) width 1600 wall shell
window id=e_bed2 at (12000,2400) width 1200 wall shell # sunrise side as well as north
window id=e_hall at (12000,5550) width 900 wall shell # light to the corridor's end
window id=w_sink at (0,6600) width 1200 wall shell # sunset side, over the sink
window id=s_bath at (3600,8500) width 600 wall shell
# ---- fixtures -------------------------------------------------------------
# No fixture here names an absolute coordinate against a wall, and none writes a
# `rotate`. The kitchen run rides the shell's west segment, so `offset` is a distance
# ALONG that segment (measured from its first point, (0,8500)) and both the position
# and the quarter-turn are derived from the wall; the size comes from the catalogue.
# The sanitary fixtures are anchored to their room instead, where `flush` measures
# from the backing wall's inner FACE, so no half-thickness is written down by hand.
furniture kitchen_sink against wall shell segment 3 offset 1900 in r_kitchen # under the window
furniture stove against wall shell segment 3 offset 1100 in r_kitchen
furniture fridge against wall shell segment 3 offset 500 in r_kitchen
furniture basin in r_bath anchor left flush size 450x600
furniture wc in r_bath anchor bottom flush size 400x700
furniture shower in r_bath anchor right flush size 900x900
furniture counter in r_laundry anchor bottom flush size 1400x600
furniture sofa at (600,2600) size 2200x900 label "Sofa"
furniture table at (3600,1800) size 1400x900 label "Table"
furniture bed at (6200,200) size 1500x2000 label "Bed"
furniture bed at (9200,200) size 1500x2000 label "Bed"
# ---- the eaves ------------------------------------------------------------
# A bungalow is mostly roof, and on a hot plot it is the eave that shades the north
# glazing rather than any glass. One line draws it: the outline is DERIVED by pushing
# `shell`'s ring out by half its thickness plus 600, mitred at each corner, so it moves
# if the walls do and there is no second set of coordinates to keep in step. `shell` is
# the only closed `exterior` wall here, so it needs no naming — write
# `roof overhang 600 wall shell` if a second one is ever added, or the plan gets
# `E_ROOF_AMBIGUOUS` rather than a guess.
#
# It draws and nothing more: no `describe()` key, no lint rule, no schedule row. What
# it does change is the PAGE — the drawing extent now includes the eaves, so the sheet
# grows to hold them.
roof overhang 600
title {
project "Suburban Bungalow"
drawn_by "ArchCanvas"
date "2026-08-13"
}
}