ArchLang Playground

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.

Living / Dining 28.8 m² Bedroom 1 14.4 m² Bedroom 2 14.4 m² Kitchen 11.1 m² Hall 13.5 m² Bath 6.2 m² Laundry 4.8 m² Entry 8.8 m² 3400 600 5600 1000 1600 3000 2800 200 2000 1000 3000 12200 6100 1200 1400 4800 1500 2200 8700 300 1400 2200 2000 900 1600 1400 1600 800 3000 2800 200 2000 1000 3000 12200 1900 1200 2100 900 2600 4800 1500 2200 8700 100 200 ROOM SCHEDULE NO. NAME AREA (m²) 01 Living / Dining 28.80 02 Bedroom 1 14.40 03 Bedroom 2 14.40 04 Kitchen 11.10 05 Hall 13.50 06 Bath 6.16 07 Laundry 4.84 08 Entry 8.80 TOTAL 102.00 N 02 m PROJECTSuburban BungalowDRAWN BYArchCanvasDATE2026-08-13SCALE1:100
"Bungalow" — a 8-room floor plan, 102 m² total: Living / Dining (28.8 m²), Bedroom 1 (14.4 m²), Bedroom 2 (14.4 m²), Kitchen (11.1 m²), Hall (13.5 m²), Bath (6.16 m²), Laundry (4.84 m²), Entry (8.8 m²); 6 doors, 7 windows, entrances via d_front, d_garden.
Open in the editor

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"
  }
}

Read more