diff --git a/.gitignore b/.gitignore
index f02594065d3a999ad2340e1c1216faf37710e9d2..d9a592e8541e1807eb6922a419f27257779afa0a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,4 @@
 *.swp
 *~
 *.pyc
+django-*.wsgi
diff --git a/django-dev.wsgi b/django-dev.wsgi
deleted file mode 100644
index 4b462e19b20bc13ccbf60f5e8bf7776313dc406a..0000000000000000000000000000000000000000
--- a/django-dev.wsgi
+++ /dev/null
@@ -1,15 +0,0 @@
-import os
-import sys
-
-# XXX The WSGI files should be unified.
-# Would be easy if settings.py were unified, which isn't hard.
-
-os.environ['DJANGO_SETTINGS_MODULE'] = 'gracedb.settings_dev'
-
-sys.path.append('/home/bmoe/sandbox/lib/python2.6/site-packages')
-sys.path.append('/home/bmoe/sandbox/lib/python2.6')
-
-import django.core.handlers.wsgi
-application = django.core.handlers.wsgi.WSGIHandler()
-
-
diff --git a/django.wsgi b/django.wsgi
index 0250c62da29defbb8854151399754bb4acd7a5f4..a5f9e18851a38315ad9e0f55ebffb2f5a6f1edb9 100644
--- a/django.wsgi
+++ b/django.wsgi
@@ -1,10 +1,14 @@
 import os
 import sys
 
-# XXX The WSGI files should be unified.
-# Would be easy if settings.py were unified, which isn't hard.
+os.environ['DJANGO_SETTINGS_MODULE'] = 'settings'
 
-os.environ['DJANGO_SETTINGS_MODULE'] = 'gracedb.settings'
+# Sandbox libs here, if required.
+#
+
+sys.path.append('/home/lars/wsgi-sandbox/lib/python2.6')
+sys.path.append('/home/lars/wsgi-sandbox/lib/python2.6/site-packages')
+sys.path.append('/home/gracedb/gracedb')
 
 import django.core.handlers.wsgi
 application = django.core.handlers.wsgi.WSGIHandler()
diff --git a/doc/CHANGES b/doc/CHANGES
index 411e9c8418f9dd90464eea8ca80452f5ecdc51c0..1f3eabb4df3d6a73ee013a8fba1d70d773b5ab9f 100644
--- a/doc/CHANGES
+++ b/doc/CHANGES
@@ -1,3 +1,17 @@
+==================================================================
+ER2
+
+    settings refactor
+        More unified settings/config.
+            settings/__init__.py
+                 locates and imports * from settings.default then settings.WHATEVER
+            settings/defaut.py
+                    /production.py
+                    /development.py
+                    /misc.py
+
+        Simple enough and gets rid of settings_dev crap.
+        Keeps prod/dev configs from diverging too much.
 
 ==================================================================
 Branch goocharts
diff --git a/gracedb/alert.py b/gracedb/alert.py
index 3399ed91266481586b87476cdbba17802dadb737..10dc7791fb6ced2a158913a27767deea394a7e17 100644
--- a/gracedb/alert.py
+++ b/gracedb/alert.py
@@ -9,7 +9,7 @@ from django.conf import settings
 from django.contrib.sites.models import Site
 from django.core.urlresolvers import reverse, get_script_prefix
 
-from gracedb.userprofile.models import Trigger, AnalysisType
+from userprofile.models import Trigger, AnalysisType
 
 import glue.ligolw.utils
 import glue.lvalert.utils
