diff --git a/server/app/core/parsers.py b/server/app/core/parsers.py
index 71f8fdee352c3fe88831124b0c8907fcbc51f505..606462d0e84b29a7387a8ce2b0d0748ede0c04b6 100644
--- a/server/app/core/parsers.py
+++ b/server/app/core/parsers.py
@@ -97,11 +97,13 @@ component_parser.add_argument("x", type=str, default=None, location="json")
 component_parser.add_argument("y", type=int, default=None, location="json")
 component_parser.add_argument("w", type=int, default=None, location="json")
 component_parser.add_argument("h", type=int, default=None, location="json")
-component_parser.add_argument("data", type=dict, default=None, location="json")
+# component_parser.add_argument("data", type=dict, default=None, location="json")
 
 component_create_parser = component_parser.copy()
-component_create_parser.replace_argument("data", type=dict, required=True, location="json")
+# component_create_parser.replace_argument("data", type=dict, required=True, location="json")
 component_create_parser.add_argument("type_id", type=int, required=True, location="json")
+component_create_parser.add_argument("text", type=str, required=False, location="json")
+component_create_parser.add_argument("image_id", type=str, required=False, location="json")
 
 login_code_parser = reqparse.RequestParser()
 login_code_parser.add_argument("code", type=str, location="json")
diff --git a/server/app/core/schemas.py b/server/app/core/schemas.py
index 79bdbc1c48fd7460e85fe18f13a744f45a0a57e1..6f128ec8a414b64418a36e121c9010f61905829b 100644
--- a/server/app/core/schemas.py
+++ b/server/app/core/schemas.py
@@ -1,3 +1,4 @@
+from marshmallow.decorators import pre_load
 import app.database.models as models
 from app.core import ma
 from marshmallow_sqlalchemy import fields
@@ -154,6 +155,8 @@ class ComponentSchema(BaseSchema):
     y = ma.auto_field()
     w = ma.auto_field()
     h = ma.auto_field()
-    data = ma.Function(lambda obj: obj.data)
     slide_id = ma.auto_field()
     type_id = ma.auto_field()
+
+    text = fields.fields.String()
+    image_id = fields.fields.Integer()
diff --git a/server/app/database/__init__.py b/server/app/database/__init__.py
index 784c006b8fab59ca1dcc9e6dbac8ebffe91cb013..e0c78ad3af3f3376fdecdae4eae219aa1c62be24 100644
--- a/server/app/database/__init__.py
+++ b/server/app/database/__init__.py
@@ -6,6 +6,7 @@ from flask_sqlalchemy.model import Model
 from sqlalchemy import Column, DateTime, Text
 from sqlalchemy.sql import func
 from sqlalchemy.types import TypeDecorator
+from sqlalchemy import event
 
 
 class Base(Model):
diff --git a/server/app/database/controller/add.py b/server/app/database/controller/add.py
index 1dbcf44230e508c3d51b3aa8faa4ba2c84e97914..db4133e5a62f97370ed17e08b4688fc62fe03925 100644
--- a/server/app/database/controller/add.py
+++ b/server/app/database/controller/add.py
@@ -5,7 +5,7 @@ This file contains functionality to add data to the database.
 from sqlalchemy.orm.session import sessionmaker
 import app.core.http_codes as codes
 from app.core import db
