diff --git a/README.rst b/README.rst
--- a/README.rst
+++ b/README.rst
@@ -1,11 +1,16 @@
 Taskotron Job Trigger
 =====================
 
-This is very simple code that listens for fedmsg messages of specific types and
-triggers jobs in taskotron in buildbot as needed.
+Taskotron Trigger listens for fedmsg messages of specific types and triggers
+Taskotron jobs (currently using Buildbot) as needed.
 
 Project page: https://pagure.io/taskotron/taskotron-trigger
 
+Documentation
+-------------
+
+Look into ``docs/`` directory.
+
 Installation in Production
 --------------------------
 
diff --git a/docs/base-design.rst b/docs/base-design.rst
new file mode 100644
--- /dev/null
+++ b/docs/base-design.rst
@@ -0,0 +1,99 @@
+Taskotron-trigger base design
+=============================
+
+Trigger consists of a set of *Fedmsg consumers*, *Triggering engine*, and
+*Runners*.
+
+
+Fedmsg consumers
+----------------
+
+*Fedmsg consumers* are the "input source" for trigger - we listen on the fedmsg
+hub for a known set of message topics (compose completed, distgit commit, koji
+build, koji tag, pagure commit). When a message is received, the data is
+parsed, and additional information is/can be gathered from external sources
+(e.g. getting the list of critpath path packages in koji build trigger).
+
+Example data from the koji build trigger::
+
+  data = {
+    "_msg": {... the raw fedmsg },
+    "message_type": "KojiBuildPackageCompleted",
+    "item": "stage-4.1.1-3.fc18",
+    "item_type": "koji_build",
+    "name": "stage",
+    "version": "4.1.1.",
+    "release": "3.fc18",
+    "critpath_pkgs": [... list of critpath package names …],
+    "distgit_branch": "f18",
+  }
+
+
+Triggering engine
+-----------------
+
+The data from the consumer are passed into the *Triggering engine*, which takes
+a list of rules + the data on input, and returns a list of tasks that are
+supposed to be triggered based on that. Behind the curtains, the rules are
+mongo-db-style queries, that are executed over the consumer-provided data. If
+the query "passes", it means that the data match the rule, and the respective
+tasks are to be executed.
+
+Some example rules for the Trigger engine::
+
+  - when:
+      message_type: KojiBuildPackageCompleted
+    do:
+      - {tasks: [awesometask, cooltask]}
+
+  - when:
+      message_type: KojiBuildPackageCompleted
+      name: firefox
+    do:
+      - {tasks: [ff_testsuite]}
+
+  - when:
+      message_type: KojiBuildPackageCompleted
+      name:
+        $in: ${critpath_pkgs}
+    do:
+      - {tasks: [othertask]}
+
+  - when:
+      message_type: DistGitCommit
+    do:
+      - {discover: {repo: 'http://pkgs.fedoraproject.org/git/test-${namespace}/${repo}.git', branch: "${distgit_branch}"}}
+
+With these rules, and the data provided by the Fedmsg Consumer, ``awesometask``
+and ``cooltask`` would be executed, because the rules (``when`` section) match
+all the constraints (``message_type`` equals ``KojiBuildPackageCompleted``).
+
+The ``ff_testsuite`` is not ran, as the ``name`` field is different (``stage``
+does not equal ``firefox``).
+
+The next example shows "dynamic constraints" - the ``${critpath_pkgs}`` is
+populated with the value of the ``critpath_pkgs`` value passed in the data
+structure prior to the rules being tested. So the ``othertask`` is executed
+only if the package name is in the list of critpath packages.
+
+And in the last case, instead of having the task-name hardcoded, the trigger
+is able to search a git repo of given url (here it is inferred from the data)
+for ``runtask.yml`` (the Taskotron formula) files, and schedules those as jobs,
+using runners.
+
+
+Runners
+-------
+
+The last bit here are the *Runners* - at the moment we have *StreamRunner*
+(basically just an echo-runner that puts what it received on stdout and does
+nothing), and *BuildbotRunner*, which takes care of scheduling the runs in
+Buildbot.
+
+The runners, in general are the interface between the Trigger and the execution
+engine - be it Buildbot, Jenkins, Beaker, or any other thing you like. They are
+in charge of doing the right (e.g. RESTful) calls, and passing the right data,
+so the actual tasks can be executed.
+
+At the moment, we only allow for using one Runner for all the tasks, based on
+the general Trigger configuration.

