diff --git a/DESIGN.md b/DESIGN.md
new file mode 100644
index 00000000..588b1feb
--- /dev/null
+++ b/DESIGN.md
@@ -0,0 +1,225 @@
+# subiquity design notes
+
+## UI
+
+### basic ground rules:
+
+1. Subiquity is entirely usable by pressing up, down, space (or return) and the
+ occasional bit of typing.
+
+2. The UI never blocks. If something takes more than about 0.1s, it is done in
+ the background, possibly with some kind of indication in the UI (and the
+ ability to cancel if appropriate).
+
+3. General UX principles that it is worth keeping in mind:
+
+ 1. Prevent invalid use if that makes sense (e.g. unix usernames can never
+ contain spaces, so you simply can't enter spaces in that box)
+
+ 2. When rejecting input, be clear about that to the user and explain what
+ they need to do differently (e.g. when you do try to put a space in a
+ unix username, a message appears explaining which characters are valid).
+
+ 3. Make the common case as easy as possible by doing things like thinking
+ about which widget should be highlighted when a screen is first shown.
+
+4. Subiquity is functional in an 80x24 terminal. It doesn't matter if it falls
+ apart in a smaller terminal and obviously you can get more information on a
+ larger terminal at once, but it needs to work in 80x24.
+
+### urwid specific ranting
+
+subiquity is built using the [urwid](http://urwid.org/) console user interface
+library for Python. urwid is mostly fine but has some design decisions that
+have meant that we're sort of slowly re-implementing pieces of it.
+
+The main one of these is that in urwid, widgets do not have a size; they
+inherit it from their parent widget. While this is unavoidable for the "outer"
+widgets (subiquity does not get to decide the size of the console it runs in!)
+I don't think it leads to a good appearance for things like stacked columns of
+buttons, which we want to fit to label length (and label length depends on
+which language it is being used in!). There is a similar tension around having
+scroll bars that are only shown when needed (scroll bars should only be shown
+when the contained widget "wants" to be taller than the space available for
+it).
+
+subiquity has a few generic facilities for handling these:
+
+ * The `subiquitycore.ui.containers` module defines a `ListBox` class that
+ automatically handles scroll bars. It is used everywhere instead of urwid's
+ `ListBox` class (it does not support lazy construction of widgets like
+ urwid's does).
+
+ * The `subiquitycore.ui.stretchy` module defines classes for creating modal
+ dialogs out of stacks of widgets that fit to their content (and let you say
+ which widget to scroll if the content is too tall to fit on the screen).
+
+ * The `subiquitycore.ui.width` module defines a `widget_width` function, which
+ knows how wide a widget "wants" to be (as above, this isn't a concept urwid
+ comes with).
+
+ * The `subiquitycore.ui.table` module defines classes for creating Tables that
+ act a little like `
` elements in HTML.
+
+Subiquity also has replacements for the standard containers that handle tab
+cycling (i.e. tab advances to the next element and wraps around to the
+beginning when at the end).
+
+urwid can be extremely frustrating to work with, but usually a good UI can be
+implemented after sufficient swearing.
+
+### The typical screen
+
+A subiquity screen consists of:
+
+ 1. a header
+ 2. a body area, which usually contains
+ 1. an excerpt (which explains what this screen is for)
+ 2. a scrollable content area
+ 3. a stack of buttons, including "done"/"cancel" buttons for moving between
+ screens
+ 3. a footer
+
+The header has a summary line describing the current screen against an "ubuntu
+orange" background.
+
+The footer has a progress bar indicating how far through the install process
+the user was, a blank line and the summary area. Currently the summary area
+contains static content for the first few screens, but there are vague plans to
+make it specific to the currently focused element. Once the install has started
+but before we get to the final screen, the summary area contains a summary of
+progress made by the installation. Someday soon the summary area will also
+contain a button that allows you to drop to a shell at any point.
+
+The body area is where most of the action is. It follows a standard pattern
+described above, and the `subiquitycore.ui.utils.screen()` function makes it
+very easy to follow that pattern. Many screen have "sub-dialogs" (think:
+editing the addresses for a NIC) which can be as large as the whole body area
+but are often smaller. The base view class has `show_overlay`/`hide_overlay`
+methods for handling these.
+
+### Custom widgets
+
+subiquity defines a few generic widgets that are used in several places.
+
+`Selector` is a bit like an html `