Sign in

RAP Studio

Design a building without needing to see it. The Radical Accessibility Project (RAP) is a way for blind and low-vision students to author architecture alongside sighted classmates — and this page is a hands-on demo of it, running right in your browser. No account or install needed to try it.

You lay out a plan by typing plain-English requests, short commands, or filling in form fields. The studio keeps your whole design as a single text file and shows it back to you several ways at once — a 3D model, a touch-readable plan, a written description, and Braille — plus downloads for a swell-paper tactile print and a 3D print. The 3D view is only an aid for sighted testing; nothing here needs sight to use. When you’re ready, the same design can be sent to Rhino, the 3D CAD software architects design in.

Loaded with a sample model — one building described at three phases (Massing → Structure → Plan), the same building at rising resolution. Use the phase rail below to focus one phase and author it cleanly (the others show as a dashed reference ghost), or pick Composite to see the whole building together. The Assistant is the main way to author: describe what you want in plain language and it writes the Controller commands for you — the same way a designer directs Claude Code in a terminal. Every change is read back in all channels (plan, 3D, text, Braille, state tree). Prefer to type commands yourself? Switch to the Console. Use Load starter to begin from an empty model, a bay grid, a massing diagram, a single floor plate, or the sample.

Design phases — focus one, or compose the whole building

New geometry lands in the focused phase; other phases show as a dashed reference ghost (a finger reads hollow context vs. solid figure — except columns, which always print solid as registration marks). The focused phase's lens — structural bays, massing, or floor-plan layout — scopes the Console, Assistant, and Forms.

Author

Type a command, or “help”. Try: wall A off

Type help for the full command list · / for history.

Model — visual test

The 3D view is an orthographic (parallel) black-and-white aid for sighted testing — hidden from screen readers. Solid black edges are visible; dotted black edges are hidden lines. The model is fully readable in the tactile plan, the read-back text, and the state tree.

Canonical state.json

