diff --git a/.gitignore b/.gitignore
index 9f28e5cb447949081556e27b2b1702613de93bbc..2dcb4d9f42f23b7af576b707bd66f202bed1e826 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,4 +2,5 @@ __pycache__
 *.db
 */env
 *.coverage
+htmlcov
 .pytest_cache
\ No newline at end of file
diff --git a/.vscode/tasks.json b/.vscode/tasks.json
index 72270e125a8b1eb2597597a576cd83192122ca04..22158c9dda3cc8462343d3ce101686335a257da2 100644
--- a/.vscode/tasks.json
+++ b/.vscode/tasks.json
@@ -2,7 +2,7 @@
     "version": "2.0.0",
     "tasks": [
         {
-            "label": "Client",
+            "label": "Start client",
             "type": "npm",
             "script": "start",
             "path": "client/",
@@ -13,7 +13,26 @@
             }
         },
         {
-            "label": "Server",
+            "label": "Test client",
+            "type": "npm",
+            "script": "test:coverage:html",
+            "path": "client/",
+            "group": "test",
+            "problemMatcher": [],
+        },
+        {
+            "label": "Open client coverage",
+            "type": "shell",
+            "group": "build",
+            "command": "start ./output/coverage/jest/index.html",
+            "problemMatcher": [],
+            "options": {
+                "cwd": "${workspaceFolder}/client"
+            },
+
+        },
+        {
+            "label": "Start server",
             "type": "shell",
             "group": "build",
             "command": "env/Scripts/python main.py",
@@ -26,10 +45,20 @@
             }
         },
         {
-            "label": "Test Server",
+            "label": "Test server",
+            "type": "shell",
+            "group": "build",
+            "command": "env/Scripts/pytest.exe --cov-report html --cov app tests/",
+            "problemMatcher": [],
+            "options": {
+                "cwd": "${workspaceFolder}/server"
+            },
+        },
+        {
+            "label": "Open server coverage",
             "type": "shell",
             "group": "build",
-            "command": "env/Scripts/pytest.exe --cov app tests/",
+            "command": "start ./htmlcov/index.html",
             "problemMatcher": [],
             "options": {
                 "cwd": "${workspaceFolder}/server"
@@ -37,11 +66,11 @@
 
         },
         {
-            "label": "Client + Server",
+            "label": "Start client and server",
             "group": "build",
             "dependsOn": [
-                "Server",
-                "Client"
+                "Start server",
+                "Start client"
             ],
             "problemMatcher": []
         }
diff --git a/README.md b/README.md
index 66ebcfb30963378191d2d4aaea096f5af3efa910..cd540e1f8c23ae68119a1b0a1d89bd7b82f5e316 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,6 @@
 ![coverage report](https://gitlab.liu.se/tddd96-grupp11/teknikattan-scoring-system/badges/dev/coverage.svg?job=client:test&key_text=Client+Coverage&key_width=110)
 ![coverage report](https://gitlab.liu.se/tddd96-grupp11/teknikattan-scoring-system/badges/dev/coverage.svg?job=server:test&key_text=Server+Coverage&key_width=115)
 
-
 # Scoring system for Teknikåttan
 
 This is the scoring system for Teknikåttan!
@@ -13,6 +12,65 @@ To install the client and server needed to run the application, look in their re
 ## Using
 
 After installing both the client and the server, you are ready to run the application.
-This is done in VSCode by pressing `ctrl+shift+b` and running the `Client + Server` task.
+This is done in VSCode by pressing `ctrl+shift+b` and running the `Start client and server` task.
 The terminals for the client and server will now be seen on the right and left, respectively.
-After making a change to either the client or the server while they are running, they will auto reload and you will see the changes immediately.
+After making a change to either the client or the server while they are running, simply reload the page to see the changes immediately.
+
+## Workflow
+
+### Working on an issue
+
+This following steps describe how you choose an issue and create a branch and merge request from it.
+
+1. See all issues by going to `Issues->Boards`.
+2. The issues no one has started on yet are showed in the `Open` tab. Choose one of these by dragging it into the `In progress` tab and opening it.
+3. Add yourself as an asignee (in top right corner).
+4. Add the current week as a milestone to the issue (to the right).
+5. Press the little green downarrow on the right of the `Create merge request` button and select and press `Create branch`.
+6. Open the project in VSCode.
+7. Type `git pull`. This will fetch the new branch you just created and you should see it in the log (Example: `* [new branch] 5-add-login-api -> origin/5-add-login-api`)
+8. Switch to it by running `git checkout <issue>-<name>`. (Example: `git checkout 5-add-login-api`)
+
+You are now ready to start working on your issue.
+
+### Creating a merge request
+
+When you have solved the issue and are ready to merge them into the `dev` will have to create a merge request.
+
+1. On GitLab open `Repository->Branches`.
+2. Find your branch and press `Merge request`.
+
+You have now create a merge request for your branch.
+The next step is to prepare your branch to be merged.
+
+1. Open the project in VSCode.
+2. Checkout your branch, if you are not already on it (`git checkout <branch>`).
+3. Run `git pull origin dev`. This will try to merge the latest changes from `dev` into your branch. This can have a few different results:
+   - There will be no changes, which is fine.
+   - There will be no conflicting changes, which is also fine.
+   - There will be conflicting changes, in which case you will need to merge it manually (see Merge conflicts) before continuing to the next step.
+4. Run `git push`.
+5. Go to GitLab and press `Merge Requests`, open your merge request and press the green `Mark as ready` button (in the top righ corner).
+
+The test will then run on your changes in the merge request on GitLab.
+You will be allowed to merge once the pipelines have passed and another person has approved your merge request.
+When this is done, simply press the `Merge` button.
+
+### Merge conflicts
+
+You will need to manually merge if there is a merge conflict between your branch and another.
+This is simply done by opening the project in VSCode and going to the Git tab on the left (git symbol).
+You will then see som files marked with `C`, which means that there are conflicts in these files.
+Open them one by one and choose if you want to keep incoming changes (from `dev`), current changes (from your branch) or both.
+The only thing you really need to do is removing the `<<<`, `===` and `>>>` symbols from the document, although you don't have to do it by hand.
+A merge typically looks like the following picture in plain (try opening this in VSCode and see how it looks).
+Simply solve all the merge conflicts in every file, run the tests to make sure it still works.
+When you are done, simply commit and push your changes.
+
+```
+<<<<<<< file.txt
+<Your changes>
+=======
+<Changes from dev>
+>>>>>>> 123456789:file.txt
+```
diff --git a/client/.gitignore b/client/.gitignore
index 4d29575de80483b005c29bfcac5061cd2f45313e..ef85236eb5861796d67cb5a15157d7e525e2989e 100644
--- a/client/.gitignore
+++ b/client/.gitignore
@@ -21,3 +21,5 @@
 npm-debug.log*
 yarn-debug.log*
 yarn-error.log*
+
+output
diff --git a/client/README.md b/client/README.md
index da908d16ebb6009136be641e69e38cad9a7f0566..23cb20572c166b66b4e46f7ba58059ecab4fd66a 100644
--- a/client/README.md
+++ b/client/README.md
@@ -24,32 +24,33 @@ npm install
 ## Using
 
 After you have done every step described in setup, you are ready to start the client.
-You can either start the client using tasks (recommended) or start it directly in the terminal.
+To see the tasks described in the following steps, press `ctrl+shift+b`.
 
-### Tasks
+### Starting
 
-You can run the client using Visual Studio Code tasks.
-This is done by pressing `ctrl+shift+b` and running the `Client` task.
+Start the server by running the `Start client` task.
 
-### Terminal
+### Testing
+
+Run the client tests running the `Test client` task.
+
+After it has finished, you can view a coverage report.
+This is done by running the `Open client coverage` task.
+
+### Adding and removing new modules
 
-You can also run the client directly from the terminal.
 All of the following snippets assume you are in the `client` folder.
 
-Running the client:
+Installing new module:
 
 ```bash
-npm run start
+npm install <module>
 ```
 
-Installing new modules:
+Uninstalling module:
 
 ```bash
-npm install new_module
+npm uninstall <module>
 ```
 
 Whenever a new module is installed, commited and pushed to git, everyone else needs to run `npm install` after pulling to install it as well.
-
-Author: Victor Löfgren
-
-Last updated: 11 February 2020
diff --git a/client/package.json b/client/package.json
index 707cdc2d1ed3efa51cb8def43c5d8c0fb3471c21..2b67c10305c3bd117c493746990d291fceb5af56 100644
--- a/client/package.json
+++ b/client/package.json
@@ -4,7 +4,10 @@
   "private": true,
   "dependencies": {
     "@material-ui/core": "^4.11.3",
+<<<<<<< HEAD
     "@material-ui/icons": "^4.11.2",
+=======
+>>>>>>> 186d707ace54d27ff8913eff2be29026e64afb43
     "@material-ui/lab": "^4.0.0-alpha.57",
     "@testing-library/jest-dom": "^5.11.9",
     "@testing-library/react": "^11.2.5",
@@ -45,7 +48,8 @@
     "test": "react-scripts test",
     "eject": "react-scripts eject",
     "lint": "eslint \"./src/**/*.{js,ts,tsx}\"",
-    "test:coverage": "react-scripts test --coverage --coverageDirectory=output/coverage/jest"
+    "test:coverage": "react-scripts test --coverage --coverageDirectory=output/coverage/jest",
+    "test:coverage:html": "npm test -- --coverage --watchAll=false --coverageDirectory=output/coverage/jest"
   },
   "browserslist": {
     "production": [
diff --git a/client/src/App.tsx b/client/src/App.tsx
index 1e8c051e2d67e0a74f4ef26ab737a7427cf23b52..c26dce58152b871aa48b13f4c333f4fbe461e6ef 100644
--- a/client/src/App.tsx
+++ b/client/src/App.tsx
@@ -9,7 +9,19 @@ const App: React.FC = () => {
         rel="stylesheet"
         href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700&display=swap"
       />
+<<<<<<< HEAD
       <Main />
+=======
+      <h1>Application</h1>
+      <TestConnection />
+      <BrowserRouter>
+        <Switch>
+          <Route path="/">
+            <LoginForm />
+          </Route>
+        </Switch>
+      </BrowserRouter>
+>>>>>>> 186d707ace54d27ff8913eff2be29026e64afb43
     </div>
   )
 }
diff --git a/server/README.md b/server/README.md
index b52b51c070844778fc4424670c8ab2ec6dc32a84..84d994d85e475930cd49d6a8adb0a6372289d302 100644
--- a/server/README.md
+++ b/server/README.md
@@ -11,7 +11,7 @@ You will need to do the following things to install the server:
 3. Clone this repository if you haven't done so already.
 4. Open the project folder in VSCode.
 5. Open the integrated terminal by pressing `ctrl+ö`.
-6. Type the following commands (or if you are on Windows, simply paste them) into your terminal:
+6. Type the following commands into your terminal:
 
 ```bash
 # Install virtualenv package. You may need to open as administrator if you get
@@ -29,12 +29,13 @@ py -m venv env
 # This step is different depending on your operating system.
 
 # Windows
-# You migt to run the following before activating the virtual environment.
 Set-ExecutionPolicy Unrestricted -Scope Process
 ./env/Scripts/activate
+# =====
 
 # Linux/Mac
-# source env/bin/activate
+source env/bin/activate
+# =====
 
 # Install all the required packages into your virtual environment.
 pip install -r requirements.txt
@@ -42,35 +43,40 @@ pip install -r requirements.txt
 
 ## Using
 
-After you have done every step described in setup, you are ready to run the server.
-You can either run the server using tasks (recommended) or run it directly in the terminal.
+After you have done every step described in setup, you are ready to start the server.
+To see the tasks described in the following steps, press `ctrl+shift+b`.
 
-### Tasks
+### Starting
 
-You can run the server using Visual Studio Code tasks.
-This is done by pressing `ctrl+shift+b` and running the `Server` task.
+Start the server by running the `Start server` task.
 
-### Terminal
+### Testing
 
-You can also run the server and tests directly from the terminal.
-Before doing anything in the terminal, you need to activate the Python virtual environment (see Setup).
-All of the following snippets assume you are in the `server` folder.
+Run the client tests running the `Test server` task.
 
-Running the server:
+After it has finished, you can view a coverage report.
+This is done by running the `Open server coverage` task.
+
+### Adding and removing new packages
+
+All of the following snippets assume you are in the `server` folder and have activated the virtual environment (see Setup).
+
+Installing new package:
 
 ```bash
-python main.py
+pip install <package>
 ```
 
-Running the tests:
+Uninstalling package:
 
 ```bash
-python test.py
+pip uninstall <package>
 ```
 
-Adding new packages:
+If you have added or removed a package from the repository, you will also have to run the following before commiting it to git:
 
 ```bash
-pip install new_package
 pip freeze > requirements.txt
 ```
+
+Whenever a new package is installed, commited and pushed to git, everyone else needs to run `pip install -r requirements.txt` after pulling to install it as well.
diff --git a/server/app/api/users.py b/server/app/api/users.py
index db7859f264c3af31d346b2b1f42cebd2f8d4574a..0d92ee52ca97406b99b98939bdc5bea54411c787 100644
--- a/server/app/api/users.py
+++ b/server/app/api/users.py
@@ -5,6 +5,7 @@ from app.api import api_blueprint
 from app.database.models import Blacklist, User
 from app.utils.validator import edit_user_schema, login_schema, register_schema, validateObject
 from flask import request
+from flask.globals import session
 from flask_jwt_extended import (
     create_access_token,
     create_refresh_token,
diff --git a/server/app/database/__init__.py b/server/app/database/__init__.py
index d755b84e4ed716e143e95b5b50503a52e98f04a9..4a1dc8b75fcd414adf91d242e8367c98d763db55 100644
--- a/server/app/database/__init__.py
+++ b/server/app/database/__init__.py
@@ -1,13 +1,10 @@
-from flask_sqlalchemy.model import Model
 import sqlalchemy as sa
+from flask_sqlalchemy.model import Model
 from sqlalchemy.ext.declarative import declared_attr
 from sqlalchemy.sql import func
 
 
 class Base(Model):
-    @declared_attr
-    def __tablename__(self):
-        return self.__class__.__name__.replace("Model", "s").lower()
-
+    __abstract__ = True
     created = sa.Column(sa.DateTime(timezone=True), server_default=func.now())
     updated = sa.Column(sa.DateTime(timezone=True), onupdate=func.now())
diff --git a/server/app/database/models.py b/server/app/database/models.py
index bd486a144d28f46c358ab8979d274ed1b3cd83e7..5452ce3d7e5a1373af783c57dd2453ede892392c 100644
--- a/server/app/database/models.py
+++ b/server/app/database/models.py
@@ -1,22 +1,38 @@
-from sqlalchemy.ext.hybrid import hybrid_property, hybrid_method
+from app import bcrypt, db
 from sqlalchemy.ext.declarative import declared_attr
+from sqlalchemy.ext.hybrid import hybrid_method, hybrid_property
 
-from app import bcrypt, db
-from app.database import Base
+STRING_SIZE = 254
 
 
 class Blacklist(db.Model):
     id = db.Column(db.Integer, primary_key=True)
     jti = db.Column(db.String, unique=True, nullable=False)
 
-    @declared_attr
-    def __tablename__(self):
-        return "blacklist"
-
     def __init__(self, jti):
         self.jti = jti
 
 
+class Role(db.Model):
+    id = db.Column(db.Integer, primary_key=True)
+    name = db.Column(db.String(STRING_SIZE), unique=True)
+
+    users = db.relationship("User", backref="role")
+
+    def __init__(self, name):
+        self.name = name
+
+
+class City(db.Model):
+    id = db.Column(db.Integer, primary_key=True)
+    name = db.Column(db.String(STRING_SIZE), unique=True)
+
+    users = db.relationship("User", backref="city")
+
+    def __init__(self, name):
+        self.name = name
+
+
 class User(db.Model):
     id = db.Column(db.Integer, primary_key=True)
     email = db.Column(db.String(254), unique=True, nullable=False)
@@ -28,9 +44,16 @@ class User(db.Model):
     twoAuthConfirmed = db.Column(db.Boolean, default=True)  # Change to false for Two factor authen
     twoAuthCode = db.Column(db.String(100), nullable=True)
 
-    def __init__(self, email, plaintext_password, name=""):
+    role_id = db.Column(db.Integer, db.ForeignKey("role.id"), nullable=True)  # Change to false
+    city_id = db.Column(db.Integer, db.ForeignKey("city.id"), nullable=True)  # Change to false
+
+    media = db.relationship("Media", backref="upload_by")
+
+    def __init__(self, email, plaintext_password, role_id=None, city_id=None, name=None):
         self._password = bcrypt.generate_password_hash(plaintext_password)
         self.email = email
+        self.role_id = role_id
+        self.city_id = city_id
         self.name = name
         self.authenticated = False
 
@@ -48,3 +71,164 @@ class User(db.Model):
     @hybrid_method
     def is_correct_password(self, plaintext_password):
         return bcrypt.check_password_hash(self._password, plaintext_password)
+
+
+class Media(db.Model):
+    id = db.Column(db.Integer, primary_key=True)
+    filename = db.Column(db.String(STRING_SIZE), unique=True)
+    type = db.Column(db.String(STRING_SIZE), nullable=False)
+    upload_by_id = db.Column(db.Integer, db.ForeignKey("user.id"), nullable=False)
+
+    def __init__(self, filename, type, upload_by_id):
+        self.filename = filename
+        self.type = type
+        self.upload_by_id = upload_by_id
+
+
+class Style(db.Model):
+    id = db.Column(db.Integer, primary_key=True)
+    name = db.Column(db.String(STRING_SIZE), unique=True)
+    css = db.Column(db.Text, nullable=True)
+    bg_image_id = db.Column(db.Integer, db.ForeignKey("media.id"), nullable=True)
+
+    bg_image = db.relationship("Media", foreign_keys=[bg_image_id], uselist=False)
+
+    def __init__(self, name, css=None, bg_image_id=None):
+        self.name = name
+        self.css = css
+        self.bg_image_id = bg_image_id
+
+
+class Competition(db.Model):
+    id = db.Column(db.Integer, primary_key=True)
+    name = db.Column(db.String(STRING_SIZE), unique=True)
+    style_id = db.Column(db.Integer, db.ForeignKey("style.id"), nullable=False)
+    city_id = db.Column(db.Integer, db.ForeignKey("city.id"), nullable=False)
+
+    style = db.relationship("Style", foreign_keys=[style_id], uselist=False)
+    city = db.relationship("City", foreign_keys=[city_id], uselist=False)
+
+    def __init__(self, name, style_id, city_id):
+        self.name = name
+        self.style_id = style_id
+        self.city_id = city_id
+
+
+class Team(db.Model):
+    id = db.Column(db.Integer, primary_key=True)
+    name = db.Column(db.String(STRING_SIZE), unique=True)
+    competition_id = db.Column(db.Integer, db.ForeignKey("competition.id"), nullable=False)
+    competition = db.relationship("Competition", foreign_keys=[competition_id], uselist=False)
+
+    def __init__(self, name, competition_id):
+        self.name = name
+        self.competition_id = competition_id
+
+
+class Slide(db.Model):
+    id = db.Column(db.Integer, primary_key=True)
+    name = db.Column(db.String(STRING_SIZE), unique=True)
+    order = db.Column(db.Integer, nullable=False)
+    tweak_settings = db.Column(db.Text, nullable=True)
+    competition_id = db.Column(db.Integer, db.ForeignKey("competition.id"), nullable=False)
+
+    competition = db.relationship("Competition", foreign_keys=[competition_id], uselist=False)
+
+    def __init__(self, name, order, competition_id, tweak_settings=None):
+        self.name = name
+        self.order = order
+        self.competition_id = competition_id
+        self.tweak_settings = tweak_settings
+
+
+class Question(db.Model):
+    id = db.Column(db.Integer, primary_key=True)
+    name = db.Column(db.String(STRING_SIZE), unique=True)
+    title = db.Column(db.String(STRING_SIZE), nullable=False)
+    timer = db.Column(db.Integer, nullable=False)
+    slide_id = db.Column(db.Integer, db.ForeignKey("slide.id"), nullable=False)
+
+    slide = db.relationship("Slide", foreign_keys=[slide_id], uselist=False)
+
+    def __init__(self, name, title, timer, slide_id):
+        self.name = name
+        self.title = title
+        self.timer = timer
+        self.slide_id = slide_id
+
+
+class TrueFalseQuestion(db.Model):
+    id = db.Column(db.Integer, primary_key=True)
+    true_false = db.Column(db.Boolean, nullable=False, default=False)
+    question_id = db.Column(db.Integer, db.ForeignKey("question.id"), nullable=False)
+
+    question = db.relationship("Question", foreign_keys=[question_id], uselist=False)
+
+    def __init__(self, true_false, question_id):
+        self.true_false = true_false
+        self.question_id = question_id
+
+
+class TextQuestion(db.Model):
+    id = db.Column(db.Integer, primary_key=True)
+    question_id = db.Column(db.Integer, db.ForeignKey("question.id"), nullable=False)
+    question = db.relationship("Question", foreign_keys=[question_id], uselist=False)
+
+    def __init__(self, question_id):
+        self.question_id = question_id
+
+
+class TextQuestionAlternative(db.Model):
+    id = db.Column(db.Integer, primary_key=True)
+    text = db.Column(db.String(STRING_SIZE), nullable=False)
+    text_question_id = db.Column(db.Integer, db.ForeignKey("text_question.id"), nullable=False)
+    text_question = db.relationship("TextQuestion", foreign_keys=[text_question_id], uselist=False)
+
+    def __init__(self, text, text_question_id):
+        self.text = text
+        self.text_question_id = text_question_id
+
+
+class MCQuestion(db.Model):
+    id = db.Column(db.Integer, primary_key=True)
+    title = db.Column(db.String(STRING_SIZE), nullable=False)
+    timer = db.Column(db.Integer, nullable=False)
+    question_id = db.Column(db.Integer, db.ForeignKey("question.id"), nullable=False)
+
+    question = db.relationship("Question", foreign_keys=[question_id], uselist=False)
+
+    def __init__(self, title, timer, slide_id):
+        self.title = title
+        self.timer = timer
+        self.slide_id = slide_id
+
+
+class MCQuestionAlternative(db.Model):
+    id = db.Column(db.Integer, primary_key=True)
+    text = db.Column(db.String(STRING_SIZE), nullable=False)
+    true_false = db.Column(db.Boolean, nullable=False, default=False)
+    mc_id = db.Column(db.Integer, db.ForeignKey("mc_question.id"), nullable=False)
+
+    mc = db.relationship("MCQuestion", foreign_keys=[mc_id], uselist=False)
+
+    def __init__(self, text, true_false, mc_id):
+        self.text = text
+        self.true_false = true_false
+        self.mc_id = mc_id
+
+
+class AnsweredQuestion(db.Model):
+    id = db.Column(db.Integer, primary_key=True)
+    data = db.Column(db.Text, nullable=False)
+    score = db.Column(db.Integer, nullable=False)
+    question_id = db.Column(db.Integer, db.ForeignKey("question.id"), nullable=False)
+    team_id = db.Column(db.Integer, db.ForeignKey("team.id"), nullable=False)
+
+    question = db.relationship("Question", foreign_keys=[question_id], uselist=False)
+    team = db.relationship("Team", foreign_keys=[team_id], uselist=False)
+
+    def __init__(self, data, score, question_id, team_id):
+        self.data = data
+        self.score = score
+        self.question_id = question_id
+        self.team_id = team_id