diff --git a/containers/MANIFEST.in b/containers/MANIFEST.in
new file mode 100644
index 0000000000..c922f11ad7
--- /dev/null
+++ b/containers/MANIFEST.in
@@ -0,0 +1 @@
+recursive-include public *
diff --git a/containers/api/__init__.py b/containers/api/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/containers/api/app.py b/containers/api/app.py
new file mode 100644
index 0000000000..1c61c1ee05
--- /dev/null
+++ b/containers/api/app.py
@@ -0,0 +1,14 @@
+from pecan import make_app
+from api import model
+
+
+def setup_app(config):
+
+ model.init_model()
+ app_conf = dict(config.app)
+
+ return make_app(
+ app_conf.pop('root'),
+ logging=getattr(config, 'logging', {}),
+ **app_conf
+ )
diff --git a/containers/api/controllers/__init__.py b/containers/api/controllers/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/containers/api/controllers/root.py b/containers/api/controllers/root.py
new file mode 100644
index 0000000000..bc1e72bdf3
--- /dev/null
+++ b/containers/api/controllers/root.py
@@ -0,0 +1,22 @@
+from pecan import expose, redirect
+from webob.exc import status_map
+
+
+class RootController(object):
+
+ @expose(generic=True, template='index.html')
+ def index(self):
+ return dict()
+
+ @index.when(method='POST')
+ def index_post(self, q):
+ redirect('http://pecan.readthedocs.org/en/latest/search.html?q=%s' % q)
+
+ @expose('error.html')
+ def error(self, status):
+ try:
+ status = int(status)
+ except ValueError: # pragma: no cover
+ status = 500
+ message = getattr(status_map.get(status), 'explanation', '')
+ return dict(status=status, message=message)
diff --git a/containers/api/model/__init__.py b/containers/api/model/__init__.py
new file mode 100644
index 0000000000..d983f7bc51
--- /dev/null
+++ b/containers/api/model/__init__.py
@@ -0,0 +1,15 @@
+from pecan import conf # noqa
+
+
+def init_model():
+ """
+ This is a stub method which is called at application startup time.
+
+ If you need to bind to a parsed database configuration, set up tables or
+ ORM classes, or perform any database initialization, this is the
+ recommended place to do it.
+
+ For more information working with databases, and some common recipes,
+ see http://pecan.readthedocs.org/en/latest/databases.html
+ """
+ pass
diff --git a/containers/api/templates/error.html b/containers/api/templates/error.html
new file mode 100644
index 0000000000..f2d9796143
--- /dev/null
+++ b/containers/api/templates/error.html
@@ -0,0 +1,12 @@
+<%inherit file="layout.html" />
+
+## provide definitions for blocks we want to redefine
+<%def name="title()">
+ Server Error ${status}
+%def>
+
+## now define the body of the template
+
+
Server Error ${status}
+
+
${message}
diff --git a/containers/api/templates/index.html b/containers/api/templates/index.html
new file mode 100644
index 0000000000..f17c3862ee
--- /dev/null
+++ b/containers/api/templates/index.html
@@ -0,0 +1,34 @@
+<%inherit file="layout.html" />
+
+## provide definitions for blocks we want to redefine
+<%def name="title()">
+ Welcome to Pecan!
+%def>
+
+## now define the body of the template
+
+
+
+
+
+
+
This is a sample Pecan project.
+
+
+ Instructions for getting started can be found online at pecanpy.org
+