state {15}
schema: "rhino_controller_v4.0"
mode: "bays"
phases [3]
0 {7}
id: "massing"
name: "Massing"
schema: "massing"
order: 0
derivedFrom: null
basis: null
visible: "auto"
1 {7}
id: "structure"
name: "Structure"
schema: "bays"
order: 1
derivedFrom: "massing"
basis: "18,12,78,52"
visible: "auto"
2 {7}
id: "plan"
name: "Plan"
schema: "floorplan"
order: 2
derivedFrom: "structure"
basis: "18,12,78,52"
visible: "auto"
focus: "structure"
meta {3}
created: "web-studio"
last_saved: "web-studio"
notes: "Authored in RAP Studio (web)"
site {4}
origin [2]
0: 0
1: 0
width: 100
height: 100
boundary [5]
0 [2]
0: 8
1: 6
1 [2]
0: 92
1: 6
2 [2]
0: 92
1: 78
3 [2]
0: 60
1: 94
4 [2]
0: 8
1: 78
style {9}
column_size: 1.5
heavy_lineweight_mm: 1.4
light_lineweight_mm: 0.08
corridor_lineweight_mm: 0.35
wall_lineweight_mm: 0.25
label_text_height: 0.3
braille_text_height: 0.5
corridor_dash_len: 3
corridor_gap_len: 2
layers {5}
Default {3}
name: "Default"
lineweight_mm: 0.25
linetype: "solid"
massing {3}
name: "massing"
lineweight_mm: 0.35
linetype: "solid"
structure {3}
name: "structure"
lineweight_mm: 0.35
linetype: "solid"
slab {3}
name: "slab"
lineweight_mm: 0.25
linetype: "solid"
walls {3}
name: "walls"
lineweight_mm: 0.25
linetype: "solid"
bays {1}
A {17}
grid_type: "rectangular"
z_order: 0
origin [2]
0: 18
1: 12
rotation_deg: 0
bays [2]
0: 3
1: 2
spacing [2]
0: 20
1: 20
corridor {5}
enabled: false
axis: "x"
position: 1
width: 8
loading: "double"
walls {2}
enabled: false
thickness: 0.5
apertures [0]
void_center: null
void_size: null
void_shape: "rectangle"
label: "Bay A"
braille: "⠠⠃⠁⠽ ⠠⠁"
level: 0
layer: "structure"
phase: "structure"
walls [5]
0 {7}
id: "pw-s"
level: 0
a [2]
0: 18
1: 12
b [2]
0: 78
1: 12
thickness: 0.5
layer: "walls"
phase: "plan"
1 {7}
id: "pw-e"
level: 0
a [2]
0: 78
1: 12
b [2]
0: 78
1: 52
thickness: 0.5
layer: "walls"
phase: "plan"
2 {7}
id: "pw-n"
level: 0
a [2]
0: 78
1: 52
b [2]
0: 18
1: 52
thickness: 0.5
layer: "walls"
phase: "plan"
3 {7}
id: "pw-w"
level: 0
a [2]
0: 18
1: 52
b [2]
0: 18
1: 12
thickness: 0.5
layer: "walls"
phase: "plan"
4 {7}
id: "iw1"
level: 0
a [2]
0: 18
1: 32
b [2]
0: 78
1: 32
thickness: 0.5
layer: "Default"
phase: "plan"
regions [5]
0 {9}
id: "g_mass1"
level: 0
kind: "box"
origin [2]
0: 18
1: 12
size [2]
0: 60
1: 40
height: 24
name: "Envelope"
layer: "massing"
phase: "massing"
1 {9}
id: "g_mass2"
level: 0
kind: "box"
origin [2]
0: 48
1: 24
size [2]
0: 16
1: 16
height: 36
name: "Core"
layer: "massing"
phase: "massing"
2 {9}
id: "g_slab1"
level: 0
kind: "plate"
origin [2]
0: 18
1: 12
size [2]
0: 36
1: 40
thickness: 0.5
name: "Plate 1"
layer: "slab"
phase: "plan"
3 {9}
id: "g_slab2"
level: 0
kind: "plate"
origin [2]
0: 54
1: 12
size [2]
0: 24
1: 40
thickness: 0.5
name: "Plate 2"
layer: "slab"
phase: "plan"
4 {9}
id: "g_slab3"
level: 1
kind: "plate"
origin [2]
0: 18
1: 12
size [2]
0: 60
1: 40
thickness: 0.5
name: "Upper plate"
layer: "slab"
phase: "plan"
columns [0]
openings [3]
0 {6}
id: "op1"
wallId: "iw1"
type: "door"
pos: 0.5
width: 4
height: 7
1 {6}
id: "op2"
wallId: "pw-s"
type: "door"
pos: 0.25
width: 4
height: 7
2 {6}
id: "op3"
wallId: "pw-w"
type: "window"
pos: 0.3
width: 6
height: 4
levels [2]
0 {3}
name: "ground"
z: 0
label: "Ground"
1 {3}
name: "level2"
z: 12
label: "Level 2"
tactile3d {6}
enabled: true
wall_height: 9
cut_height: 4
floor: true
floor_thickness: 0.5
scale_factor: 1

Read-back — the non-visual model

FOCUS — Structure (think in a column grid), refining Massing. Other phases read hollow for reference — except columns, which always print solid.

OVERVIEW — An irregular infill lot (5-sided, within 100×100 ft); 2 levels. Holds 1 structural bay, 3 floor plates, 2 extruded boxes, 5 free walls, 0 columns, across 3 phases on 5 layers.
LAYERS — Default (solid, 0.25 mm); massing (solid, 0.35 mm); structure (solid, 0.35 mm); slab (solid, 0.25 mm); walls (solid, 0.25 mm).

PHASES (3) —
  • Massing (massing): 2 elements, 60×40 ft [reference]
  • Structure (bays): 1 element, 60×40 ft, from Massing [focused]
  • Plan (floorplan): 8 elements, 60×40 ft, from Structure [reference]

LEVEL 0 — Ground (z=0 ft):
  • bay Bay A: 3×2 grid @ 20×20 ft, origin (18,12)
LEVEL 1 — Level 2 (z=12 ft):
  • (nothing from the focused phase on this level)

NOT SHOWN IN DETAIL — 10 element(s) in other phases (counted in PHASES above).
Braille key
⠠⠃⠁⠽ ⠠⠁ Bay A
⠠⠑⠝⠧⠑⠇⠕⠏⠑ Envelope
⠠⠉⠕⠗⠑ Core
⠠⠏⠇⠁⠞⠑ ⠼⠁ Plate 1
⠠⠏⠇⠁⠞⠑ ⠼⠃ Plate 2
⠠⠥⠏⠏⠑⠗ ⠏⠇⠁⠞⠑ Upper plate

