Skip to main content

porta

porta is two things:

  1. A DSL for concisely defining a relational floorplan; and
  2. A software package for deterministically converting a floorplan into a clean SVG map.
room hall    "Great Hall" 40x20 root
room parlour "Parlour"    20x20 left-of hall
room kitchen "Kitchen"    20x20 right-of hall
room study   "Study"      ?x20  down-of parlour

The porta DSL

porta floorplans are defined in .porta files adhering to a strict specification. Each room is defined in a single line relative to one or more anchor rooms, forming a dependency graph all the way back to the initial root room. This model creates a 1-to-1 correspondence between the floorplan and the final SVG map it produces, allowing porta to rapidly and deterministically generate one from the other.

Files are read line by line: a # starts a comment that runs to the end of the line (a # inside a quoted name is literal), and blank lines are ignored.

Any statement can be continued onto the next physical line by ending it with a backslash, separated from the last token by whitespace:

room pn "" 40x10 root
room pw "" 10x20 down-of pn
room pe "" 10x20 down-of pn align=end
room ps "" 40x10 down-of pw \
    down-of pe
block passages "Passages" glyph=pn \
    pn pw \
    pe ps

Continued lines parse as one statement, and errors still point at the physical line of the offending token. A backslash anywhere else — mid-line, glued to a token, or followed by a comment — is an error, as is a blank (or comment-only) line inside a continued statement.

For more on the porta DSL specification, see the following documentation:

  • Rooms — the room statement, room positioning, auto-dimensions (?), disconnected components, and the layout resolution procedure.
  • Doors — default doors & how to modify them, and the door statement for explicitly adding non-default doors.
  • Blocks — the block statement for joining multiple rooms into a single non-rectangular space.
  • Links — the link statement for joining disconnected components into one continuous plan.

The porta tool

Once a valid floorplan has been written, porta draw converts it into an SVG map in a two-step process. First, the dependency graph is traversed and the relations in the floorplan are converted into a coordinate system. Second, that coordinate system is used to deterministically generate an SVG file.

porta draw plan.porta -o plan.svg

The solved coordinate system can also be viewed and debugged directly as an ASCII grid:

porta draw plan.porta --debug-ascii

A plan that can't be solved (due to overlaps, missing anchors, gaps between a room and its anchor, etc) will fail and raise an error.

Installation

porta is published on PyPI and can be installed with pip:

pip install porta

Alternatively, install it from a checkout of this repo. Add the [dev] extra to pull in the test and lint tools as well:

pip install -e .          # editable install
pip install -e ".[dev]"   # ... plus pytest, ruff, and mypy

Why porta?

porta is built to be:

  • Text-based — a plan is plain text: editable in any editor, diffable, and version-controlled alongside your campaign notes. No WYSIWYG, no binary files.
  • Concise — a terse syntax with strong defaults; a whole plan is a handful of short lines.
  • Deterministic — no procedural generation and no randomness; the same plan always renders the same map.
  • Relational — rooms are placed against other rooms, never drawn by hand or given raw coordinates.
  • Spatial — the output is a flush, to-scale floor plan in tabletop conventions, not a flowchart or connectivity graph.
  • Fast — placement is a single pass over a dependency graph, with no constraint solver to run.
  • AI-friendly — terse, text-only, and predictable, so a language model can read and write plans reliably (this one falls out of the rest).

No existing tool hits all of these:

  • Procedural and AI generators (Watabou, Inkarnate) aren't deterministic or controllable — they invent a layout instead of rendering yours.
  • GUI map editors (Dungeondraft, Dungeon Scrawl) aren't text: mouse-driven, binary, and kept apart from your notes.
  • Diagram tools (Mermaid, Graphviz, D2) give connectivity, not a spatial, to-scale map.
  • Hand-written SVG is text, but neither concise nor relational — verbose and easy to get wrong.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

porta-1.4.0.tar.gz (90.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

porta-1.4.0-py3-none-any.whl (33.9 kB view details)

Uploaded Python 3

File details

Details for the file porta-1.4.0.tar.gz.

File metadata

  • Download URL: porta-1.4.0.tar.gz
  • Upload date:
  • Size: 90.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.12.1 {"installer":{"name":"uv","version":"0.12.1","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for porta-1.4.0.tar.gz
Algorithm Hash digest
SHA256 1fcbd243718ce0a52a01a6f358b9dc179b372db0fddfb974d9232bd174de96d2
MD5 536bf28b4c8c10fba3ad6f2948fb31d4
BLAKE2b-256 1ee7a033141c537883de3b46d03ea4eff67b20a0459bf3c4547bf34665c25865

See more details on using hashes here.

File details

Details for the file porta-1.4.0-py3-none-any.whl.

File metadata

  • Download URL: porta-1.4.0-py3-none-any.whl
  • Upload date:
  • Size: 33.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.12.1 {"installer":{"name":"uv","version":"0.12.1","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for porta-1.4.0-py3-none-any.whl
Algorithm Hash digest
SHA256 9ced5035a9e56d6a112504de283e6bf98f19763f0e49239a26c3cf108b043d73
MD5 dd53ee19d5d43760d70bc445e9c0e4f0
BLAKE2b-256 5f0b903121ccf9bbf771bdd46627a970740fee59c1fcdc1beddfd68049444dbd

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page