diff --git a/gracedb/buildVOEvent.py b/gracedb/buildVOEvent.py
index 5305db2fa4909c16e831dbb256575abfb81304df..e83a2145bcd304a8f6adb7f008e17c292bea0a64 100755
--- a/gracedb/buildVOEvent.py
+++ b/gracedb/buildVOEvent.py
@@ -8,11 +8,12 @@ See the VOEvent specification for details
 http://www.ivoa.net/Documents/latest/VOEvent.html
 """
 
-from gracedb.VOEventLib.VOEvent import *
-from gracedb.VOEventLib.Vutil import *
+from VOEventLib.VOEvent import *
+from VOEventLib.Vutil import *
 import sys, os
 
-from gracedb.utils import gpsToUtc
+# XXX ER2.utils.  utils is in project directory.  ugh.
+from utils import gpsToUtc
 from django.conf import settings
 
 def buildVOEvent(gevent):
diff --git a/ligolw/__init__.py b/gracedb/middleware/__init__.py
similarity index 100%
rename from ligolw/__init__.py
rename to gracedb/middleware/__init__.py
diff --git a/middleware/auth.py b/gracedb/middleware/auth.py
similarity index 99%
rename from middleware/auth.py
rename to gracedb/middleware/auth.py
index f9b0ef0ae8dafc12f3baff33907450612bb11d6a..e2d85da63db6ec3f760bb67dee7e003d08b4d727 100644
--- a/middleware/auth.py
+++ b/gracedb/middleware/auth.py
@@ -1,7 +1,7 @@
 
 from django.contrib.auth import authenticate
 
-from gracedb.gracedb.models import User
+from gracedb.models import User
 from django.contrib.auth.models import User as DjangoUser
 
 import re
diff --git a/gracedb/models.py b/gracedb/models.py
index 2d57f9ade38a414569931a71f2ea4dc9c78a7d39..49f793f99e3a716d1dbede2d97937ac76ee09231 100644
--- a/gracedb/models.py
+++ b/gracedb/models.py
@@ -5,8 +5,8 @@ import string
 import os
 
 
-from gracedb.ligolw.models import CoincEvent
-from gracedb.utils import posixToGpsTime
+# XXX ER2.utils.  utils is in project directory.  ugh.
+from utils import posixToGpsTime
 
 from django.conf import settings
 import pytz, time
@@ -60,12 +60,12 @@ class Event(models.Model):
     created = models.DateTimeField(auto_now_add=True)
     group = models.ForeignKey(Group)
     analysisType = models.CharField(max_length=20, choices=ANALYSIS_TYPE_CHOICES)
-    # From ligolw coinc_event table -- none are required.  yet.
+
+    # from coinc_event
     instruments = models.CharField(max_length=20, default="")
     nevents = models.PositiveIntegerField(null=True)
     far = models.FloatField(null=True)
     likelihood = models.FloatField(null=True)
-    coincEvent = models.ForeignKey(CoincEvent, null=True)
 
     # NOT from coinc_event, but so, so common.
     #   Note that the semantics for this is different depending
@@ -73,20 +73,13 @@ class Event(models.Model):
     #   be considered, umm, wrong?  But it is a starting point.
     gpstime = models.PositiveIntegerField(null=True)
 
-    # XXX Deprecated.  Only useful for old test data.
-    # Remove this when it won't freak people out to lose
-    # old date encoded uids.
-    uid = models.CharField(max_length=20, unique=False, default="")
-
     labels = models.ManyToManyField(Label, through="Labelling")
 
     class Meta:
         ordering = ["-id"]
 
     def graceid(self):
-        if self.uid:
-            return self.uid
-        elif self.group.name == "Test":
+        if self.group.name == "Test":
             return "T%04d" % self.id
         elif self.analysisType == "HWINJ":
             return "H%04d" % self.id
@@ -138,15 +131,14 @@ class Event(models.Model):
 
     @classmethod
     def getByGraceid(cls, id):
-        if id[0] not in "GHT":
-            # Very old, probably useless data.
-            return cls.objects.get(uid=id)
         e = cls.objects.get(id=int(id[1:]))
-        if (id[0] == "T") and (e.group.name != "Test"):
-            raise cls.DoesNotExist()
+        if (id[0] == "T") and (e.group.name == "Test"):
+            return e
         if (id[0] == "H") and (e.analysisType == "HWINJ"):
-            raise cls.DoesNotExist()
-        return e
+            return e
+        if (id[0] == "G"):
+            return e
+        raise cls.DoesNotExist()
 
     def __unicode__(self):
         return self.graceid()
diff --git a/gracedb/templatetags/timeutil.py b/gracedb/templatetags/timeutil.py
index a3d5da3d4a010d85dd4efc464dea288f9651c7e4..0938dc542ad1a3b3895b4ca60a22390c69fa816c 100644
--- a/gracedb/templatetags/timeutil.py
+++ b/gracedb/templatetags/timeutil.py
@@ -6,7 +6,8 @@ from django.utils import dateformat
 from django.utils.html import conditional_escape
 from django.utils.safestring import mark_safe
 
-from gracedb.utils import posixToGpsTime, gpsToUtc
+# XXX utils is in the project root.  this is not right. ER2.utils
+from utils import posixToGpsTime, gpsToUtc
 
 import pytz
 import time
diff --git a/gracedb/translator.py b/gracedb/translator.py
index ac94fd9975928c37dfc82da8e415c3d6dd82f356..a7bd55da576aead418395c35a627de016fc1fa39 100644
--- a/gracedb/translator.py
+++ b/gracedb/translator.py
@@ -18,35 +18,6 @@ from glue.gracedb.utils import populate_inspiral_tables, \
                                populate_coinc_tables,    \
                                write_output_files
 
-# Importing this messes with other ligolw table actions.
-#from gracedb.ligolw.insert import insert_ligolw_tables
-import gracedb.ligolw
-
-def insert_ligolw_tables(xml_filename):
-    #insert_ligolw_tables(django.db.connection, xml_filename)
-    prog = os.path.dirname(gracedb.ligolw.__file__)
-    prog = os.path.join(prog, "insert.py")
-    e = dict(os.environ)
-    ppath = e.get("PYTHONPATH") or ""
-    ppath = ppath.split(':')
-    ppath = ppath + sys.path
-    e['PYTHONPATH'] = ':'.join(ppath)
-    p = Popen( (prog,
-                 settings.DATABASE_USER,
-                 settings.DATABASE_PASSWORD,
-                 settings.DATABASE_NAME,
-                 xml_filename),
-               stdout=PIPE, stderr=PIPE, env=e)
-    out = p.stdout.read()
-    err = p.stderr.read()
-    p.wait()
-    out += p.stdout.read()
-    if out.find("OK") != 0:
-        coinc_id = None
-    else:
-        coinc_id = out[2:].strip()
-    return coinc_id
-
 def handle_uploaded_data(event, datafilename,
                          log_filename='event.log',
                          coinc_table_filename='coinc.xml'):
@@ -137,7 +108,6 @@ def handle_uploaded_data(event, datafilename,
         event.likelihood = coinc_table[0].likelihood
 
         xml_filename = os.path.join(output_dir, coinc_table_filename)
-        event.coincEvent_id = insert_ligolw_tables(xml_filename)
 
         event.save()
 
@@ -189,7 +159,6 @@ def handle_uploaded_data(event, datafilename,
         event.likelihood = coinc_table[0].likelihood
 
         xml_filename = os.path.join(output_dir, coinc_table_filename)
-        event.coincEvent_id = insert_ligolw_tables(xml_filename)
 
         event.save()
 
@@ -233,7 +202,6 @@ def handle_uploaded_data(event, datafilename,
         event.likelihood = coinc_table[0].likelihood
 
         xml_filename = os.path.join(output_dir, coinc_table_filename)
-        event.coincEvent_id = insert_ligolw_tables(xml_filename)
 
         event.save()
     elif event.analysisType == 'CWB':
@@ -294,9 +262,60 @@ def val_or_dashes(val):
     return val
 
 class Translator(object):
-    pass
+    event_type = "Undefined"  # override
+
+    def getData(self):
+        # override
+        raise(NotImplemented)
+
+    def castData(self, data):
+        # convert ints to ints
+        for key in ['gpstime', 'likelihood']:
+            if data[key]:
+                data[key] = int(float(data[key]))
+
+        # convert floats to floats
+        for key in ['far']:
+            if data[key]:
+                data[key] = float(data[key])
+
+    def populateEvent(self, event):
+        data = self.getData()
+
+        event.gpstime = data.get('gpstime')
+        event.likelihood = data.get('likelihood')
+        event.instruments = data.get('instruments')
+        event.far = data.get('far')
+
+        event.save()
+
+    def logData(self):
+        data = self.getData()
+        logdata = []
+        logdata.append("Event Type: %s", self.event_type)
+        logdata.append("Time: %s" % data.get('gpstime', '---'))
+        logdata.append("Duration: %s" % data['rawdata'].get('duration',["---"])[0])
+        logdata.append("Frequency: %s" % data['rawdata'].get('frequency',["---"])[0])
+        logdata.append("Bandwidth: %s" % data['rawdata'].get('bandwidth',["---"])[0])
+        logdata.append("RA: %s" % data['rawdata'].get('phi',[None,None,"---"])[2])
+        logdata.append("Dec: %s" % data['rawdata'].get('theta',[None,None,"---"])[2])
+        logdata.append("Effective SNR: %s" % data['rawdata'].get('rho',["---"])[0])
+        logdata.append("IFOs: %s" % val_or_dashes(data.get('instruments')))
+        logdata.append("FAR: %s" % val_or_dashes(data.get('far')))
+        return "\n".join(logdata)
+
+    def writeLogfile(self, path):
+        data = self.logData()
+        if data:
+            f = open(path, 'w')
+            f.write(data)
+            f.close()
+        return True
+
+
 
 class CwbData(Translator):
+    event_type = "cWB"
     CWB_IFO_MAP = {
         '1' : 'L1',
         '2' : 'H1',
@@ -307,19 +326,21 @@ class CwbData(Translator):
         '7' : 'A1',
     }
 
-    def __init__(self, datafile):
-        print "Got datafile", datafile
+    def __init__(self, datafile, *args, **kwargs):
         self.datafile = datafile
         self.data = None
 
     def getData(self):
         if not self.data:
-            self.data = self._readData(self.datafile)
+            data = self.readData(self.datafile)
+            self.castData(data)
         return self.data
 
-    def _readData(self, datafile):
+    def readData(self, datafile):
+        needToClose = False
         if isinstance(datafile, str) or isinstance(datafile, unicode):
             datafile = open(datafile, "r")
+            needToClose = True
 
         # cWB data look like
         #
@@ -348,55 +369,12 @@ class CwbData(Translator):
         ifos.sort()
         data['instruments'] = ','.join(ifos)
 
-        self._castData(data)
+        if needToClose:
+            datafile.close()
 
+        self.data = data
         return data
 
-    def _castData(self, data):
-        # convert ints to ints
-        for key in ['gpstime', 'likelihood']:
-            if data[key]:
-                data[key] = int(float(data[key]))
-
-        # convert floats to floats
-        for key in ['far']:
-            if data[key]:
-                data[key] = float(data[key])
-
-
-    def populateEvent(self, event):
-        data = self.getData()
-
-        event.gpstime = data.get('gpstime')
-        event.likelihood = data.get('likelihood')
-        event.instruments = data.get('instruments')
-        event.far = data.get('far')
-
-        event.save()
-
-    def logData(self):
-        data = self.getData()
-        logdata = []
-        logdata.append("Event Type: cWB")
-        logdata.append("Time: %s" % data.get('gpstime', '---'))
-        logdata.append("Duration: %s" % data['rawdata'].get('duration',["---"])[0])
-        logdata.append("Frequency: %s" % data['rawdata'].get('frequency',["---"])[0])
-        logdata.append("Bandwidth: %s" % data['rawdata'].get('bandwidth',["---"])[0])
-        logdata.append("RA: %s" % data['rawdata'].get('phi',[None,None,"---"])[2])
-        logdata.append("Dec: %s" % data['rawdata'].get('theta',[None,None,"---"])[2])
-        logdata.append("Effective SNR: %s" % data['rawdata'].get('rho',["---"])[0])
-        logdata.append("IFOs: %s" % val_or_dashes(data.get('instruments')))
-        logdata.append("FAR: %s" % val_or_dashes(data.get('far')))
-        return "\n".join(logdata)
-
     def writeCoincFile(self, path):
         pass
 
-    def writeLogfile(self, path):
-        data = self.logData()
-        if data:
-            f = open(path, 'w')
-            f.write(data)
-            f.close()
-        return True
-
diff --git a/gracedb/urls.py b/gracedb/urls.py
index 8344a9cf500574cd23b59d38793c4476ec8d20a2..7a2046701d5ad3322e183e7ddb93590143cd486f 100644
--- a/gracedb/urls.py
+++ b/gracedb/urls.py
@@ -3,7 +3,7 @@ from django.conf.urls.defaults import *
 
 #import django.views.generic.list_detail
 
-urlpatterns = patterns('gracedb.gracedb.views',
+urlpatterns = patterns('gracedb.views',
     url (r'^$', 'index', name="home"),
     url (r'^create/$', 'create', name="create"),
     url (r'^search/(?P<format>(json|flex))?$', 'search', name="search"),
diff --git a/gracedb/views.py b/gracedb/views.py
index 4aac4948e85312a7ea290c72a5afa3980393f862..9530093dd7a2de2b5cfc17f0ccadbec089d3ab8e 100644
--- a/gracedb/views.py
+++ b/gracedb/views.py
@@ -459,7 +459,7 @@ def log(request):
 
 def ping(request):
     #ack = "(%s) " % Site.objects.get_current()
-    ack = "(%s) " % request.META['SERVER_NAME']
+    ack = "(%s/%s) " % (request.META['SERVER_NAME'], settings.CONFIG_NAME)
     ack += request.POST.get('ack', None) or request.GET.get('ack','ACK')
 
     from templatetags.timeutil import utc
@@ -720,7 +720,7 @@ def oldsearch(request):
             context_instance=RequestContext(request))
 
 def timeline(request):
-    from gracedb.utils import gpsToUtc
+    from utils import gpsToUtc
     from django.utils import dateformat
 
     response = HttpResponse(mimetype='application/javascript')
diff --git a/ligolw/insert.py b/ligolw/insert.py
deleted file mode 100755
index d065d7fe0ed6a7ebc3b769ff87ce02a8ee2e7e97..0000000000000000000000000000000000000000
--- a/ligolw/insert.py
+++ /dev/null
@@ -1,140 +0,0 @@
-#!/usr/bin/env python
-
-#
-# preamble
-#
-
-import sys, os
-
-import StringIO
-
-import MySQLdb
-from MySQLdb import OperationalError
-
-import glue
-from glue.ligolw import ligolw
-from glue.ligolw import lsctables
-# FIXME:  remove the next line when this attribute is initialized properly
-# in lsctables.py
-lsctables.SnglInspiralTable.next_id = lsctables.SnglInspiralID(0)
-# FIXME:  remove the next line when SnglInspiralTable no longer has its own
-# custom version of this method
-lsctables.SnglInspiralTable.updateKeyMapping = lsctables.table.Table.updateKeyMapping
-from glue.ligolw import utils
-from glue.ligolw.utils.ligolw_add import reassign_ids as ligolw_reassign_ids
-# while importing dbtables, need before and after copies of the
-# LIGOLWContentHandler class
-class LIGOLWRAMContentHandler(ligolw.LIGOLWContentHandler):
-    startTable = ligolw.LIGOLWContentHandler.startTable
-    endTable = ligolw.LIGOLWContentHandler.endTable
-from glue.ligolw import dbtables
-class LIGOLWDBContentHandler(ligolw.LIGOLWContentHandler):
-    startTable = ligolw.LIGOLWContentHandler.startTable
-    endTable = ligolw.LIGOLWContentHandler.endTable
-
-dbtables.DBTable.maxrowid = lambda self: None
-
-#
-# initialize the next_id attributes of all the table classes
-#
-
-#------------------------------------------------------------------
-
-#from insert_nextid import next_id
-# included below.
-
-import MySQLdb
-from MySQLdb.constants import ER
-
-TABLE_NAME = "ligolwids"
-
-create_table_sql = "CREATE TABLE %s (tablename VARCHAR(30) PRIMARY KEY, nextid INTEGER)" % TABLE_NAME
-select_id_sql = "SELECT nextid FROM %s WHERE tablename = %%s" % TABLE_NAME
-insert_new_sql = "INSERT INTO %s (tablename, nextid) VALUES (%%s, 0)" % TABLE_NAME
-update_sql = "UPDATE %s SET nextid = nextid+1 WHERE tablename = %%s" % TABLE_NAME
-lock_sql = "LOCK TABLE %s WRITE" % TABLE_NAME
-unlock_sql = "UNLOCK TABLES"
-
-def create_id_table(connection):
-    connection.cursor().execute(create_table_sql)
-
-def db_get_next_id(connection, table_name, create_table=True, create_row=True):
-    cursor = connection.cursor()
-    try:
-        try:
-            cursor.execute(lock_sql)
-            cursor.execute(select_id_sql, [table_name])
-            next = cursor.fetchone()
-            if next is None:
-                cursor.execute(insert_new_sql, [table_name])
-                cursor.execute(select_id_sql, [table_name])
-                next = cursor.fetchone()
-            cursor.execute(update_sql, [table_name])
-        finally:
-            cursor.execute(unlock_sql)
-            cursor.close()
-    except MySQLdb.ProgrammingError, e:
-        if e.args[0] != ER.NO_SUCH_TABLE or not create_table:
-            raise
-        create_id_table(connection)
-        return db_get_next_id(connection, table_name, create_table=False)
-    return int(next[0])
-
-
-#------------------------------------------------------------------
-
-def initialize(connection):
-    for cls in lsctables.TableByName.values():
-        if cls.next_id is not None:
-            cls.get_next_id = lambda self: type(self.next_id)(db_get_next_id(connection, self.next_id.table_name))
-            classmethod(cls.get_next_id)
-
-def insert_ligolw_tables(connection, filename, verbose=False):
-
-    initialize(connection)
-    #
-    # parse .xml file into memory, reassign ids, write xml stream to in-ram
-    # buffer
-    #
-    xmldoc = ligolw_reassign_ids(
-        utils.load_filename(
-            filename,
-            gz = (filename or "stdin").endswith(".gz"),
-            verbose = verbose,
-            contenthandler = LIGOLWRAMContentHandler
-        ),
-        verbose = verbose
-    )
-
-    # <-- find coinc_event_id
-    coinc_table = glue.ligolw.table.get_table(
-            xmldoc,
-            glue.ligolw.lsctables.CoincTable.tableName)
-    coinc_id = coinc_table[0].coinc_event_id
-
-
-    buf = StringIO.StringIO()
-    utils.write_fileobj(xmldoc, buf)
-    buf.seek(0)
-    #
-    # re-parse xml stream from in-ram buffer to sqlite database
-    #
-    dbtables.DBTable_set_connection(connection)
-    xmldoc, digest = utils.load_fileobj(buf, contenthandler = LIGOLWDBContentHandler)
-    xmldoc.unlink()
-    dbtables.DBTable_set_connection(None)
-
-    return coinc_id
-
-if __name__ == "__main__":
-    import sys
-
-    user = sys.argv[1]
-    password = sys.argv[2]
-    db = sys.argv[3]
-    filename = sys.argv[4]
-
-    conn= MySQLdb.connect(user=user, passwd=password, db=db)
-
-    rv = insert_ligolw_tables(conn, filename)
-    print "OK", rv
diff --git a/ligolw/insert_nextid.py b/ligolw/insert_nextid.py
deleted file mode 100644
index 9e6d78965bc9ecce139c7b59c43e9c3c5ebaf19a..0000000000000000000000000000000000000000
--- a/ligolw/insert_nextid.py
+++ /dev/null
@@ -1,48 +0,0 @@
-import MySQLdb
-from MySQLdb.constants import ER
-
-conn = MySQLdb.connect(db='ligolw', user='root')
-
-TABLE_NAME = "ligolwids"
-
-create_table_sql = "CREATE TABLE %s (tablename VARCHAR(30) PRIMARY KEY, nextid INTEGER)" % TABLE_NAME
-select_id_sql = "SELECT nextid FROM %s WHERE tablename = %%s" % TABLE_NAME
-insert_new_sql = "INSERT INTO %s (tablename, nextid) VALUES (%%s, 0)" % TABLE_NAME
-update_sql = "UPDATE %s SET nextid = nextid+1 WHERE tablename = %%s" % TABLE_NAME
-lock_sql = "LOCK TABLE %s WRITE" % TABLE_NAME
-unlock_sql = "UNLOCK TABLES"
-
-def create_id_table(connection):
-    connection.cursor().execute(create_table_sql)
-
-def next_id(connection, table_name, create_table=True, create_row=True):
-    next = None
-    cursor = connection.cursor()
-    try:
-        try:
-            cursor.execute(lock_sql)
-            cursor.execute(select_id_sql, [table_name])
-            next = cursor.fetchone()
-            if not next:
-                cursor.execute(insert_new_sql, [table_name])
-                cursor.execute(select_id_sql, [table_name])
-                next = cursor.fetchone()
-            cursor.execute(update_sql, [table_name])
-        finally:
-            cursor.execute(unlock_sql)
-            cursor.close()
-    except MySQLdb.ProgrammingError, e:
-        # XXX remove
-        global foo
-        foo = e
-        cursor.close()
-        if e.args[0] == ER.NO_SUCH_TABLE:
-            if not create_table:
-                raise
-            create_id_table(connection)
-            return next_id(connection, table_name, create_table=False)
-        else:
-            raise
-    cursor.close()
-    return next[0]
-
diff --git a/ligolw/models.py b/ligolw/models.py
deleted file mode 100644
index 1b36b986bf4008365b88d5c06552bc2307260f4b..0000000000000000000000000000000000000000
--- a/ligolw/models.py
+++ /dev/null
@@ -1,228 +0,0 @@
-
-# This is an auto-generated Django model module.
-# You'll have to do the following manually to clean this up:
-#     * Rearrange models' order
-#     * Make sure each model has one field with primary_key=True
-# Feel free to rename the models, but don't rename db_table values or field names.
-#
-# Also note:
-#   You'll have to insert the output of 'django-admin.py sqlcustom [appname]'
-#   into your database.
-
-from django.db import models
-
-class CoincDefiner(models.Model):
-    search = models.CharField(max_length=150, blank=True)
-    description = models.CharField(max_length=150, blank=True)
-    coinc_def_id = models.CharField(max_length=150, primary_key=True)
-    search_coinc_type = models.IntegerField(null=True, blank=True)
-    class Meta:
-        db_table = u'coinc_definer'
-
-class TimeSlide(models.Model):
-    instrument = models.CharField(max_length=150, primary_key=True)
-    time_slide_id = models.CharField(max_length=150, primary_key=True)
-    process_id = models.CharField(max_length=150, blank=True)
-    offset = models.FloatField(null=True, blank=True)
-    class Meta:
-        db_table = u'time_slide'
-
-class Process(models.Model):
-    program = models.CharField(max_length=150, blank=True)
-    version = models.CharField(max_length=150, blank=True)
-    cvs_repository = models.CharField(max_length=150, blank=True)
-    cvs_entry_time = models.IntegerField(null=True, blank=True)
-    comment = models.CharField(max_length=150, blank=True)
-    is_online = models.IntegerField(null=True, blank=True)
-    node = models.CharField(max_length=150, blank=True)
-    username = models.CharField(max_length=150, blank=True)
-    unix_procid = models.IntegerField(null=True, blank=True)
-    start_time = models.IntegerField(null=True, blank=True)
-    end_time = models.IntegerField(null=True, blank=True)
-    jobid = models.IntegerField(null=True, blank=True)
-    domain = models.CharField(max_length=150, blank=True)
-    ifos = models.CharField(max_length=150, blank=True)
-    process_id = models.CharField(max_length=150, primary_key=True)
-    class Meta:
-        db_table = u'process'
-
-
-class CoincEvent(models.Model):
-    coinc_event_id = models.CharField(max_length=150, primary_key=True)
-    instruments = models.CharField(max_length=150, blank=True)
-    nevents = models.IntegerField(null=True, blank=True)
-    #process_id = models.CharField(max_length=150, blank=True)
-    process =  models.ForeignKey(Process, blank=True)
-    #coinc_def_id = models.CharField(max_length=150, blank=True)
-    coinc_def = models.ForeignKey(CoincDefiner, blank=True)
-    #time_slide_id = models.CharField(max_length=150, blank=True)
-    time_slide = models.ForeignKey(TimeSlide, blank=True)
-    likelihood = models.FloatField(null=True, blank=True)
-    class Meta:
-        db_table = u'coinc_event'
-
-class CoincEventMap(models.Model):
-    event_id = models.CharField(max_length=150, blank=True)
-    table_name = models.CharField(max_length=150, blank=True)
-    coinc_event_id = models.CharField(max_length=150, blank=True)
-    class Meta:
-        db_table = u'coinc_event_map'
-
-class CoincInspiral(models.Model):
-    false_alarm_rate = models.FloatField(null=True, blank=True)
-    mchirp = models.FloatField(null=True, blank=True)
-    #coinc_event_id = models.CharField(max_length=150, blank=True)
-    coinc_event = models.OneToOneField(CoincEvent, primary_key=True)
-    combined_far = models.FloatField(null=True, blank=True)
-    mass = models.FloatField(null=True, blank=True)
-    end_time = models.IntegerField(null=True, blank=True)
-    snr = models.FloatField(null=True, blank=True)
-    end_time_ns = models.IntegerField(null=True, blank=True)
-    ifos = models.CharField(max_length=150, blank=True)
-    class Meta:
-        db_table = u'coinc_inspiral'
-
-
-class Experiment(models.Model):
-    search = models.CharField(max_length=150, blank=True)
-    instruments = models.CharField(max_length=150, blank=True)
-    search_group = models.CharField(max_length=150, blank=True)
-    comments = models.CharField(max_length=150, blank=True)
-    lars_id = models.CharField(max_length=150, blank=True)
-    experiment_id = models.CharField(max_length=150, primary_key=True)
-    gps_start_time = models.IntegerField(null=True, blank=True)
-    gps_end_time = models.IntegerField(null=True, blank=True)
-    class Meta:
-        db_table = u'experiment'
-
-class ExperimentMap(models.Model):
-    experiment_summ_id = models.CharField(max_length=150, blank=True)
-    #coinc_event_id = models.CharField(max_length=150, blank=True)
-    coinc_event = models.ForeignKey(CoincEvent, blank=True)
-    class Meta:
-        db_table = u'experiment_map'
-
-class ExperimentSummary(models.Model):
-    sim_proc_id = models.CharField(max_length=150, blank=True)
-    datatype = models.CharField(max_length=150, blank=True)
-    experiment_summ_id = models.CharField(max_length=150, primary_key=True)
-    nevents = models.IntegerField(null=True, blank=True)
-    #experiment_id = models.CharField(max_length=150, blank=True)
-    experiment = models.ForeignKey(Experiment, blank=True)
-    duration = models.IntegerField(null=True, blank=True)
-    #time_slide_id = models.CharField(max_length=150, blank=True)
-    time_slide = models.ForeignKey(TimeSlide, blank=True)
-    veto_def_name = models.CharField(max_length=150, blank=True)
-    rowid = models.IntegerField(unique=True, db_column='ROWID') # Field name made lowercase.
-    class Meta:
-        db_table = u'experiment_summary'
-
-class Ligolwids(models.Model):
-    tablename = models.CharField(max_length=90, primary_key=True)
-    nextid = models.IntegerField(null=True, blank=True)
-    class Meta:
-        db_table = u'ligolwids'
-
-class ProcessParams(models.Model):
-    program = models.CharField(max_length=150, blank=True)
-    #process_id = models.CharField(max_length=150, blank=True)
-    process = models.ForeignKey(Process, blank=True)
-    param = models.CharField(max_length=150, blank=True)
-    type = models.CharField(max_length=150, blank=True)
-    value = models.CharField(max_length=150, blank=True)
-    class Meta:
-        db_table = u'process_params'
-
-class SearchSummary(models.Model):
-    #process_id = models.CharField(max_length=150, blank=True)
-    process = models.ForeignKey(Process, blank=True)
-    shared_object = models.CharField(max_length=150, blank=True)
-    lalwrapper_cvs_tag = models.CharField(max_length=150, blank=True)
-    lal_cvs_tag = models.CharField(max_length=150, blank=True)
-    comment = models.CharField(max_length=150, blank=True)
-    ifos = models.CharField(max_length=150, blank=True)
-    in_start_time = models.IntegerField(null=True, blank=True)
-    in_start_time_ns = models.IntegerField(null=True, blank=True)
-    in_end_time = models.IntegerField(null=True, blank=True)
-    in_end_time_ns = models.IntegerField(null=True, blank=True)
-    out_start_time = models.IntegerField(null=True, blank=True)
-    out_start_time_ns = models.IntegerField(null=True, blank=True)
-    out_end_time = models.IntegerField(null=True, blank=True)
-    out_end_time_ns = models.IntegerField(null=True, blank=True)
-    nevents = models.IntegerField(null=True, blank=True)
-    nnodes = models.IntegerField(null=True, blank=True)
-    class Meta:
-        db_table = u'search_summary'
-
-class SearchSummvars(models.Model):
-    #process_id = models.CharField(max_length=150, blank=True)
-    process = models.ForeignKey(Process, blank=True)
-    name = models.CharField(max_length=150, blank=True)
-    string = models.CharField(max_length=150, blank=True)
-    value = models.FloatField(null=True, blank=True)
-    search_summvar_id = models.CharField(max_length=150, primary_key=True)
-    class Meta:
-        db_table = u'search_summvars'
-
-class SnglInspiral(models.Model):
-    process_id = models.CharField(max_length=150, blank=True)
-    ifo = models.CharField(max_length=150, blank=True)
-    search = models.CharField(max_length=150, blank=True)
-    channel = models.CharField(max_length=150, blank=True)
-    end_time = models.IntegerField(null=True, blank=True)
-    end_time_ns = models.IntegerField(null=True, blank=True)
-    end_time_gmst = models.FloatField(null=True, blank=True)
-    impulse_time = models.IntegerField(null=True, blank=True)
-    impulse_time_ns = models.IntegerField(null=True, blank=True)
-    template_duration = models.FloatField(null=True, blank=True)
-    event_duration = models.FloatField(null=True, blank=True)
-    amplitude = models.FloatField(null=True, blank=True)
-    eff_distance = models.FloatField(null=True, blank=True)
-    coa_phase = models.FloatField(null=True, blank=True)
-    mass1 = models.FloatField(null=True, blank=True)
-    mass2 = models.FloatField(null=True, blank=True)
-    mchirp = models.FloatField(null=True, blank=True)
-    mtotal = models.FloatField(null=True, blank=True)
-    eta = models.FloatField(null=True, blank=True)
-    kappa = models.FloatField(null=True, blank=True)
-    chi = models.FloatField(null=True, blank=True)
-    tau0 = models.FloatField(null=True, blank=True)
-    tau2 = models.FloatField(null=True, blank=True)
-    tau3 = models.FloatField(null=True, blank=True)
-    tau4 = models.FloatField(null=True, blank=True)
-    tau5 = models.FloatField(null=True, blank=True)
-    ttotal = models.FloatField(null=True, blank=True)
-    psi0 = models.FloatField(null=True, blank=True)
-    psi3 = models.FloatField(null=True, blank=True)
-    alpha = models.FloatField(null=True, blank=True)
-    alpha1 = models.FloatField(null=True, blank=True)
-    alpha2 = models.FloatField(null=True, blank=True)
-    alpha3 = models.FloatField(null=True, blank=True)
-    alpha4 = models.FloatField(null=True, blank=True)
-    alpha5 = models.FloatField(null=True, blank=True)
-    alpha6 = models.FloatField(null=True, blank=True)
-    beta = models.FloatField(null=True, blank=True)
-    f_final = models.FloatField(null=True, blank=True)
-    snr = models.FloatField(null=True, blank=True)
-    chisq = models.FloatField(null=True, blank=True)
-    chisq_dof = models.IntegerField(null=True, blank=True)
-    bank_chisq = models.FloatField(null=True, blank=True)
-    bank_chisq_dof = models.IntegerField(null=True, blank=True)
-    cont_chisq = models.FloatField(null=True, blank=True)
-    cont_chisq_dof = models.IntegerField(null=True, blank=True)
-    sigmasq = models.FloatField(null=True, blank=True)
-    rsqveto_duration = models.FloatField(null=True, blank=True)
-    gamma0 = models.FloatField(null=True, db_column='Gamma0', blank=True) # Field name made lowercase.
-    gamma1 = models.FloatField(null=True, db_column='Gamma1', blank=True) # Field name made lowercase.
-    gamma2 = models.FloatField(null=True, db_column='Gamma2', blank=True) # Field name made lowercase.
-    gamma3 = models.FloatField(null=True, db_column='Gamma3', blank=True) # Field name made lowercase.
-    gamma4 = models.FloatField(null=True, db_column='Gamma4', blank=True) # Field name made lowercase.
-    gamma5 = models.FloatField(null=True, db_column='Gamma5', blank=True) # Field name made lowercase.
-    gamma6 = models.FloatField(null=True, db_column='Gamma6', blank=True) # Field name made lowercase.
-    gamma7 = models.FloatField(null=True, db_column='Gamma7', blank=True) # Field name made lowercase.
-    gamma8 = models.FloatField(null=True, db_column='Gamma8', blank=True) # Field name made lowercase.
-    gamma9 = models.FloatField(null=True, db_column='Gamma9', blank=True) # Field name made lowercase.
-    event_id = models.CharField(max_length=150, primary_key=True)
-    class Meta:
-        db_table = u'sngl_inspiral'
-
diff --git a/manage.py b/manage.py
index b6f360910e283c1fd569f0703857fba8b22f6b60..aac8ce41ae98f7da6909119e6499ac247408d994 100755
--- a/manage.py
+++ b/manage.py
@@ -1,12 +1,6 @@
 #!/usr/bin/env python
 from django.core.management import execute_manager
 
-# THIS IS TERRIBLE, but some idiot named the project AND application gracedb.
-# Things looking for gracedb.settings fail because they find the app not the proj.
-# This also causes things wanting the app having to do gracedb.gracedb.whatever
-# all the time, but that mess has already been made.
-import sys, os
-sys.path.insert(0, os.path.join(os.path.dirname(__file__),'..'))
 
 try:
     import settings # Assumed to be in the same directory.
diff --git a/manage_dev.py b/manage_dev.py
deleted file mode 100755
index e935d64855141dfe4a368e0a2a1adaadd3a56c46..0000000000000000000000000000000000000000
--- a/manage_dev.py
+++ /dev/null
@@ -1,19 +0,0 @@
-#!/usr/bin/env python
-from django.core.management import execute_manager
-
-# THIS IS TERRIBLE, but some idiot named the project AND application gracedb.
-# Things looking for gracedb.settings fail because they find the app not the proj.
-# This also causes things wanting the app having to do gracedb.gracedb.whatever
-# all the time, but that mess has already been made.
-import sys, os
-sys.path.insert(0, os.path.join(os.path.dirname(__file__),'..'))
-
-try:
-    import settings_dev as settings # Assumed to be in the same directory.
-except ImportError:
-    import sys
-    sys.stderr.write("Error: Can't find the file 'settings.py' in the directory containing %r. It appears you've customized things.\nYou'll have to run django-admin.py, passing it your settings module.\n(If the file settings.py does indeed exist, it's causing an ImportError somehow.)\n" % __file__)
-    sys.exit(1)
-
-if __name__ == "__main__":
-    execute_manager(settings)
diff --git a/middleware/debug.py b/middleware/debug.py
new file mode 100644
index 0000000000000000000000000000000000000000..b1379cc8aa4cee10481575986764a81b995a26ea
--- /dev/null
+++ b/middleware/debug.py
@@ -0,0 +1,7 @@
+
+from django.conf import settings
+
+def LigoDebugContext(request):
+    if settings.DEBUG and settings.DEBUG != "PRODUCTION":
+        return { 'config_name' : settings.CONFIG_NAME }
+    return {}
diff --git a/settings/__init__.py b/settings/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..b5a9d97d9e449f34bf84a569a02b205b428017e8
--- /dev/null
+++ b/settings/__init__.py
@@ -0,0 +1,39 @@
+
+# Django settings for gracedb project.
+
+try:
+    # Workaround for a bug
+    # http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=473584
+    # http://bugs.python.org/setuptools/issue36
+    # import MySQLdb followed by import pkg_resources complains
+    #   /usr/lib/python2.6/dist-packages/pytz/__init__.py:32: UserWarning: Module _mysql was already imported from /usr/lib/pymodules/python2.6/_mysql.so, but /usr/lib/pymodules/python2.6 is being added to sys.path
+    import pkg_resources
+except:
+    pass
+
+import os
+ROOT_PATH = os.path.abspath( os.path.join( os.path.dirname(__file__), os.pardir ) )
+
+configs = {
+    '/home/bmoe/ER2': 'development_er2',
+    '/home/bmoe/er2box/lib/python2.6/site-packages/gracedb' : 'development_er2',
+
+    '/home/bmoe/er2box/lib/python2.6/site-packages/ER2' : 'development_er2',
+
+    '/home/bmoe/gracedb': 'development',
+    '/home/gracedb/gracedb': 'production',
+}
+
+
+from default import *
+
+config = configs.get(ROOT_PATH, "NO_CONFIG")
+
+settings_module = __import__('%s' % config, globals(), locals(), 'gracedb')
+
+# Load the config settings properties into the local scope.
+for setting in dir(settings_module):
+    if setting == setting.upper():
+        locals()[setting] = getattr(settings_module, setting)
+
+
diff --git a/settings.py b/settings/default.py
similarity index 70%
rename from settings.py
rename to settings/default.py
index 13ca03bc0d77ea36f99eb21cc3c0fede4552f70c..1fb9c0f39314a9657c86ca709ed6ffef56d72457 100644
--- a/settings.py
+++ b/settings/default.py
@@ -1,15 +1,5 @@
-# Django settings for gracedb project.
-import os
-
-try:
-    # Workaround for a bug
-    # http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=473584
-    # http://bugs.python.org/setuptools/issue36
-    # import MySQLdb followed by import pkg_resources complains
-    #   /usr/lib/python2.6/dist-packages/pytz/__init__.py:32: UserWarning: Module _mysql was already imported from /usr/lib/pymodules/python2.6/_mysql.so, but /usr/lib/pymodules/python2.6 is being added to sys.path
-    import pkg_resources
-except:
-    pass
+
+# Suitable for production
 
 DEBUG = False
 TEMPLATE_DEBUG = DEBUG
@@ -18,7 +8,6 @@ EMAIL_HOST = 'gravity.phys.uwm.edu'
 
 ADMINS = (
     ('Brian Moe', 'bmoe@gravity.phys.uwm.edu'),
-#   ('Larry Price', 'larry@gravity.phys.uwm.edu'),
 )
 
 MANAGERS = ADMINS
@@ -28,14 +17,10 @@ ALERT_EMAIL_TO = [
                   "gracedb@listserv.ligo.org",
                  ]
 ALERT_EMAIL_BCC = [
-#                 "Frederique Marion <marionf@lapp.in2p3.fr>",
-#                 "Benoit MOURS <mours@lapp.in2p3.fr>",
-#                 "Jonah Kanner <jkanner@umd.edu>",
                   ]
 
 ALERT_TEST_EMAIL_FROM = "GraCEDb TEST <gracedb@ligo.org>"
 ALERT_TEST_EMAIL_TO = [
-#                      "bmoe@gravity.phys.uwm.edu",
                       ]
 
 XMPP_ALERT_CHANNELS = [
@@ -76,34 +61,36 @@ LATENCY_MAXIMUM_CHARTED = 1800
 LATENCY_REPORT_WEB_PAGE_FILE_PATH = LATENCY_REPORT_DEST_DIR + "/latency.inc"
 
 
-# CBC IFAR Reports
-
-from utils import posixToGpsTime
-from datetime import datetime, timedelta
-import time
-
-now = datetime.now()
-yesterday = now - timedelta(days=1)
-lastweek = now - timedelta(days=7)
-now = posixToGpsTime(time.mktime(now.timetuple()))
-yesterday = posixToGpsTime(time.mktime(yesterday.timetuple()))
-lastweek = posixToGpsTime(time.mktime(lastweek.timetuple()))
-
-REPORT_IFAR_IMAGE_DIR = LATENCY_REPORT_DEST_DIR
-REPORTS_IFAR = [
-    #(query, axis_label, title, fname)
-    ("LowMass %d..%d" % (yesterday, now),
-     "GraceDB CBC LowMass ER1 events",
-     "ER1 FARs from gstlal_ll_inspiral - last day",
-     "ifar_day.png"
-    ),
-    ("LowMass %d..%d" % (lastweek, now),
-     "GraceDB CBC LowMass ER1 events",
-     "ER1 FARs from gstlal_ll_inspiral - last week",
-     "ifar_week.png"
-    ),
-]
 
+# Find another way to do this.
+#
+## CBC IFAR Reports
+#
+#from gracedb.utils import posixToGpsTime
+#from datetime import datetime, timedelta
+#import time
+#
+#now = datetime.now()
+#yesterday = now - timedelta(days=1)
+#lastweek = now - timedelta(days=7)
+#now = posixToGpsTime(time.mktime(now.timetuple()))
+#yesterday = posixToGpsTime(time.mktime(yesterday.timetuple()))
+#lastweek = posixToGpsTime(time.mktime(lastweek.timetuple()))
+#
+#REPORT_IFAR_IMAGE_DIR = LATENCY_REPORT_DEST_DIR
+#REPORTS_IFAR = [
+#    #(query, axis_label, title, fname),
+#    ("LowMass %d..%d" % (yesterday, now),
+#     "GraceDB CBC LowMass ER1 events",
+#     "ER1 FARs from gstlal_ll_inspiral - last day",
+#     "ifar_day.png"
+#    ),
+#    ("LowMass %d..%d" % (lastweek, now),
+#     "GraceDB CBC LowMass ER1 events",
+#     "ER1 FARs from gstlal_ll_inspiral - last week",
+#     "ifar_week.png"
+#    ),
+#]
 
 
 # RSS Feed Defaults
@@ -122,11 +109,11 @@ GRACE_DATETIME_FORMAT = 'Y-m-d H:i:s T'
 # http://www.i18nguy.com/unicode/language-identifiers.html
 LANGUAGE_CODE = 'en-us'
 
-SITE_ID = 3
+SITE_ID = 1
 
 # If you set this to False, Django will make some optimizations so as not
 # to load the internationalization machinery.
-USE_I18N = True
+USE_I18N = False
 
 # Absolute path to the directory that holds media.
 # Example: "/home/media/media.lawrence.com/"
@@ -163,20 +150,21 @@ TEMPLATE_CONTEXT_PROCESSORS = (
     "django.core.context_processors.media",
     "django.core.context_processors.request",
     "gracedb.middleware.auth.LigoAuthContext",
+    'middleware.debug.LigoDebugContext',
 )
 
 AUTHENTICATION_BACKENDS = ('gracedb.middleware.auth.LigoAuthBackend',)
 
-MIDDLEWARE_CLASSES = (
-    'gracedb.middleware.accept.AcceptMiddleware',
+MIDDLEWARE_CLASSES = [
+    'middleware.accept.AcceptMiddleware',
     'gracedb.middleware.auth.LigoAuthMiddleware',
-    'gracedb.middleware.cli.CliExceptionMiddleware',
+    'middleware.cli.CliExceptionMiddleware',
     'django.middleware.common.CommonMiddleware',
     'django.contrib.sessions.middleware.SessionMiddleware',
     'django.contrib.auth.middleware.AuthenticationMiddleware',
-)
+]
 
-ROOT_URLCONF = 'gracedb.urls'
+ROOT_URLCONF = 'urls'
 
 TEMPLATE_DIRS = (
     # Put strings here, like "/home/html/django_templates" or "C:/www/django/templates".
@@ -191,6 +179,6 @@ INSTALLED_APPS = (
     'django.contrib.contenttypes',
     'django.contrib.sessions',
     'django.contrib.sites',
-    'gracedb.gracedb',
-    'gracedb.userprofile',
+    'gracedb',
+    'userprofile',
 )
diff --git a/settings/development.py b/settings/development.py
new file mode 100644
index 0000000000000000000000000000000000000000..cdcd076049b4319a8914899c033b8d6b9c488d94
--- /dev/null
+++ b/settings/development.py
@@ -0,0 +1,40 @@
+
+CONFIG_NAME = "DEVELOPMENT"
+
+DEBUG = True
+TEMPLATE_DEBUG = DEBUG
+
+
+ALERT_EMAIL_FROM = "Dev Alert <root@moe.phys.uwm.edu>"
+ALERT_EMAIL_TO = [
+    "Brian Moe <bmoe@gravity.phys.uwm.edu>",
+    ]
+ALERT_EMAIL_BCC = ["bmoe@uwm.edu"]
+
+ALERT_TEST_EMAIL_FROM = "Dev Test Alert <root@moe.phys.uwm.edu>"
+ALERT_TEST_EMAIL_TO = [
+    "Brian Moe <bmoe@gravity.phys.uwm.edu>",
+    ]
+
+# Don't sent out non-test XMPP alerts on dev box!
+XMPP_ALERT_CHANNELS = [
+                        'test_omega',
+                        'test_mbtaonline',
+                        'test_cwb',
+                        'test_lowmass',
+                      ]
+ 
+# SkyAlert
+SKYALERT_IVORN_PATTERN = "ivo://ligo.org/gracedb#%s-dev"
+
+# Latency histograms.  Where they go and max latency to bin.
+LATENCY_REPORT_DEST_DIR = "/home/bmoe/data/latency"
+
+SITE_ID = 4
+
+TEMPLATE_DIRS = (
+    # Put strings here, like "/home/html/django_templates" or "C:/www/django/templates".
+    # Always use forward slashes, even on Windows.
+    # Don't forget to use absolute paths, not relative paths.
+    "/home/bmoe/gracedb/templates",
+)
diff --git a/settings/development_er2.py b/settings/development_er2.py
new file mode 100644
index 0000000000000000000000000000000000000000..22260173ca1cb7a1474e7395634f26b54ff8b652
--- /dev/null
+++ b/settings/development_er2.py
@@ -0,0 +1,46 @@
+
+
+CONFIG_NAME = "ER2"
+
+DEBUG = True
+TEMPLATE_DEBUG = DEBUG
+
+DATABASES = {
+    'default' : {
+        'NAME'     : 'er2',
+        'ENGINE'   : 'django.db.backends.mysql',
+        'USER'     : 'er2',
+        'PASSWORD' : 'weasel',
+    }
+}
+
+ALERT_EMAIL_FROM = "Dev Alert <root@moe.phys.uwm.edu>"
+ALERT_EMAIL_TO = [
+    "Brian Moe <bmoe@gravity.phys.uwm.edu>",
+    ]
+ALERT_EMAIL_BCC = ["bmoe@uwm.edu"]
+
+ALERT_TEST_EMAIL_FROM = "Dev Test Alert <root@moe.phys.uwm.edu>"
+ALERT_TEST_EMAIL_TO = [
+    "Brian Moe <bmoe@gravity.phys.uwm.edu>",
+    ]
+
+XMPP_ALERT_CHANNELS = [
+                      ]
+ 
+# SkyAlert
+SKYALERT_IVORN_PATTERN = "ivo://ligo.org/gracedb#%s-dev-er2"
+
+# Latency histograms.  Where they go and max latency to bin.
+LATENCY_REPORT_DEST_DIR = "/home/bmoe/data/latency"
+
+SITE_ID = 4
+
+TEMPLATE_DIRS = (
+    # Put strings here, like "/home/html/django_templates" or "C:/www/django/templates".
+    # Always use forward slashes, even on Windows.
+    # Don't forget to use absolute paths, not relative paths.
+    "/home/bmoe/ER2/templates",
+)
+
+
diff --git a/settings/production.py b/settings/production.py
new file mode 100644
index 0000000000000000000000000000000000000000..9738870b9656c1ceb33b6b2182e92394b440234d
--- /dev/null
+++ b/settings/production.py
@@ -0,0 +1,4 @@
+
+CONFIG_NAME = "PRODUCTION"
+
+SITE_ID = 3
diff --git a/settings_dev.py b/settings_dev.py
deleted file mode 100644
index c0bece276522b8fa465eaf7df76ee0aeb6303043..0000000000000000000000000000000000000000
--- a/settings_dev.py
+++ /dev/null
@@ -1,185 +0,0 @@
-# Django settings for gracedb project.
-
-try:
-    # Workaround for a bug
-    # http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=473584
-    # http://bugs.python.org/setuptools/issue36
-    # import MySQLdb followed by import pkg_resources complains
-    #   /usr/lib/python2.6/dist-packages/pytz/__init__.py:32: UserWarning: Module _mysql was already imported from /usr/lib/pymodules/python2.6/_mysql.so, but /usr/lib/pymodules/python2.6 is being added to sys.path
-    import pkg_resources
-except:
-    pass
-
-
-DEBUG = True
-TEMPLATE_DEBUG = DEBUG
-
-ADMINS = (
-    ('Brian Moe', 'bmoe@gravity.phys.uwm.edu'),
-)
-
-MANAGERS = ADMINS
-
-ALERT_EMAIL_FROM = "Dev Alert <root@moe.phys.uwm.edu>"
-ALERT_EMAIL_TO = [
-    "Brian Moe <bmoe@gravity.phys.uwm.edu>",
-    ]
-ALERT_EMAIL_BCC = ["bmoe@uwm.edu"]
-
-ALERT_TEST_EMAIL_FROM = "Dev Test Alert <root@moe.phys.uwm.edu>"
-ALERT_TEST_EMAIL_TO = [
-    "Brian Moe <bmoe@gravity.phys.uwm.edu>",
-    ]
-
-# Don't sent out non-test XMPP alerts on dev box!
-XMPP_ALERT_CHANNELS = [
-                        'test_omega',
-                        'test_mbtaonline',
-                        'test_cwb',
-                        'test_lowmass',
-                      ]
- 
-DATABASES = {
-    'default' : {
-        'NAME'     : 'gracedb',
-        'ENGINE'   : 'django.db.backends.mysql',
-        'USER'     : 'gracedb',
-        'PASSWORD' : 'redrum4x',
-    }
-}
-
-# SkyAlert
-
-SKYALERT_IVORN_PATTERN = "ivo://ligo.org/gracedb#%s-dev"
-SKYALERT_ROLE          = "test"
-SKYALERT_DESCRIPTION   = "LIGO / Virgo trigger"
-SKYALERT_SUBMITTERS = ['Patrick Brady', 'Brian Moe']
-
-
-GRACEDB_DATA_DIR = "/mnt/gracedb-web/data"
-#GRACEDB_DATA_DIR = "/mnt/gracedb-web-temp/data"
-
-# Latency histograms.  Where they go and max latency to bin.
-LATENCY_REPORT_DEST_DIR = "/home/bmoe/data/latency"
-LATENCY_MAXIMUM_CHARTED = 1800
-LATENCY_REPORT_WEB_PAGE_FILE_PATH = LATENCY_REPORT_DEST_DIR + "/latency.inc"
-
-
-
-# CBC IFAR Reports
-
-from utils import posixToGpsTime
-from datetime import datetime, timedelta
-import time
-
-now = datetime.now()
-yesterday = now - timedelta(days=1)
-lastweek = now - timedelta(days=7)
-now = posixToGpsTime(time.mktime(now.timetuple()))
-yesterday = posixToGpsTime(time.mktime(yesterday.timetuple()))
-lastweek = posixToGpsTime(time.mktime(lastweek.timetuple()))
-
-REPORT_IFAR_IMAGE_DIR = LATENCY_REPORT_DEST_DIR
-REPORTS_IFAR = [
-    #(query, axis_label, title, fname),
-    ("LowMass %d..%d" % (yesterday, now),
-     "GraceDB CBC LowMass ER1 events",
-     "ER1 FARs from gstlal_ll_inspiral - last day",
-     "ifar_day.png"
-    ),
-    ("LowMass %d..%d" % (lastweek, now),
-     "GraceDB CBC LowMass ER1 events",
-     "ER1 FARs from gstlal_ll_inspiral - last week",
-     "ifar_week.png"
-    ),
-]
-
-
-# RSS Feed Defaults
-FEED_MAX_RESULTS = 50
-
-# Local time zone for this installation. Choices can be found here:
-# http://en.wikipedia.org/wiki/List_of_tz_zones_by_name
-# although not all choices may be available on all operating systems.
-# If running in a Windows environment this must be set to the same as your
-# system time zone.
-
-TIME_ZONE = 'America/Chicago'
-GRACE_DATETIME_FORMAT = 'Y-m-d H:i:s T'
-
-# Language code for this installation. All choices can be found here:
-# http://www.i18nguy.com/unicode/language-identifiers.html
-LANGUAGE_CODE = 'en-us'
-
-SITE_ID = 4
-
-# If you set this to False, Django will make some optimizations so as not
-# to load the internationalization machinery.
-USE_I18N = True
-
-# Absolute path to the directory that holds media.
-# Example: "/home/media/media.lawrence.com/"
-MEDIA_ROOT = ''
-
-# URL that handles the media served from MEDIA_ROOT. Make sure to use a
-# trailing slash if there is a path component (optional in other cases).
-# Examples: "http://media.lawrence.com", "http://example.com/media/"
-MEDIA_URL = '/gracedb-static/'
-
-# URL prefix for admin media -- CSS, JavaScript and images. Make sure to use a
-# trailing slash.
-# Examples: "http://foo.com/media/", "/media/".
-ADMIN_MEDIA_PREFIX = '/media/'
-
-# Make this unique, and don't share it with anybody.
-SECRET_KEY = '$$&hl%^_4&s0k7sbdr8ll_^gkz-j8oab0tz$t^^b-%$!83d(av'
-
-# List of callables that know how to import templates from various sources.
-TEMPLATE_LOADERS = (
-    #'django.template.loaders.filesystem.load_template_source',
-    # replaced by...
-    'django.template.loaders.filesystem.Loader',
-    'django.template.loaders.app_directories.load_template_source',
-#     'django.template.loaders.eggs.load_template_source',
-)
-
-TEMPLATE_CONTEXT_PROCESSORS = (
-    #"django.core.context_processors.auth",
-    # replaced by...
-    "django.contrib.auth.context_processors.auth",
-    "django.core.context_processors.debug",
-    "django.core.context_processors.i18n",
-    "django.core.context_processors.media",
-    "django.core.context_processors.request",
-    "gracedb.middleware.auth.LigoAuthContext",
-)
-
-AUTHENTICATION_BACKENDS = ('gracedb.middleware.auth.LigoAuthBackend',)
-
-MIDDLEWARE_CLASSES = (
-    'gracedb.middleware.accept.AcceptMiddleware',
-    'gracedb.middleware.auth.LigoAuthMiddleware',
-    'gracedb.middleware.cli.CliExceptionMiddleware',
-    'django.middleware.common.CommonMiddleware',
-    'django.contrib.sessions.middleware.SessionMiddleware',
-    'django.contrib.auth.middleware.AuthenticationMiddleware',
-)
-
-ROOT_URLCONF = 'gracedb.urls'
-
-TEMPLATE_DIRS = (
-    # Put strings here, like "/home/html/django_templates" or "C:/www/django/templates".
-    # Always use forward slashes, even on Windows.
-    # Don't forget to use absolute paths, not relative paths.
-    "/home/bmoe/gracedb/templates",
-)
-
-INSTALLED_APPS = (
-    'django.contrib.auth',
-    'django.contrib.admin',
-    'django.contrib.contenttypes',
-    'django.contrib.sessions',
-    'django.contrib.sites',
-    'gracedb.gracedb',
-    'gracedb.userprofile',
-)
diff --git a/templates/base.html b/templates/base.html
index 32b3cbbe5e44b8177956e3e3d495fd973f1fd57e..df80171f9508abd62b75675cb4b4275555bd3f6f 100644
--- a/templates/base.html
+++ b/templates/base.html
@@ -38,6 +38,13 @@ function changeTime(obj, label) {
     <li id="nav-userprofile"><a href="{% url userprofile-home %}">Options</a></li>
     {% if ligouser %}<li id="nav-user">Authenticated as: {{ ligouser.name }}</li>{% endif %}
 </ul>
+<center>
+    {% if config_name %}
+      <h1 style="color: red;">
+          {{config_name}}
+      </h1>
+    {% endif %}
+</center>
 {% endblock %}
 
         <p>&nbsp;</p> <!-- bad way to create vertical space -->
diff --git a/templates/feeds/index.html b/templates/feeds/index.html
index 7050bf6e90ed5f2855dfe1b932c3b2cd58952727..4137a15b46b7d520595b35785d802f8bdf6171e9 100644
--- a/templates/feeds/index.html
+++ b/templates/feeds/index.html
@@ -12,7 +12,7 @@
     <li><a href="latest/burst/">Burst</a></li>
       <ul>
         <li><a href="latest/burst/omega">Omega</a></li>
-        <li><a href="latest/stochastic/cwb">CWB</a></li>
+        <li><a href="latest/burst/cwb">CWB</a></li>
         <li><a href="latest/burst/q">Q</a></li>
         <li><a href="latest/burst/x">X</a></li>
       </ul>
diff --git a/urls.py b/urls.py
index 9d2d04ede91e9c537502d343a1dd9bfe09874a1b..021b2905cc1d3bf4377a8382784b68c6d89dc4f4 100644
--- a/urls.py
+++ b/urls.py
@@ -14,20 +14,20 @@ feeds = {
 
 urlpatterns = patterns('',
 
-    url (r'^$', 'gracedb.gracedb.views.index', name="home"),
-    (r'^events/', include('gracedb.gracedb.urls')),
-    (r'^options/', include('gracedb.userprofile.urls')),
-    (r'^cli/create', 'gracedb.gracedb.views.create'),
-    (r'^cli/ping', 'gracedb.gracedb.views.ping'),
-    (r'^cli/log', 'gracedb.gracedb.views.log'),
-    (r'^cli/upload', 'gracedb.gracedb.views.upload'),
-    (r'^cli/tag', 'gracedb.gracedb.views.cli_tag'),
-    (r'^cli/label', 'gracedb.gracedb.views.cli_label'),
-    (r'^cli/search', 'gracedb.gracedb.views.cli_search'),
+    url (r'^$', 'gracedb.views.index', name="home"),
+    (r'^events/', include('gracedb.urls')),
+    (r'^options/', include('userprofile.urls')),
+    (r'^cli/create', 'gracedb.views.create'),
+    (r'^cli/ping', 'gracedb.views.ping'),
+    (r'^cli/log', 'gracedb.views.log'),
+    (r'^cli/upload', 'gracedb.views.upload'),
+    (r'^cli/tag', 'gracedb.views.cli_tag'),
+    (r'^cli/label', 'gracedb.views.cli_label'),
+    (r'^cli/search', 'gracedb.views.cli_search'),
     (r'^feeds/(?P<url>.*)/$', EventFeed()),
     url (r'^feeds/$', feedview, name="feeds"),
 
-    url (r'^reports/$', 'gracedb.gracedb.reports.histo', name="reports"),
+    url (r'^reports/$', 'gracedb.reports.histo', name="reports"),
     (r'^reports/(?P<path>.+)$', 'django.views.static.serve',
             {'document_root': settings.LATENCY_REPORT_DEST_DIR}),
 
diff --git a/userprofile/models.py b/userprofile/models.py
index ba3ad70dc252d95089456da71cc6bfb4555448cd..dbabd67bfff5550932a19c270ef7ca62adc0e9b5 100644
--- a/userprofile/models.py
+++ b/userprofile/models.py
@@ -1,7 +1,7 @@
 
 from django.db import models
 
-from gracedb.gracedb.models import User, Label, Event
+from gracedb.models import User, Label, Event
 
 
 #class Notification(models.Model):
diff --git a/userprofile/urls.py b/userprofile/urls.py
index 00f08d595c897fa9100432953622e35bfc7a7550..e531245f3ca2cebb1a177dfa79f7d0dd2e3f20ff 100644
--- a/userprofile/urls.py
+++ b/userprofile/urls.py
@@ -2,7 +2,7 @@
 from django.conf.urls.defaults import *
 
 
-urlpatterns = patterns('gracedb.userprofile.views',
+urlpatterns = patterns('userprofile.views',
     url (r'^$', 'index', name="userprofile-home"),
     url (r'^contact/create$', 'createContact', name="userprofile-create-contact"),
     url (r'^contact/delete/(?P<id>[\d]+)$', 'deleteContact', name="userprofile-delete-contact"),
diff --git a/userprofile/views.py b/userprofile/views.py
index 25f8c3d871e8cfd18326d770cbcd9b75f88dbdfd..d2d3ddea758702ff3a9c22a6d0fe8f6042f97b19 100644
--- a/userprofile/views.py
+++ b/userprofile/views.py
@@ -8,7 +8,7 @@ from django.core.urlresolvers import reverse
 from django.template import RequestContext
 from django.shortcuts import render_to_response
 
-from gracedb.userprofile.models import Trigger, Contact
+from models import Trigger, Contact
 
 from forms import ContactForm, triggerFormFactory