Drive Rhino — talk to state.json + the Watcher

How it works: your model is one state.json file. A small Watcher running inside Rhino rebuilds the geometry every time that file changes. So the whole job is getting state.json into the folder the Watcher is watching — three ways below, simplest first. (Set up the Watcher in Rhino once; see the last card.)

Surfaces vs. mesh: driving Rhino this way rebuilds your model as native Rhino solids — plates and boxes become real surfaces you keep editing, which is Rhino’s default working mode. The Export STL button instead writes a fixed mesh(a triangle skin) for printing or hand-off — not surface-editable. Same model, two representations: know which one you’re holding. (The Export .3dm button in the toolbar above makes the same choice explicit — native surfaces by default, mesh with its “as mesh” toggle.)

This page(browser)state.jsonin your folderWatcherin RhinoRhino3D modelwriteswatchesrebuilds
Options A and B put state.json into the folder by hand or by connecting it. The live link (Option C) pushes it straight from this page the moment you change anything — so Rhino rebuilds as you work.

Studio-native elements: 5 geometric regions, 5 free walls, 3 wall openings travel in the file under web_* keys. The Watcher below (v3, “web edition”) rebuilds all of them in Rhino — plates and boxes as solids, free walls with their openings, the irregular site boundary as a real polyline, and your design phases as toggleable sublayers. An older desktop Watcher rebuilds only the bays/apertures/levels core and skips the rest — if that’s what you have, grab the new one below.

Option A · Download the file (any browser, no setup)

Save it into your Rhino project folder — the one the Watcher is watching. It is the same file as Export → state.json at the top of the page; write it again whenever you want Rhino to rebuild.

Option B · Auto-write to that folder (Chrome or Edge)

This browser can’t write files directly — use Chrome or Edge, or use Option C below.

Option C · Live bridge (any browser)

For any browser, or a live link to Rhino: a tiny helper runs on your machine and this page pushes to it. Set it up once:

  1. Download the helper and save it next to your Rhino project folder:
  2. In a terminal, run it pointed at that folder:
    python3 rap_bridge.py --folder /path/to/your/rap-project
  3. It prints a URL and a token — paste them here and test:
  4. Push the model — now, or automatically on every change:

In Rhino (once)

Download the RAP Watcher, open it in Rhino’s ScriptEditor (type ScriptEditor, open the file, press play), and set its STATE_FILE to the state.json in your project folder. It rebuilds the whole model whenever that file changes — bays, corridors and apertures, plus the studio’s floor plates, extruded boxes, free walls with their openings, columns, the irregular site boundary, and your design phases as toggleable sublayers.

How to use this — instructions & tips

The idea

There is one canonical model (the state.json above). Every way of building — the Assistant, the Console, and the Forms — writes the same commands to it, and every view — the tactile plan, the 3D aid, the read-back text, the Braille key, and the state tree — reads from that one model. Change it once, and it's correct in every channel at the same time. That parity is the whole point: a designer using a screen reader and a designer looking at the plan are working on the identical building.

Getting started

  1. Read the sample model in the views to see what a finished model looks like.
  2. Use Load starter → Empty to start from an empty model (or → Sample model to bring the example back).
  3. In the Assistant, describe a move — e.g. “add a 36 by 20 floor plate on a new slab layer.”
  4. Watch the commands it ran, and confirm the change in the read-back and the plan.
  5. Keep going one move at a time; export when you're ready to drive Rhino.

Tips

  • Assistant is fastest for whole moves; Console gives you exact control — type help for every command.
  • In the Assistant, press Enter to send (Shift+Enter for a new line).
  • Made a wrong move? Undo / Redo step through your whole history (loading a starter is undoable too).
  • Turn on Speak confirmations to hear every change announced aloud.
  • Use the level selector on the model to view and export one floor at a time.
  • The 3D view is only a sighted aid — it's hidden from screen readers. The plan, read-back, and Braille are the real model.
  • Exports — state.json, PIAF PNG (tactile print), STL (3D print), and the command log — all match what's on screen.
Driving real Rhino — what’s next. The state.json you download here is the interchange. Drop it into a RAP working folder and the existing Watcher (TCP 1998) rebuilds the model in desktop Rhino — a free, working drive with no new infrastructure. A small local companion bridge would make it live (type here, Rhino moves). See the options write-up for the full menu.