diff --git a/inst/bluebream.zcml b/inst/bluebream.zcml
new file mode 100644
index 0000000..c54c82c
--- /dev/null
+++ b/inst/bluebream.zcml
@@ -0,0 +1,62 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/inst/bluebream/.env b/inst/bluebream/.env
new file mode 100644
index 0000000..9defda0
--- /dev/null
+++ b/inst/bluebream/.env
@@ -0,0 +1,8 @@
+# loops/inst/bluebream/.env
+
+SERVER_PORT=8800
+
+DBNAME=ccotest
+DBUSER=ccotest
+DBPASSWORD=cco
+DBSCHEMA=testing
diff --git a/inst/bluebream/application.zcml b/inst/bluebream/application.zcml
new file mode 100644
index 0000000..c366a69
--- /dev/null
+++ b/inst/bluebream/application.zcml
@@ -0,0 +1,63 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/inst/bluebream/config.py b/inst/bluebream/config.py
new file mode 100644
index 0000000..163b2af
--- /dev/null
+++ b/inst/bluebream/config.py
@@ -0,0 +1,19 @@
+# loops/inst/bluebream/config.py
+
+from dotenv import load_dotenv
+from os import getenv
+from scopes.server.app import zope_app_factory
+
+load_dotenv()
+
+server_port = getenv('SERVER_PORT', '8099')
+
+app_factory = zope_app_factory
+
+# storage settings
+from scopes.storage.db.postgres import StorageFactory
+dbengine = 'postgresql+psycopg'
+dbname = getenv('DBNAME', 'demo')
+dbuser = getenv('DBUSER', 'demo')
+dbpassword = getenv('DBPASSWORD', 'secret')
+dbschema = getenv('DBSCHEMA', 'demo')
diff --git a/inst/bluebream/main.py b/inst/bluebream/main.py
new file mode 100644
index 0000000..7cd6ab5
--- /dev/null
+++ b/inst/bluebream/main.py
@@ -0,0 +1,20 @@
+# loops/inst/bluebream/main.py
+
+from wsgiref.simple_server import make_server
+
+def run(app, config):
+ port = int(config.server_port)
+ with make_server('', port, app) as httpd:
+ print(f'Serving on port {port}.')
+ try:
+ httpd.serve_forever()
+ except KeyboardInterrupt:
+ print('Shutting down.')
+
+
+if __name__ == '__main__':
+ import config
+ #run(config.app, config)
+ app = config.app_factory(config)
+ run(app, config)
+ # see zope.app.wsgi.getWSGIApplication
diff --git a/inst/bluebream/overrides.zcml b/inst/bluebream/overrides.zcml
new file mode 100644
index 0000000..e1d9b9c
--- /dev/null
+++ b/inst/bluebream/overrides.zcml
@@ -0,0 +1,48 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/inst/bluebream/securitypolicy.zcml b/inst/bluebream/securitypolicy.zcml
new file mode 100644
index 0000000..a27e369
--- /dev/null
+++ b/inst/bluebream/securitypolicy.zcml
@@ -0,0 +1,52 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/inst/bluebream/zope.conf b/inst/bluebream/zope.conf
new file mode 100644
index 0000000..ab4a5e2
--- /dev/null
+++ b/inst/bluebream/zope.conf
@@ -0,0 +1,39 @@
+# loops/inst/bluebream/zope.conf
+# main zope configuration file for deployment
+
+# Identify the component configuration used to define the site:
+site-definition application.zcml
+
+
+
+
+ path var/filestorage/Data.fs
+ blob-dir var/blob
+
+
+# Uncomment this if you want to connect to a ZEO server instead:
+#
+# server localhost:8100
+# storage 1
+# # ZEO client cache, in bytes
+# cache-size 20MB
+# # Uncomment to have a persistent disk cache
+# #client zeo1
+#
+
+
+
+ # This sets up logging to both a file and to standard output (STDOUT).
+ # The "path" setting can be a relative or absolute filesystem path or
+ # the tokens STDOUT or STDERR.
+
+
+ path var/log/z3-deploy.log
+ formatter zope.exceptions.log.Formatter
+
+
+
+ path STDOUT
+ formatter zope.exceptions.log.Formatter
+
+
diff --git a/inst/loops/application.zcml b/inst/loops/application.zcml
new file mode 100644
index 0000000..c366a69
--- /dev/null
+++ b/inst/loops/application.zcml
@@ -0,0 +1,63 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/inst/loops/overrides.zcml b/inst/loops/overrides.zcml
new file mode 100644
index 0000000..e1d9b9c
--- /dev/null
+++ b/inst/loops/overrides.zcml
@@ -0,0 +1,48 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/inst/loops/securitypolicy.zcml b/inst/loops/securitypolicy.zcml
new file mode 100644
index 0000000..a27e369
--- /dev/null
+++ b/inst/loops/securitypolicy.zcml
@@ -0,0 +1,52 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pyproject.toml b/pyproject.toml
index 16647ba..a3a6b20 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -31,6 +31,7 @@ dependencies = [
]
[project.optional-dependencies]
+server = ["waitress", "ZConfig", "zope.app.wsgi"]
test = ["zope.testrunner"]
[tool.setuptools]
diff --git a/runtests.sh b/runtests.sh
new file mode 100755
index 0000000..6e514f2
--- /dev/null
+++ b/runtests.sh
@@ -0,0 +1,5 @@
+# runtests.sh
+# run all unit / doc tests
+
+zope-testrunner --test-path=. $*
+