-from app.database.controller import utils
+from app.database.controller import edit, utils
 from app.database.models import (
     Blacklist,
     City,
@@ -13,6 +13,7 @@ from app.database.models import (
     Competition,
     Component,
     ComponentType,
+    ImageComponent,
     Media,
     MediaType,
     Question,
@@ -22,11 +23,13 @@ from app.database.models import (
     Role,
     Slide,
     Team,
+    TextComponent,
     User,
     ViewType,
 )
 from flask_restx import abort
 from sqlalchemy import exc
+from sqlalchemy.orm import with_polymorphic
 
 
 def db_add(item):
@@ -50,85 +53,23 @@ def db_add(item):
     return item
 
 
-def blacklist(jti):
-    """ Adds a blacklist to the database. """
-
-    return db_add(Blacklist(jti))
-
-
-def mediaType(name):
-    """ Adds a media type to the database. """
-
-    return db_add(MediaType(name))
-
-
-def questionType(name):
-    """ Adds a question type to the database. """
-
-    return db_add(QuestionType(name))
-
-
-def componentType(name):
-    """ Adds a component type to the database. """
-
-    return db_add(ComponentType(name))
-
-
-def viewType(name):
-    """ Adds a view type to the database. """
-
-    return db_add(ViewType(name))
-
-
-def role(name):
-    """ Adds a role to the database. """
-
-    return db_add(Role(name))
-
-
-def city(name):
-    """ Adds a city to the database. """
-
-    return db_add(City(name))
-
-
-def component(type_id, slide_id, data, x=0, y=0, w=0, h=0):
+def component(type_id, slide_id, x=0, y=0, w=0, h=0, **data):
     """
     Adds a component to the slide at the specified coordinates with the
     provided size and data .
     """
 
-    return db_add(Component(slide_id, type_id, data, x, y, w, h))
-
-
-def image(filename, user_id):
-    """
-    Adds an image to the database and keeps track of who called the function.
-    """
-
-    return db_add(Media(filename, 1, user_id))
-
-
-def user(email, password, role_id, city_id, name=None):
-    """ Adds a user to the database using the provided arguments. """
-
-    return db_add(User(email, password, role_id, city_id, name))
-
-
-def question(name, total_score, type_id, slide_id):
-    """
-    Adds a question to the specified slide using the provided arguments.
-    """
-
-    return db_add(Question(name, total_score, type_id, slide_id))
-
-
-def question_alternative(text, value, question_id):
-    return db_add(QuestionAlternative(text, value, question_id))
+    if type_id == 1:
+        item = db_add(TextComponent(slide_id, type_id, x, y, w, h))
+        item.text = data.get("text")
+    elif type_id == 2:
+        item = db_add(ImageComponent(slide_id, type_id, x, y, w, h))
+        item.image_id = data.get("image_id")
+    else:
+        abort(codes.BAD_REQUEST, f"Invalid type_id{type_id}")
 
-
-def question_answer(data, score, question_id, team_id):
-    return db_add(QuestionAnswer(data, score, question_id, team_id))
+    item = utils.commit_and_refresh(item)
+    return item
 
 
 def code(pointer, view_type_id):
@@ -216,3 +157,75 @@ def _competition_no_slides(name, year, city_id, font=None):
 
     item_competition = utils.refresh(item_competition)
     return item_competition
+
+
+def blacklist(jti):
+    """ Adds a blacklist to the database. """
+
+    return db_add(Blacklist(jti))
+
+
+def mediaType(name):
+    """ Adds a media type to the database. """
+
+    return db_add(MediaType(name))
+
+
+def questionType(name):
+    """ Adds a question type to the database. """
+
+    return db_add(QuestionType(name))
+
+
+def componentType(name):
+    """ Adds a component type to the database. """
+
+    return db_add(ComponentType(name))
+
+
+def viewType(name):
+    """ Adds a view type to the database. """
+
+    return db_add(ViewType(name))
+
+
+def role(name):
+    """ Adds a role to the database. """
+
+    return db_add(Role(name))
+
+
+def city(name):
+    """ Adds a city to the database. """
+
+    return db_add(City(name))
+
+
+def image(filename, user_id):
+    """
+    Adds an image to the database and keeps track of who called the function.
+    """
+
+    return db_add(Media(filename, 1, user_id))
+
+
+def user(email, password, role_id, city_id, name=None):
+    """ Adds a user to the database using the provided arguments. """
+
+    return db_add(User(email, password, role_id, city_id, name))
+
+
+def question(name, total_score, type_id, slide_id):
+    """
+    Adds a question to the specified slide using the provided arguments.
+    """
+
+    return db_add(Question(name, total_score, type_id, slide_id))
+
+
+def question_alternative(text, value, question_id):
+    return db_add(QuestionAlternative(text, value, question_id))
+
+
+def question_answer(data, score, question_id, team_id):
+    return db_add(QuestionAnswer(data, score, question_id, team_id))
diff --git a/server/app/database/controller/copy.py b/server/app/database/controller/copy.py
index 79a4df0f4a7f308b7bc40b5b9ab20e61423ffb14..8e0a39103ecbc195a76f41357ef4ef643ed1740a 100644
--- a/server/app/database/controller/copy.py
+++ b/server/app/database/controller/copy.py
@@ -41,7 +41,6 @@ def _component(item_component, item_slide_new):
     add.component(
         item_component.type_id,
         item_slide_new.id,
-        item_component.data,
         item_component.x,
         item_component.y,
         item_component.w,
diff --git a/server/app/database/controller/get.py b/server/app/database/controller/get.py
index 96405b5ad28584bfb62268da894af9dd27a533a8..14b2714bacf22fde56646d6921e42629cd50bc9a 100644
--- a/server/app/database/controller/get.py
+++ b/server/app/database/controller/get.py
@@ -2,17 +2,20 @@
 This file contains functionality to get data from the database.
 """
 
+from sqlalchemy.orm.util import with_polymorphic
 from app.core import db
 from app.core import http_codes as codes
 from app.database.models import (
     Code,
     Competition,
     Component,
+    ImageComponent,
     Question,
     QuestionAlternative,
     QuestionAnswer,
     Slide,
     Team,
+    TextComponent,
     User,
 )
 from sqlalchemy.orm import joinedload, subqueryload
@@ -200,7 +203,15 @@ def component(competition_id, slide_id, component_id):
     join_competition = Competition.id == Slide.competition_id
     join_slide = Slide.id == Component.slide_id
     filters = (Competition.id == competition_id) & (Slide.id == slide_id) & (Component.id == component_id)
-    return Component.query.join(Competition, join_competition).join(Slide, join_slide).filter(filters).first_extended()
+
+    poly = with_polymorphic(Component, [TextComponent, ImageComponent])
+    return (
+        db.session.query(poly)
+        .join(Competition, join_competition)
+        .join(Slide, join_slide)
+        .filter(filters)
+        .first_extended()
+    )
 
 
 def component_list(competition_id, slide_id):
diff --git a/server/app/database/models.py b/server/app/database/models.py
index cded9ddf7aa00d2b5545a2ae5f40cf28eecba209..625370657c1ef5b2a57993667a7f1fcb6e741b14 100644
--- a/server/app/database/models.py
+++ b/server/app/database/models.py
@@ -2,6 +2,8 @@ from app.core import bcrypt, db
 from app.database import Dictionary
 from sqlalchemy.ext.hybrid import hybrid_method, hybrid_property
 
+from app.database.types import ID_IMAGE_COMPONENT, ID_TEXT_COMPONENT
+
 STRING_SIZE = 254
 
 
@@ -190,20 +192,34 @@ class Component(db.Model):
     y = db.Column(db.Integer, nullable=False, default=0)
     w = db.Column(db.Integer, nullable=False, default=1)
     h = db.Column(db.Integer, nullable=False, default=1)
-    data = db.Column(Dictionary())
     slide_id = db.Column(db.Integer, db.ForeignKey("slide.id"), nullable=False)
     type_id = db.Column(db.Integer, db.ForeignKey("component_type.id"), nullable=False)
 
-    def __init__(self, slide_id, type_id, data, x=0, y=0, w=1, h=1):
+    __mapper_args__ = {"polymorphic_on": type_id}
+
+    def __init__(self, slide_id, type_id, x=0, y=0, w=1, h=1):
         self.x = x
         self.y = y
         self.w = w
         self.h = h
-        self.data = data
         self.slide_id = slide_id
         self.type_id = type_id
 
 
+class TextComponent(Component):
+    text = db.Column(db.Text, default="", nullable=False)
+
+    # __tablename__ = None
+    __mapper_args__ = {"polymorphic_identity": ID_TEXT_COMPONENT}
+
+
+class ImageComponent(Component):
+    image_id = db.Column(db.Integer, db.ForeignKey("media.id"), nullable=True)
+
+    # __tablename__ = None
+    __mapper_args__ = {"polymorphic_identity": ID_IMAGE_COMPONENT}
+
+
 class Code(db.Model):
     table_args = (db.UniqueConstraint("pointer", "type"),)
     id = db.Column(db.Integer, primary_key=True)
diff --git a/server/app/database/types.py b/server/app/database/types.py
new file mode 100644
index 0000000000000000000000000000000000000000..236e50f5278d03684f2cbdcc05c2e7637e21a057
--- /dev/null
+++ b/server/app/database/types.py
@@ -0,0 +1,2 @@
+ID_TEXT_COMPONENT = 1
+ID_IMAGE_COMPONENT = 2
diff --git a/server/populate.py b/server/populate.py
index 9ca3c95e7f683decfac5e9f697d0cfdbff958e1e..71538f1513048f9e9cc64f39ef34f0df221db293 100644
--- a/server/populate.py
+++ b/server/populate.py
@@ -82,7 +82,7 @@ def _add_items():
                 y = random.randrange(1, 500)
                 w = random.randrange(150, 400)
                 h = random.randrange(150, 400)
-                dbc.add.component(1, item_slide.id, {"text": f"hej{k}"}, x, y, w, h)
+                dbc.add.component(1, item_slide.id, x, y, w, h, text=f"hej{k}")
 
         # item_slide = dbc.add.slide(item_comp)
         # item_slide.title = f"Slide {len(item_comp.slides)}"