diff --git a/README.md b/README.md
index 5e58d826a82090fe8beface27f60130beadd185e..a25dfde990b292b190f8733f274e6306659d698e 100644
--- a/README.md
+++ b/README.md
@@ -10,5 +10,5 @@ dynamic/interactive parts of [ant.sr](https://ant.sr).
 
 # Development Server
 
-* `flask run`
+* `./run.py`
 * Visit [localhost:5000](http://127.0.0.1:5000).
diff --git a/api/.app.py.swo b/api/.app.py.swo
new file mode 100644
index 0000000000000000000000000000000000000000..f0d79534215d138ef7a155ac0b1f677cbbdecd18
Binary files /dev/null and b/api/.app.py.swo differ
diff --git a/api/__init__.py b/api/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/api/api.py b/api/api.py
new file mode 100644
index 0000000000000000000000000000000000000000..dbeb7e9a79dde5a9782f122a0a289f664a69017c
--- /dev/null
+++ b/api/api.py
@@ -0,0 +1,12 @@
+import json
+from strava import Strava
+
+class Api():
+    """API interfaces"""
+    def __init__(self, api_name):
+        def strava():
+            """Strava API - get my recent rides"""
+            s = Strava()
+            return json.dumps(s.get_athlete())
+        functions = {name:f for (name, f) in locals() if l != 'self'}
+        return functions[api_name]
diff --git a/app.py b/api/app.py
similarity index 73%
rename from app.py
rename to api/app.py
index 404dd4ca77f097a6c4159fb8e13c32cf05ea4742..fd1a6fabb6d42ec164f7769afd955a43512dd636 100644
--- a/app.py
+++ b/api/app.py
@@ -2,8 +2,9 @@ from flask import Flask, redirect, render_template, url_for
 from strava import Strava
 from decorators import admin
 
-app = Flask(__name__)
+app = Flask(__name__, instance_relative_config=True)
 app.config.from_object('config')
+app.config.from_pyfile('config.py')
 
 @app.route('/')
 def index():
@@ -14,6 +15,11 @@ def index():
 def strava_auth():
     return Strava.authorize()
 
+@app.route('/api/<api_name>')
+def api(api_name):
+    from api import Api
+    return Api(api_name)
+
 @app.context_processor
 def cp_is_admin():
     from util import is_admin
diff --git a/decorators.py b/api/decorators.py
similarity index 100%
rename from decorators.py
rename to api/decorators.py
diff --git a/strava.py b/api/strava.py
similarity index 81%
rename from strava.py
rename to api/strava.py
index 52785d673219ad85e2321de82fa3960f37343674..434675c5d473c43c3eea1a361b60c0c58f4a2f2d 100644
--- a/strava.py
+++ b/api/strava.py
@@ -1,7 +1,6 @@
-from flask import request, redirect
+from flask import request, redirect, current_app
 from stravalib.client import Client
 from requests.exceptions import HTTPError
-import config
 
 class Strava():
     @classmethod
@@ -14,7 +13,7 @@ class Strava():
             return strava.get_athlete().email
         except (HTTPError, AttributeError):
             return False
-        
+
     @classmethod
     def authorize(cls, code = None):
         """Redirect to Strava to get an access token."""
@@ -24,14 +23,14 @@ class Strava():
             source_url = request.referrer
             authorized_url = request.url
             authorize_url = strava.authorization_url(
-                client_id=config.STRAVA_APP_ID, redirect_uri=authorized_url, state=source_url)
+                client_id=current_app.config['STRAVA_APP_ID'], redirect_uri=authorized_url, state=source_url)
             return redirect(authorize_url)
         else:
             source_url = request.args.get('state', None)
             strava = Client()
             access_token = strava.exchange_code_for_token(
-                client_id=config.STRAVA_APP_ID,
-                client_secret=config.STRAVA_APP_SECRET,
+                client_id=current_app.config['STRAVA_APP_ID'],
+                client_secret=current_app.config['STRAVA_APP_SECRET'],
                 code=code)
             strava.access_token = access_token
             # TODO: store the access token
diff --git a/templates/base.html b/api/templates/base.html
similarity index 100%
rename from templates/base.html
rename to api/templates/base.html
diff --git a/templates/index.html b/api/templates/index.html
similarity index 100%
rename from templates/index.html
rename to api/templates/index.html
diff --git a/util.py b/api/util.py
similarity index 59%
rename from util.py
rename to api/util.py
index a42b05fcde1bdbc3782a51b2b778ccf954932c03..bdbbcc47ed43dd0f25ba2b17b595b6e48fcf552e 100644
--- a/util.py
+++ b/api/util.py
@@ -1,9 +1,8 @@
-from flask import request
-import config
+from flask import request, current_app
 
 def is_admin():
     try:
-        admin_ip = config.ADMIN_IP
+        admin_ip = current_app.config.ADMIN_IP
     except AttributeError:
         admin_ip = '127.0.0.1'
     return request.remote_addr == admin_ip
diff --git a/config.py.dist b/config.py.dist
deleted file mode 100644
index 01cdaf993677e3c2d7b079b7f60953264de2b0ef..0000000000000000000000000000000000000000
--- a/config.py.dist
+++ /dev/null
@@ -1,4 +0,0 @@
-STRAVA_APP_ID = '12345'
-STRAVA_APP_SECRET = 'your-strava-app-secret'
-ADMIN_IP = '127.0.0.1'
-
diff --git a/run.py b/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..53c616fe7a62d29877ae0de67ee5dd41acef262d
--- /dev/null
+++ b/run.py
@@ -0,0 +1,4 @@
+#!/usr/bin/env python
+from api.app import app
+
+app.run()