diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..5f9bb7d6d4966cde2b06f26d5f668b449a925dcb
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,33 @@
+.idea/
+.DS_Store
+*.sqlite3
+
+__pycache__
+# dependencies
+*/node_modules
+/.pnp
+.pnp.js
+
+# testing
+/coverage
+
+# production
+/build
+*/build
+
+# misc
+.env.local
+.env.development.local
+.env.test.local
+.env.production.local
+.env
+
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+
+*.eslintcache
+*/media/account/images/
+
+solar/django_static
+pypi/*/
diff --git a/Pipfile b/Pipfile
index 71e4f7cbf92007f3a0f0ef426b670c974a6d7e7c..8e60571b6ab19789cf8ddfbda397be30e2485890 100644
--- a/Pipfile
+++ b/Pipfile
@@ -4,6 +4,11 @@ verify_ssl = true
 name = "pypi"
 
 [packages]
+django = "*"
+django-cors-headers = "*"
+djangorestframework = "*"
+pillow = "*"
+uwsgi = "*"
 
 [dev-packages]
 
diff --git a/Pipfile.lock b/Pipfile.lock
new file mode 100644
index 0000000000000000000000000000000000000000..9d8d6a14c906b3b26240170a8390306e493429f0
--- /dev/null
+++ b/Pipfile.lock
@@ -0,0 +1,122 @@
+{
+    "_meta": {
+        "hash": {
+            "sha256": "f1ffc1e60d515d604136eec07eea7e16c697c4e5529414b3b41eb9a672871223"
+        },
+        "pipfile-spec": 6,
+        "requires": {
+            "python_version": "3.9"
+        },
+        "sources": [
+            {
+                "name": "pypi",
+                "url": "https://pypi.org/simple",
+                "verify_ssl": true
+            }
+        ]
+    },
+    "default": {
+        "asgiref": {
+            "hashes": [
+                "sha256:4ef1ab46b484e3c706329cedeff284a5d40824200638503f5768edb6de7d58e9",
+                "sha256:ffc141aa908e6f175673e7b1b3b7af4fdb0ecb738fc5c8b88f69f055c2415214"
+            ],
+            "markers": "python_version >= '3.6'",
+            "version": "==3.4.1"
+        },
+        "django": {
+            "hashes": [
+                "sha256:51284300f1522ffcdb07ccbdf676a307c6678659e1284f0618e5a774127a6a08",
+                "sha256:e22c9266da3eec7827737cde57694d7db801fedac938d252bf27377cec06ed1b"
+            ],
+            "index": "pypi",
+            "version": "==3.2.9"
+        },
+        "django-cors-headers": {
+            "hashes": [
+                "sha256:cba6e99659abb0e47cc4aaabb8fcde03f193e6bb3b92ba47c5185ec4cedc5d9e",
+                "sha256:cd6f4360f5246569c149dc1c40c907c191f1ec45551e10d2a2e2e68512652f78"
+            ],
+            "index": "pypi",
+            "version": "==3.10.0"
+        },
+        "djangorestframework": {
+            "hashes": [
+                "sha256:6d1d59f623a5ad0509fe0d6bfe93cbdfe17b8116ebc8eda86d45f6e16e819aaf",
+                "sha256:f747949a8ddac876e879190df194b925c177cdeb725a099db1460872f7c0a7f2"
+            ],
+            "index": "pypi",
+            "version": "==3.12.4"
+        },
+        "pillow": {
+            "hashes": [
+                "sha256:066f3999cb3b070a95c3652712cffa1a748cd02d60ad7b4e485c3748a04d9d76",
+                "sha256:0a0956fdc5defc34462bb1c765ee88d933239f9a94bc37d132004775241a7585",
+                "sha256:0b052a619a8bfcf26bd8b3f48f45283f9e977890263e4571f2393ed8898d331b",
+                "sha256:1394a6ad5abc838c5cd8a92c5a07535648cdf6d09e8e2d6df916dfa9ea86ead8",
+                "sha256:1bc723b434fbc4ab50bb68e11e93ce5fb69866ad621e3c2c9bdb0cd70e345f55",
+                "sha256:244cf3b97802c34c41905d22810846802a3329ddcb93ccc432870243211c79fc",
+                "sha256:25a49dc2e2f74e65efaa32b153527fc5ac98508d502fa46e74fa4fd678ed6645",
+                "sha256:2e4440b8f00f504ee4b53fe30f4e381aae30b0568193be305256b1462216feff",
+                "sha256:3862b7256046fcd950618ed22d1d60b842e3a40a48236a5498746f21189afbbc",
+                "sha256:3eb1ce5f65908556c2d8685a8f0a6e989d887ec4057326f6c22b24e8a172c66b",
+                "sha256:3f97cfb1e5a392d75dd8b9fd274d205404729923840ca94ca45a0af57e13dbe6",
+                "sha256:493cb4e415f44cd601fcec11c99836f707bb714ab03f5ed46ac25713baf0ff20",
+                "sha256:4acc0985ddf39d1bc969a9220b51d94ed51695d455c228d8ac29fcdb25810e6e",
+                "sha256:5503c86916d27c2e101b7f71c2ae2cddba01a2cf55b8395b0255fd33fa4d1f1a",
+                "sha256:5b7bb9de00197fb4261825c15551adf7605cf14a80badf1761d61e59da347779",
+                "sha256:5e9ac5f66616b87d4da618a20ab0a38324dbe88d8a39b55be8964eb520021e02",
+                "sha256:620582db2a85b2df5f8a82ddeb52116560d7e5e6b055095f04ad828d1b0baa39",
+                "sha256:62cc1afda735a8d109007164714e73771b499768b9bb5afcbbee9d0ff374b43f",
+                "sha256:70ad9e5c6cb9b8487280a02c0ad8a51581dcbbe8484ce058477692a27c151c0a",
+                "sha256:72b9e656e340447f827885b8d7a15fc8c4e68d410dc2297ef6787eec0f0ea409",
+                "sha256:72cbcfd54df6caf85cc35264c77ede902452d6df41166010262374155947460c",
+                "sha256:792e5c12376594bfcb986ebf3855aa4b7c225754e9a9521298e460e92fb4a488",
+                "sha256:7b7017b61bbcdd7f6363aeceb881e23c46583739cb69a3ab39cb384f6ec82e5b",
+                "sha256:81f8d5c81e483a9442d72d182e1fb6dcb9723f289a57e8030811bac9ea3fef8d",
+                "sha256:82aafa8d5eb68c8463b6e9baeb4f19043bb31fefc03eb7b216b51e6a9981ae09",
+                "sha256:84c471a734240653a0ec91dec0996696eea227eafe72a33bd06c92697728046b",
+                "sha256:8c803ac3c28bbc53763e6825746f05cc407b20e4a69d0122e526a582e3b5e153",
+                "sha256:93ce9e955cc95959df98505e4608ad98281fff037350d8c2671c9aa86bcf10a9",
+                "sha256:9a3e5ddc44c14042f0844b8cf7d2cd455f6cc80fd7f5eefbe657292cf601d9ad",
+                "sha256:a4901622493f88b1a29bd30ec1a2f683782e57c3c16a2dbc7f2595ba01f639df",
+                "sha256:a5a4532a12314149d8b4e4ad8ff09dde7427731fcfa5917ff16d0291f13609df",
+                "sha256:b8831cb7332eda5dc89b21a7bce7ef6ad305548820595033a4b03cf3091235ed",
+                "sha256:b8e2f83c56e141920c39464b852de3719dfbfb6e3c99a2d8da0edf4fb33176ed",
+                "sha256:c70e94281588ef053ae8998039610dbd71bc509e4acbc77ab59d7d2937b10698",
+                "sha256:c8a17b5d948f4ceeceb66384727dde11b240736fddeda54ca740b9b8b1556b29",
+                "sha256:d82cdb63100ef5eedb8391732375e6d05993b765f72cb34311fab92103314649",
+                "sha256:d89363f02658e253dbd171f7c3716a5d340a24ee82d38aab9183f7fdf0cdca49",
+                "sha256:d99ec152570e4196772e7a8e4ba5320d2d27bf22fdf11743dd882936ed64305b",
+                "sha256:ddc4d832a0f0b4c52fff973a0d44b6c99839a9d016fe4e6a1cb8f3eea96479c2",
+                "sha256:e3dacecfbeec9a33e932f00c6cd7996e62f53ad46fbe677577394aaa90ee419a",
+                "sha256:eb9fc393f3c61f9054e1ed26e6fe912c7321af2f41ff49d3f83d05bacf22cc78"
+            ],
+            "index": "pypi",
+            "version": "==8.4.0"
+        },
+        "pytz": {
+            "hashes": [
+                "sha256:3672058bc3453457b622aab7a1c3bfd5ab0bdae451512f6cf25f64ed37f5b87c",
+                "sha256:acad2d8b20a1af07d4e4c9d2e9285c5ed9104354062f275f3fcd88dcef4f1326"
+            ],
+            "version": "==2021.3"
+        },
+        "sqlparse": {
+            "hashes": [
+                "sha256:0c00730c74263a94e5a9919ade150dfc3b19c574389985446148402998287dae",
+                "sha256:48719e356bb8b42991bdbb1e8b83223757b93789c00910a616a071910ca4a64d"
+            ],
+            "markers": "python_version >= '3.5'",
+            "version": "==0.4.2"
+        },
+        "uwsgi": {
+            "hashes": [
+                "sha256:88ab9867d8973d8ae84719cf233b7dafc54326fcaec89683c3f9f77c002cdff9"
+            ],
+            "index": "pypi",
+            "version": "==2.0.20"
+        }
+    },
+    "develop": {}
+}
diff --git a/the_social_network/core/__init__.py b/the_social_network/core/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..f709468b08cb08b3724248bc7b5b3485e59807c5
--- /dev/null
+++ b/the_social_network/core/__init__.py
@@ -0,0 +1,10 @@
+from enum import Enum
+
+
+class Operations(Enum):
+    """
+    This enum is the distribute all possible operations globally in this app.
+    """
+    REGISTER = "register"
+    LOGIN = "login"
+    LOGOUT = "logout"
diff --git a/the_social_network/core/admin.py b/the_social_network/core/admin.py
new file mode 100644
index 0000000000000000000000000000000000000000..ef201f8551aaad861f919057223b1c10b3fb9800
--- /dev/null
+++ b/the_social_network/core/admin.py
@@ -0,0 +1,78 @@
+from django.contrib import admin
+
+from .models import *
+
+
+class RelationshipInline(admin.StackedInline):
+    """
+    This is the stackable inline representation of the relationships.
+    It will use the from_account as an foreign key.
+    It will not display any more then relationships then necessary (extra = 0)
+    """
+    model = Relationship
+    fk_name = 'from_account'
+    extra = 0
+
+
+class StatementsInline(admin.StackedInline):
+    """
+    This is the stackable inline representation of the statements.
+    It will not display any more then statements then necessary (extra = 0)
+    """
+    model = Statement
+    extra = 0
+
+
+class AccountAdmin(admin.ModelAdmin):
+    """
+    This is the admin for the accounts.
+    This will add the relationships of an account to admin interface.
+    This will add content of an account to admin interface.
+    """
+    inlines = [RelationshipInline, StatementsInline]
+
+
+class StatementHashtagInline(admin.StackedInline):
+    """
+    This is the stackable representation of the tagging of an statement with an hashtag.
+    """
+    model = HashtagTagging
+    fk_name = 'statement'
+    extra = 0
+
+
+class StatementAccountInline(admin.StackedInline):
+    """
+    This is the stackable representation of the mentioning of an account within an statement.
+    """
+    model = AccountTagging
+    fk_name = 'statement'
+    extra = 0
+
+
+class StatementReactionInline(admin.StackedInline):
+    """
+    This is the stackable representation of the reaction relation between statements.
+    """
+    model = Reaction
+    fk_name = 'parent'
+    extra = 0
+
+
+class StatementAdmin(admin.ModelAdmin):
+    """
+    This ist the admin for the statements.
+    It will add the tagging of statements with hashtags to the admin interface.
+    """
+    inlines = [StatementHashtagInline,
+               StatementAccountInline, StatementReactionInline]
+
+
+admin.site.register(Account, AccountAdmin)
+admin.site.register(Relationship)
+
+admin.site.register(Hashtag)
+admin.site.register(HashtagTagging)
+admin.site.register(AccountTagging)
+admin.site.register(Reaction)
+admin.site.register(Statement, StatementAdmin)
diff --git a/the_social_network/core/apps.py b/the_social_network/core/apps.py
new file mode 100644
index 0000000000000000000000000000000000000000..d180014e8bb2febb22415aaca9e2fe95bc6c5eec
--- /dev/null
+++ b/the_social_network/core/apps.py
@@ -0,0 +1,5 @@
+from django.apps import AppConfig
+
+
+class AuthenticationConfig(AppConfig):
+    name = 'core'
diff --git a/the_social_network/core/migrations/0001_initial.py b/the_social_network/core/migrations/0001_initial.py
new file mode 100644
index 0000000000000000000000000000000000000000..7ac9b1f12f78275b221441e1079c533471a2ca89
--- /dev/null
+++ b/the_social_network/core/migrations/0001_initial.py
@@ -0,0 +1,113 @@
+# Generated by Django 3.1.2 on 2020-12-02 11:13
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+    initial = True
+
+    dependencies = [
+        ('auth', '0012_alter_user_first_name_max_length'),
+    ]
+
+    operations = [
+        migrations.CreateModel(
+            name='Account',
+            fields=[
+                ('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, primary_key=True, serialize=False, to='auth.user')),
+                ('image', models.ImageField(default='account/default/Argunaut.png', upload_to='account/images')),
+                ('biography', models.CharField(default='Hey there, nice to meet you!', max_length=1000))
+            ],
+        ),
+        migrations.CreateModel(
+            name='Relationship',
+            fields=[
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('created', models.DateTimeField(auto_now_add=True, db_index=True)),
+                ('from_account', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='from_account', to='core.account')),
+                ('to_account', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='to_account', to='core.account')),
+            ],
+            options={
+                'ordering': ('-created',),
+            },
+        ),
+        migrations.AddField(
+            model_name='account',
+            name='related_to',
+            field=models.ManyToManyField(blank=True, default=None, related_name='related_by', through='core.Relationship', to='core.Account'),
+        ),
+        migrations.CreateModel(
+            name='Statement',
+            fields=[
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('content', models.CharField(max_length=120)),
+                ('created', models.DateTimeField(auto_now_add=True, db_index=True)),
+                ('author', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='core.account')),
+            ],
+            options={
+                'ordering': ('-created',),
+            },
+        ),
+        migrations.CreateModel(
+            name='Hashtag',
+            fields=[
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('tag', models.CharField(max_length=30)),
+                ('created', models.DateTimeField(auto_now_add=True, db_index=True)),
+            ],
+        ),
+        migrations.CreateModel(
+            name='HashtagTagging',
+            fields=[
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('created', models.DateTimeField(auto_now_add=True, db_index=True)),
+                ('hashtag', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='hashtag', to='core.hashtag')),
+                ('statement', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='core.statement')),
+            ],
+            options={
+                'ordering': ('-created',),
+            },
+        ),
+        migrations.AddField(
+            model_name='statement',
+            name='tagged',
+            field=models.ManyToManyField(blank=True, default=None, related_name='tags', through='core.HashtagTagging', to='core.Hashtag'),
+        ),
+        migrations.CreateModel(
+            name='AccountTagging',
+            fields=[
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('created', models.DateTimeField(auto_now_add=True, db_index=True)),
+                ('account', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='account', to='core.account')),
+                ('statement', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='core.statement')),
+            ],
+            options={
+                'ordering': ('-created',),
+            },
+        ),
+        migrations.AddField(
+            model_name='statement',
+            name='mentioned',
+            field=models.ManyToManyField(blank=True, default=None, related_name='mentions', through='core.AccountTagging', to='core.Account'),
+        ),
+        migrations.CreateModel(
+            name='Reaction',
+            fields=[
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('created', models.DateTimeField(auto_now_add=True, db_index=True)),
+                ('vote', models.PositiveSmallIntegerField(choices=[(1, 'like'), (2, 'dislike')], default=1)),
+                ('child', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='child', to='core.statement')),
+                ('parent', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='parent', to='core.statement')),
+            ],
+            options={
+                'ordering': ('-created',),
+            },
+        ),
+        migrations.AddField(
+            model_name='statement',
+            name='reactions',
+            field=models.ManyToManyField(blank=True, default=None, related_name='reaction_of', through='core.Reaction', to='core.Statement'),
+        ),
+    ]
diff --git a/the_social_network/core/migrations/0002_auto_20211111_1220.py b/the_social_network/core/migrations/0002_auto_20211111_1220.py
new file mode 100644
index 0000000000000000000000000000000000000000..4eed0fd51fd2f2f37d8d8e36b874c37792e02882
--- /dev/null
+++ b/the_social_network/core/migrations/0002_auto_20211111_1220.py
@@ -0,0 +1,43 @@
+# Generated by Django 3.2.9 on 2021-11-11 12:20
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('core', '0001_initial'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='accounttagging',
+            name='id',
+            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
+        ),
+        migrations.AlterField(
+            model_name='hashtag',
+            name='id',
+            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
+        ),
+        migrations.AlterField(
+            model_name='hashtagtagging',
+            name='id',
+            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
+        ),
+        migrations.AlterField(
+            model_name='reaction',
+            name='id',
+            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
+        ),
+        migrations.AlterField(
+            model_name='relationship',
+            name='id',
+            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
+        ),
+        migrations.AlterField(
+            model_name='statement',
+            name='id',
+            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
+        ),
+    ]
diff --git a/the_social_network/core/migrations/__init__.py b/the_social_network/core/migrations/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/the_social_network/core/models.py b/the_social_network/core/models.py
new file mode 100644
index 0000000000000000000000000000000000000000..34ef3619b4ca82310e325dca043cdc3509c68808
--- /dev/null
+++ b/the_social_network/core/models.py
@@ -0,0 +1,418 @@
+import logging
+from typing import List, Optional, Tuple
+import re
+
+from django.contrib.auth.models import User
+from django.core.files.uploadedfile import InMemoryUploadedFile
+from django.db import models
+from django.apps import apps
+
+logger = logging.getLogger(__name__)
+
+
+class Statement(models.Model):
+    """
+    This model represents an statement of an specific account.
+    """
+    author = models.ForeignKey('core.Account', on_delete=models.CASCADE)
+    content = models.CharField(max_length=120, blank=False)
+    created = models.DateTimeField(auto_now_add=True, db_index=True)
+    # Add an hashtag between statements and hashtags  over the tagging model
+    tagged = models.ManyToManyField('Hashtag',
+                                    blank=True,
+                                    through='HashtagTagging',
+                                    symmetrical=False,
+                                    related_name='tags',
+                                    default=None)
+    mentioned = models.ManyToManyField('core.Account',
+                                       blank=True,
+                                       through='AccountTagging',
+                                       symmetrical=False,
+                                       related_name='mentions',
+                                       default=None)
+    reactions = models.ManyToManyField('self',
+                                       blank=True,
+                                       through='Reaction',
+                                       symmetrical=False,
+                                       related_name='reaction_of',
+                                       default=None)
+
+    def __str__(self):
+        return "{author} says: {content}".format(author=self.author.user.username, content=self.content)
+
+    class Meta:
+        ordering = ('-created',)
+
+    def save(self, *args, **kwargs) -> None:
+        """
+        This method adds hashtags relations after the statement is saved.
+        Save is ran after update or create.
+
+        :param args: Not used.
+        :param kwargs: Not used.
+        :return: None
+        """
+        super(Statement, self).save(*args, **kwargs)
+        # resolve hashtags after saving the statement
+        used_hashtags: List[str] = self.__extract_hashtags()
+        for used_hashtag in used_hashtags:
+            result: Tuple[Hashtag, bool] = Hashtag.objects.get_or_create(tag=used_hashtag)
+            hashtag: Hashtag = result[0]
+            self.add_hashtag(hashtag=hashtag)
+        used_mentions: List[str] = self.__extract_mentioning()
+        # resolve mentions after saving the statement
+        for used_mention in used_mentions:
+            account: 'core.Account' = apps.get_model("core", "Account").objects.filter(
+                user__username=used_mention).first()
+            if account:
+                self.add_mentioning(account=account)
+
+    def add_reaction(self, reaction_statement: 'Statement', vote: int) -> Tuple['Reaction', bool]:
+        """
+        This method adds an reaction to the calling statement.
+        :param reaction_statement:  The statement to be added as an reaction.
+        :param vote: The vote of the reaction regarding the parent element. (Like 1, Dislike 0)
+        :return: The reaction as well as the status if the reaction was already existing.
+        """
+        reaction, created = Reaction.objects.get_or_create(
+            parent=self,
+            child=reaction_statement,
+            vote=vote
+        )
+        return reaction, created
+
+    def remove_as_reaction(self) -> bool:
+        """
+        This method removes the calling statement as an reaction for the parent.
+        :return: Status if the reaction was deleted or not.
+        """
+        deleted, _ = Reaction.objects.filter(child=self).delete()
+        return deleted
+
+    def get_reactions(self) -> List['Reaction']:
+        """
+        This method returns all reaction of the calling statement.
+        :return: List of all reactions to the calling statement
+        """
+        return list(Reaction.objects.filter(parent=self))
+
+    def get_reaction_to_parent(self) -> Optional[List['Reaction']]:
+        """
+        This method returns the reaction relation to the parent if this statement is used as an reaction.
+        :return: Reaction to the parent if there is one. Else none.
+        """
+        reaction: List[Reaction] = Reaction.objects.filter(child=self)
+        if len(reaction) == 0:
+            return None
+        # todo: is there a way to use the instance and not a list in the reaction serialize, if so, also change frontend
+        return reaction
+
+    def get_parent(self) -> Optional['Statement']:
+        """
+        This method is for getting the parent if of an statement if this statement is an reaction.
+        :return: The parent statement of the reaction. If there is no parent then None is returned.
+        """
+        parents: List['Statement'] = self.reaction_of.all()
+        if len(parents) == 0:
+            return None
+        return parents[0]
+
+    def __extract_hashtags(self) -> List[str]:
+        """
+        This method extracts the hashtag of the content.
+        Hashtags are alpha numeric words.
+
+        :return: List of all hashtags used in the content of the statement.
+        """
+        return re.findall(r"#(\w+)", self.content)
+
+    def add_hashtag(self, hashtag: 'Hashtag'):
+        """
+        This method is for adding an hashtag to the corresponding statement.
+        :param hashtag: The hashtag to be added.
+        :return: True if the hashtag was created, false otherwise.
+        """
+        tagging, created = HashtagTagging.objects.get_or_create(statement=self, hashtag=hashtag)
+        return created
+
+    def get_hashtags(self) -> List['Hashtag']:
+        """
+        This method is to get all hashtags of the calling statement.
+
+        :return: List of all hashtags of the calling statement.
+        """
+        return list(self.tagged.all())
+
+    def remove_hashtag(self, hashtag: 'Hashtag'):
+        """
+        This method is used to delete an specific hashtag for the calling statement.
+
+        :param hashtag: The hashtag to be deleted.
+        :return: True if the hashtag was deleted, false else.
+        """
+        deleted: bool = HashtagTagging.objects.filter(
+            statement=self,
+            hashtag=hashtag
+        ).delete()
+        return deleted
+
+    def __extract_mentioning(self) -> List['core.Account']:
+        """
+        This method extracts the mentions of accounts in the calling statement.
+        Accounts names are alpha numeric words.
+
+        :return: List of all accounts mentioned in the calling statement.
+        """
+        return re.findall(r"@(\w+)", self.content)
+
+    def add_mentioning(self, account: 'core.Account'):
+        """
+        This method is for adding an mention of an account to the corresponding statement.
+        :param account: The account to be mentioned.
+        :return: True if the mention was created, false otherwise.
+        """
+        mentioning, created = AccountTagging.objects.get_or_create(statement=self, account=account)
+        return created
+
+    def get_mentioning(self) -> List['core.Account']:
+        """
+        This method is to get all accounts mentioned by the calling statement.
+
+        :return: List of all accounts mentioned by the calling statement.
+        """
+        return list(self.mentioned.all())
+
+    def remove_mentioning(self, account: 'core.Account'):
+        """
+        This method is used to delete an specific mentioning of an account for the calling statement.
+
+        :param account: The account to be unmentioned.
+        :return: True if the hashtag was deleted, false else.
+        """
+        deleted: bool = AccountTagging.objects.filter(
+            statement=self,
+            account=account
+        ).delete()
+        return deleted
+
+
+
+
+
+class Hashtag(models.Model):
+    """
+    This model represents an hashtag which can be added to specific contents.
+    """
+    tag = models.CharField(max_length=30, blank=False)
+    created = models.DateTimeField(auto_now_add=True, db_index=True)
+
+    def __str__(self):
+        return "#{tag}".format(tag=self.tag)
+
+
+class Tagging(models.Model):
+    """
+    This model represents the relation between any type of content and an hashtag
+    """
+    # What is the corresponding statement?
+    statement = models.ForeignKey(Statement, on_delete=models.CASCADE)
+    # When was this tagging created?
+    created = models.DateTimeField(auto_now_add=True, db_index=True)
+    # The default manager
+    objects = models.Manager()
+
+    class Meta:
+        abstract = True
+
+
+class HashtagTagging(Tagging):
+    """
+    This model is to represent the tagging of an statement with an hashtag.
+    """
+    # Which hashtag should be tagged?
+    hashtag = models.ForeignKey(Hashtag, related_name='hashtag', on_delete=models.CASCADE)
+
+    class Meta:
+        ordering = ('-created',)
+
+    def __str__(self):
+        return "{statement} tagged with {hashtag}".format(statement=self.statement, hashtag=self.hashtag)
+
+
+class AccountTagging(Tagging):
+    """
+    This model is to represent the mention of an account within an statement.
+    """
+    # Which account should be mentioned?
+    account = models.ForeignKey('core.Account', related_name='account', on_delete=models.CASCADE)
+
+    class Meta:
+        ordering = ('-created',)
+
+    def __str__(self):
+        return "{statement} mentioned {account}".format(statement=self.statement, account=self.account)
+
+
+class Reaction(models.Model):
+    # Who is the parent element of the reaction
+    parent = models.ForeignKey(Statement, related_name='parent', on_delete=models.CASCADE)
+    # Who is the reaction to the parent
+    child = models.ForeignKey(Statement, related_name='child', on_delete=models.CASCADE)
+    # When was this reaction created?
+    created = models.DateTimeField(auto_now_add=True, db_index=True)
+    # The relation must have an clear vote
+    vote = models.PositiveSmallIntegerField(
+        choices=[
+            (1, "like"),
+            (2, "dislike")
+        ],
+        default=1
+    )
+    # The default manager
+    objects = models.Manager()
+
+    class Meta:
+        ordering = ('-created',)
+
+    def __str__(self):
+        return "{child_author} {reaction}s >>{parent_content}<< of {parent_author} because >>{child_content}<<".format(
+            child_author=self.child.author.user.username,
+            child_content=self.child.content,
+            reaction=self.get_vote_display(),
+            parent_content=self.parent.content,
+            parent_author=self.parent.author.user.username,
+        )
+
+class Account(models.Model):
+    """
+    This model is for handling user accounts.
+    Therefore all data regarding an user is stored in this model.
+    The account is separated from the user since the default user model is used.
+    """
+    # Link the account to an user
+    user: User = models.OneToOneField(to=User,
+                                      on_delete=models.CASCADE,
+                                      primary_key=True)
+    # Add an relationship between accounts over the relationship model
+    related_to = models.ManyToManyField('self',
+                                        blank=True,
+                                        through='Relationship',
+                                        symmetrical=False,
+                                        related_name='related_by',
+                                        default=None)
+    # This is the image of the account
+    image = models.ImageField(upload_to='account/images',
+                              default='account/default/Argunaut.png')
+
+    biography = models.CharField(blank=False,
+                                 max_length=1000,
+                                 default="Hey there, nice to meet you!".format(user))
+
+    # The default manager
+    objects = models.Manager()
+
+    def __str__(self):
+        return "{username}".format(username=self.user.username)
+
+    def add_relationship(self, account: 'Account') -> bool:
+        """
+        This method adds an relationship for an instance.
+
+        :param account: Who should be added to an relation with the instance.
+        :return: True if the relationship was created, false otherwise.
+        """
+        relationship, created = Relationship.objects.get_or_create(
+            from_account=self,
+            to_account=account)
+        return created
+
+    def remove_relationship(self, account: 'Account'):
+        """
+        This method deletes the relationship to an other Account.
+
+        :param account: The user with whom the relationship is to be terminated.
+        :return: True if the relationship was deleted, false otherwise.
+        """
+        deleted: bool = Relationship.objects.filter(
+            from_account=self,
+            to_account=account).delete()
+        return deleted
+
+    def get_related_to(self) -> List['Account']:
+        """
+        This method returns all accounts related to the calling instance of this method.
+        Therefore this returns accounts the calling accounts relates to.
+
+        :return: All related accounts of the calling instance.
+        """
+        return list(self.related_to.filter(to_account__from_account=self))
+
+    def get_related_by(self) -> List['Account']:
+        """
+        This method returns all accounts who relates with the calling account.
+        
+        :return: All accounts who relates to the calling account.
+        """
+        return list(self.related_by.filter(from_account__to_account=self))
+
+    def get_statements(self) -> List['Statement']:
+        """
+        This method returns all all statements made by the calling account.
+
+        :return: All statements made by the calling account.
+        """
+        return list(self.statement_set.all())
+
+    def add_statement(self, content: str) -> Statement:
+        """
+        This methods add a statement for the calling account.
+
+        :param content: The content of the statement.
+        :return: The added statement.
+        """
+        statement: Statement = Statement(author=self, content=content)
+        self.statement_set.add(statement, bulk=False)
+        return statement
+
+    def update_image(self, new_image: InMemoryUploadedFile):
+        """
+        This method overwrites the image of an account.
+        If the account uses the default image the image will not be deleted.
+        :param new_image: The new image to be added for the account.
+        :return: Nothing
+        """
+        if self.image != "account/default/Argunaut.png":
+            self.image.delete(save=True)
+        self.image = new_image
+        self.save()
+
+    def update_biography(self, new_biography: str):
+        """
+        This method overwrites the biography of an account if it is not none.
+        :param new_biography: The new biography to be added for the account.
+        :return: Nothing
+        """
+        if new_biography and self.biography != new_biography:
+            self.biography = new_biography
+            self.save()
+
+
+class Relationship(models.Model):
+    """
+    This model handles relations between users.
+    By using this model it is possible to create more detailed relationships.
+    """
+    # Who wants to have an relation?
+    from_account = models.ForeignKey(Account, related_name='from_account', on_delete=models.CASCADE)
+    # To whom should a relationship be established?
+    to_account = models.ForeignKey(Account, related_name='to_account', on_delete=models.CASCADE)
+    # When was this relation created?
+    created = models.DateTimeField(auto_now_add=True, db_index=True)
+    # The default manager
+    objects = models.Manager()
+
+    class Meta:
+        ordering = ('-created',)
+
+    def __str__(self):
+        return "{from_user} related to {to_user}".format(from_user=self.from_account, to_user=self.to_account)
\ No newline at end of file
diff --git a/the_social_network/core/serializers/accountSerializers.py b/the_social_network/core/serializers/accountSerializers.py
new file mode 100644
index 0000000000000000000000000000000000000000..95724791e0802b4da840e94c3a38d37fe9a407da
--- /dev/null
+++ b/the_social_network/core/serializers/accountSerializers.py
@@ -0,0 +1,80 @@
+from rest_framework import serializers
+
+from ..models import Account
+from ..serializers.authenticationSerializers import UserPublicSerializer, UserOwnSerializer
+from ..serializers.contentSerializers import StatementSerializer
+
+
+class AccountSerializer(serializers.ModelSerializer):
+    """
+    This serializer serializes the accounts and their data.
+    It can be used to serialize accounts.
+    """
+    user = UserPublicSerializer()
+
+    class Meta:
+        model = Account
+        fields = ('user', 'image',)
+
+
+class AccountPublicSerializer(serializers.ModelSerializer):
+    """
+    This serializer serializes the public data of accounts.
+    It can be used to get all public data of the accounts.
+    """
+    # this is the parent account
+    user = UserPublicSerializer()
+    # these are the related (child) accounts
+    related_to = serializers.ListField(source='get_related_to', child=AccountSerializer())
+    # these are all statements of the account
+    statements = serializers.ListField(source='get_statements', child=StatementSerializer())
+    # check if the calling account knows the account as friend.
+    is_friend = serializers.SerializerMethodField('_is_friend')
+    # this field is to check if the one calls his own public data.
+    self_request = serializers.SerializerMethodField('_self_request')
+
+    def _self_request(self, obj: Account):
+        return self.context["calling_account"].user.id == obj.user.id
+
+    def _is_friend(self, obj: Account):
+        """
+        This intern method checks for the calling account if the requested account is a friend or not!
+
+        :param obj: The requested account.
+        :return: True if obj is a friend of the calling account.
+        """
+        account: Account = self.context["calling_account"]
+        return obj in account.get_related_to()
+
+    class Meta:
+        model = Account
+        fields = ('user', 'image', 'biography', 'related_to', 'statements', 'is_friend', 'self_request',)
+
+
+class AccountTinySerializer(AccountPublicSerializer):
+    """
+    This serializer serializes the public data of accounts but it is shorter.
+    It can be used to get all shortened public data of the accounts.
+    """
+    # this is the parent account
+    user = UserPublicSerializer()
+
+    class Meta:
+        model = Account
+        fields = ('user', 'image', 'related_to')
+
+
+class AccountOwnSerializer(AccountPublicSerializer):
+    """
+    This serializer is for the representation of an own account.
+    It shows more information to the user then the public serializer.
+    Todo: Make statements use the StatementSerializer.
+    """
+    # this is the parent account, it overwrites the field of AccountPublicSerializer
+    user = UserOwnSerializer()
+    # to see how follows the own account
+    related_by = serializers.ListField(source='get_related_by', child=AccountSerializer())
+
+    class Meta:
+        model = Account
+        fields = ('user', 'image', 'biography', 'related_by', 'related_to', 'statements')
diff --git a/the_social_network/core/serializers/authenticationSerializers.py b/the_social_network/core/serializers/authenticationSerializers.py
new file mode 100644
index 0000000000000000000000000000000000000000..aec3ee52f925304a57fe6e7249e6769e2b032457
--- /dev/null
+++ b/the_social_network/core/serializers/authenticationSerializers.py
@@ -0,0 +1,100 @@
+import logging
+from typing import OrderedDict
+
+from django.contrib.auth import authenticate
+from django.contrib.auth.models import User
+from django.core.validators import RegexValidator
+from rest_framework import serializers
+from rest_framework.validators import UniqueValidator
+
+logger = logging.getLogger(__name__)
+
+
+class UserDefaultSerializer(serializers.ModelSerializer):
+    """
+    This is the default serializer to get users and validate their data.
+    """
+
+    username = serializers.CharField()
+
+    def validate(self, data: OrderedDict):
+        """
+        This method validates the provided data to check if there is an user existing.
+
+        :param data: Data describing the user.
+        :return: The validated data.
+        """
+        username: str = data.get("username", None)
+        password: str = data.get("password", None)
+
+        if not username:
+            raise serializers.ValidationError("This username is missing", code='blank')
+
+        if not password:
+            raise serializers.ValidationError("This password is missing", code='blank')
+
+        user: User = authenticate(username=username, password=password)
+        if not user:
+            raise serializers.ValidationError({"user": "There is no user like this"}, code='invalid')
+
+        return data
+
+    class Meta:
+        model = User
+        fields = ['username', 'password']
+
+
+class UserRegisterSerializer(serializers.ModelSerializer):
+    """
+    This serializer is used for user registration and their validation.
+    A user should have a unique valid and non-empty username, email and password.
+    """
+
+    username = serializers.CharField(
+        required=True,
+        validators=[
+            UniqueValidator(queryset=User.objects.all()),
+            RegexValidator(r'^[0-9a-zA-Z_]*$', 'Only aA-zZ, 0-9, _ are allowed.')
+        ]
+    )
+    email = serializers.EmailField(
+        required=True,
+        validators=[
+            UniqueValidator(queryset=User.objects.all())
+        ]
+    )
+
+    def create(self, validated_data):
+        """
+        This method creates a new user by the validated data.
+
+        :param validated_data: The validated data providing all information to create an user.
+        :return: The created user.
+        """
+        user: User = User.objects.create_user(**validated_data)
+        return user
+
+    class Meta:
+        model = User
+        fields = ['username', 'email', 'password']
+
+
+class UserPublicSerializer(serializers.ModelSerializer):
+    """
+    This serializer is for the public representation of the user.
+    It only shows the username.
+    """
+
+    class Meta:
+        model = User
+        fields = ('id', 'username',)
+
+
+class UserOwnSerializer(serializers.ModelSerializer):
+    """
+    This serializer is for the own representation of the user.
+    """
+
+    class Meta:
+        model = User
+        fields = ('id', 'username', 'email', 'date_joined',)
diff --git a/the_social_network/core/serializers/contentSerializers.py b/the_social_network/core/serializers/contentSerializers.py
new file mode 100644
index 0000000000000000000000000000000000000000..cb936f0f2c594e54c940f2169f0ae6c007c2fda9
--- /dev/null
+++ b/the_social_network/core/serializers/contentSerializers.py
@@ -0,0 +1,124 @@
+from typing import OrderedDict
+
+from django.apps import apps
+from django.db.models import QuerySet
+from rest_framework import serializers
+
+from ..models import Account, Statement, Hashtag, Reaction, HashtagTagging
+from ..serializers.authenticationSerializers import UserPublicSerializer
+
+
+class HashtagSerializer(serializers.ModelSerializer):
+    """
+    This serializer can be used to serialize hashtags.
+    """
+
+    class Meta:
+        model = Hashtag
+        fields = ("id", "tag",)
+
+
+class TrendingHashtagSerializer(HashtagSerializer):
+    """
+    This serializer is for the serialization of trending hashtags.
+    In addition to the serialization of the hashtags this serializer adds the usage and participants.
+    This serializer needs an context. The context must include:
+        - counted: Dict with the hashtag id as key and the usage as value.
+        - calling_user: Id of the calling user.
+    """
+    count = serializers.SerializerMethodField('_count')
+    participants = serializers.SerializerMethodField('_participants')
+
+    def _count(self, obj: Hashtag) -> int:
+        """
+        This method adds the precalculated usage of the hashtag.
+        :param obj: The current hashtag.
+        :return: The amount of usage of the specific hashtag.
+        """
+        return self.context["counted"][obj.id]
+
+    def _participants(self, obj: Hashtag) -> OrderedDict:
+        """
+        This method takes all usage of the hashtag in combination ith an statements and returns the authors.
+        Therefore one can get the participants of an conversation regarding this hashtag.
+        The calling account is excluded from the results.
+        :param obj: The current hashtag.
+        :return: The participants of an hashtag with out the requesting account.
+        """
+        tagged: QuerySet[HashtagTagging] = HashtagTagging.objects.filter(hashtag=obj.id)
+        tagged = tagged.exclude(statement__author=self.context["calling_user"])
+
+        authors: QuerySet[Account] = Account.objects.filter(
+            user__id__in=tagged.values_list('statement__author', flat=True).distinct()
+        )
+        serializer: AccountSerializer = AccountSerializer(instance=authors, many=True)
+        return serializer.data
+
+    class Meta:
+        model = Hashtag
+        fields = HashtagSerializer.Meta.fields + ('count', 'participants')
+
+
+class AccountSerializer(serializers.ModelSerializer):
+    """
+    This serializer serializes the accounts and their data.
+    It can be used to serialize accounts.
+    Todo: Replace the account mentioning with users to remove this dependencies.
+    """
+    user = UserPublicSerializer()
+
+    class Meta:
+        model = apps.get_model("core", "Account")
+        fields = ('user', 'image',)
+
+
+class SimpleStatementSerializer(serializers.ModelSerializer):
+    """
+    This serializer serializes the statements and their content.
+    It can be used to serialize content of a statement.
+    """
+    author = AccountSerializer()
+    tagged = serializers.ListField(source='get_hashtags', child=HashtagSerializer())
+    mentioned = serializers.ListField(source='get_mentioning', child=AccountSerializer())
+
+    class Meta:
+        model = Statement
+        fields = ('id', 'author', 'content', 'tagged', 'mentioned', 'created')
+
+
+class ReactionSerializer(serializers.ModelSerializer):
+    """
+    This serializer is for reactions.
+    It will return the serialized reaction and shows the id, vote and the child statement.
+    """
+    child = SimpleStatementSerializer()
+    parent = SimpleStatementSerializer()
+
+    class Meta:
+        model = Reaction
+        fields = ('id', 'vote', 'child', 'parent')
+
+
+class StatementSerializer(SimpleStatementSerializer):
+    """
+    This is more then the simple statement serializer.
+    With this serializer one can also get information regarding the connection to the parent.
+    Todo: Is there a way to combine each statement with parent and child information and shorten the frontend?
+    """
+    relation_to_parent = serializers.ListField(source='get_reaction_to_parent', child=ReactionSerializer())
+
+    class Meta:
+        model = Statement
+        fields = SimpleStatementSerializer.Meta.fields + ('relation_to_parent',)
+
+
+class StatementObservationSerializer(StatementSerializer):
+    """
+    This serializer is for the statement observation.
+    Therefore the reactions are extended in the fields.
+    """
+    reactions = serializers.ListField(source='get_reactions', child=ReactionSerializer())
+
+    class Meta:
+        model = Statement
+        fields = StatementSerializer.Meta.fields + ('reactions',)
diff --git a/the_social_network/core/tests.py b/the_social_network/core/tests.py
new file mode 100644
index 0000000000000000000000000000000000000000..26f67fa7b58bf203bfb2bcd8e03e2bf530a47cbe
--- /dev/null
+++ b/the_social_network/core/tests.py
@@ -0,0 +1,707 @@
+from typing import List
+
+from django.contrib.auth import authenticate
+from django.contrib.auth.models import User
+from django.test import TestCase
+from rest_framework.authtoken.models import Token
+from rest_framework.response import Response
+from rest_framework.test import APIClient, APITestCase
+from rest_framework import status
+
+from .models import Account, Statement, Hashtag, Reaction
+
+class TestAccounts(TestCase):
+
+    def setUp(self):
+        self.user_bernd = User.objects.create_user(username="Bernd", email="Bernd@Brot.de", password="Brot")
+        self.user_beate = User.objects.create_user(username="Beate", email="Rote@Beate.de", password="Rote")
+
+        self.account_bernd: Account = Account.objects.create(user=self.user_bernd)
+        self.account_beate: Account = Account.objects.create(user=self.user_beate)
+
+    def clear_up_users(self, users: 'list[User]'):
+        for user in users:
+            user.delete()
+            try:
+                user_exists = User.objects.get(username=user.username)
+            except Exception as exception:
+                user_exists = None
+            self.assertIsNone(user_exists)
+        # check if the accounts are also removed if the user is deleted
+        for user in users:
+            try:
+                account_exists = Account.objects.get(user=user)
+            except Exception as exception:
+                account_exists = None
+            self.assertIsNone(account_exists)
+
+    def tearDown(self):
+        self.clear_up_users([self.user_beate, self.user_bernd])
+
+    def test_account_can_follow_accounts(self):
+        self.assertIsNotNone(self.account_bernd)
+        self.assertIsNotNone(self.account_beate)
+        self.assertFalse(self.account_bernd.related_to.all().exists())
+        self.assertFalse(self.account_beate.related_to.all().exists())
+
+        created: bool = self.account_beate.add_relationship(self.account_bernd)
+        self.assertTrue(created)
+        # Beate should have an relationship to Bernd
+        beates_relations = self.account_beate.related_to.all()
+        self.assertEqual(beates_relations[0], self.account_bernd)
+        # But Bernd should not have an relationship to Beate
+        self.assertFalse(self.account_bernd.related_to.all().exists())
+
+    def test_account_can_unfollow_accounts(self):
+        self.test_account_can_follow_accounts()
+        deleted: bool = self.account_beate.remove_relationship(self.account_bernd)
+        # Beate can delete her relationships
+        self.assertTrue(deleted)
+        self.assertFalse(self.account_beate.related_to.all().exists())
+
+    def test_accounts_provide_related_accounts(self):
+        self.test_account_can_follow_accounts()
+        related_accounts_of_beate: List[Account] = self.account_beate.get_related_to()
+        related_accounts_of_bernd: List[Account] = self.account_bernd.get_related_to()
+        # there are results for the relationships for beate but not for bernd
+        self.assertIsNotNone(related_accounts_of_beate)
+        self.assertIsNotNone(related_accounts_of_bernd)
+        self.assertEqual(related_accounts_of_bernd, [])
+        # Beate has relation to Bernd
+        self.assertEqual(related_accounts_of_beate[0], self.account_bernd)
+
+    def test_accounts_can_provides_accounts_who_relates_with_them(self):
+        self.test_account_can_follow_accounts()
+        accounts_relating_to_beate: List[Account] = self.account_beate.get_related_by()
+        accounts_relating_to_bernd: List[Account] = self.account_bernd.get_related_by()
+        # Beate only relates to Bernd
+        self.assertEqual([], accounts_relating_to_beate)
+        self.assertNotEqual([], accounts_relating_to_bernd)
+
+
+class TestGetAccount(APITestCase):
+    def setUp(self):
+        self.client = APIClient()
+        self.user_bernd = User.objects.create_user(username="Bernd", email="Bernd@Brot.de", password="Brot")
+        self.user_beate = User.objects.create_user(username="Beate", email="Rote@Beate.de", password="Rote")
+        self.token_bernd = Token.objects.create(user=self.user_bernd)
+        self.token_beate = Token.objects.create(user=self.user_beate)
+
+        self.account_bernd: Account = Account.objects.create(user=self.user_bernd)
+        self.account_beate: Account = Account.objects.create(user=self.user_beate)
+
+    def test_own_account_provides_own_data(self):
+
+        created: bool = self.account_beate.add_relationship(self.account_bernd)
+        self.assertTrue(created)
+        # Beate should have an relationship to Bernd
+        beates_relations = self.account_beate.related_to.all()
+        self.assertEqual(beates_relations[0], self.account_bernd)
+        # But Bernd should not have an relationship to Beate
+        self.assertFalse(self.account_bernd.related_to.all().exists())
+
+        self.client.credentials(HTTP_AUTHORIZATION='Token ' + str(self.token_beate))
+        response: Response = self.client.get(path="/accounts/show/own/")
+
+        # public information about beate
+        self.assertEqual(response.data[0]["user"]["username"], self.user_beate.username)
+        self.assertEqual(response.data[0]["user"]["id"], self.user_beate.id)
+
+        # public information about the account she is relates to
+        self.assertEqual(response.data[0]["related_to"][0]["user"]["username"], self.user_bernd.username)
+        self.assertEqual(response.data[0]["related_to"][0]["user"]["id"], self.user_bernd.id)
+
+        # public information about the account who relates to her
+        self.assertEqual(response.data[0]["related_by"], [])
+
+        # what do we know about bernd
+        self.client.credentials(HTTP_AUTHORIZATION='Token ' + str(self.token_bernd))
+        response: Response = self.client.get(path="/accounts/show/own/")
+
+        # public information about bernd
+        self.assertEqual(response.data[0]["user"]["username"], self.user_bernd.username)
+        self.assertEqual(response.data[0]["user"]["id"], self.user_bernd.id)
+
+        # public information about the accounts who relates to Bernd
+        self.assertEqual(response.data[0]["related_by"][0]["user"]["username"], self.user_beate.username)
+        self.assertEqual(response.data[0]["related_by"][0]["user"]["id"], self.user_beate.id)
+
+        # public information about the account Bernd relates to
+        self.assertEqual(response.data[0]["related_to"], [])
+
+        # Bernd adds an statement
+        self.account_bernd.add_statement("I like Beate")
+        # what do we know about Bernd
+        response: Response = self.client.get(path="/accounts/show/{}/".format(self.user_bernd.id))
+        self.assertEqual(response.data[0]["statements"][0]["content"], "I like Beate")
+
+    def test_account_provide_public_data(self):
+        created: bool = self.account_beate.add_relationship(self.account_bernd)
+        self.assertTrue(created)
+        # Beate should have an relationship to Bernd
+        beates_relations = self.account_beate.related_to.all()
+        self.assertEqual(beates_relations[0], self.account_bernd)
+        # But Bernd should not have an relationship to Beate
+        self.assertFalse(self.account_bernd.related_to.all().exists())
+
+        self.client.credentials(HTTP_AUTHORIZATION='Token ' + str(self.token_bernd))
+        response: Response = self.client.get(path="/accounts/show/{}/".format(self.user_beate.id))
+
+        # public information about beate
+        self.assertEqual(response.data[0]["user"]["username"], self.user_beate.username)
+        self.assertEqual(response.data[0]["user"]["id"], self.user_beate.id)
+
+        # public information about the account she is relates to
+        self.assertEqual(response.data[0]["related_to"][0]["user"]["username"], self.user_bernd.username)
+        self.assertEqual(response.data[0]["related_to"][0]["user"]["id"], self.user_bernd.id)
+        self.assertFalse(response.data[0]["is_friend"])
+
+        # what do we know about bernd
+        self.client.credentials(HTTP_AUTHORIZATION='Token ' + str(self.token_beate))
+        response: Response = self.client.get(path="/accounts/show/{}/".format(self.user_bernd.id))
+
+        # public information about bernd
+        self.assertEqual(response.data[0]["user"]["username"], self.user_bernd.username)
+        self.assertEqual(response.data[0]["user"]["id"], self.user_bernd.id)
+
+        # public information about the account Bernd relates to
+        self.assertEqual(response.data[0]["related_to"], [])
+        self.assertTrue(response.data[0]["is_friend"])
+
+        # Bernd adds an statement
+        self.account_bernd.add_statement("I like Beate")
+        # what do we know about Bernd
+        self.client.credentials(HTTP_AUTHORIZATION='Token ' + str(self.token_beate))
+        response: Response = self.client.get(path="/accounts/show/{}/".format(self.user_bernd.id))
+        self.assertEqual(response.data[0]["statements"][0]["content"], "I like Beate")
+
+    def clear_up_users(self, users: 'list[User]'):
+        for user in users:
+            user.delete()
+            try:
+                user_exists = User.objects.get(username=user.username)
+            except Exception as exception:
+                user_exists = None
+            self.assertIsNone(user_exists)
+        # check if the accounts are also removed if the user is deleted
+        for user in users:
+            try:
+                account_exists = Account.objects.get(user=user)
+            except Exception as exception:
+                account_exists = None
+            self.assertIsNone(account_exists)
+
+    def tearDown(self):
+        self.clear_up_users([self.user_beate, self.user_bernd])
+
+
+class TestObtainingAToken(APITestCase):
+    def setUp(self):
+        self.client = APIClient()
+        self.user = User.objects.create_user(username="Rudiger", email="Rudiger@Dog.com", password="Rudiger")
+        self.user.save()
+
+    def tearDown(self):
+        self.user.delete()
+        try:
+            user = User.objects.get(username="Rudiger")
+        except Exception as exception:
+            user = None
+        self.assertIsNone(user)
+
+    def test_valid_user_obtains_token(self):
+        response: Response = self.client.post(path="/authentication/obtain/", data={
+            "username": "Rudiger",
+            "password": "Rudiger"
+        })
+        self.assertEqual(response.status_code, status.HTTP_200_OK)
+        self.assertTrue("token" in response.data.keys())
+        self.assertIsNotNone(response.data["token"])
+
+    def test_invalid_user_does_not_obtains_token(self):
+        response: Response = self.client.post(path="/authentication/obtain/", data={
+            "username": "Klaus",
+            "password": "Klaus"
+        })
+        self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
+
+
+class TestValidateAToken(APITestCase):
+    def setUp(self):
+        self.client = APIClient()
+        self.user = User.objects.create_user(username="Rudiger", email="Rudiger@Dog.com", password="Rudiger")
+        self.user_token = Token.objects.create(user=self.user)
+
+    def tearDown(self):
+        self.user.delete()
+        try:
+            user = User.objects.get(username="Rudiger")
+        except Exception as exception:
+            user = None
+        self.assertIsNone(user)
+
+    def test_invalid_user_cant_validate_token(self):
+        self.client.credentials(HTTP_AUTHORIZATION='Token ' + 'Invalid Token')
+        response: Response = self.client.get(path="/authentication/validate/")
+        self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED)
+
+    def test_valid_user_can_validate_token(self):
+        self.client.credentials(HTTP_AUTHORIZATION='Token ' + str(self.user_token))
+        response: Response = self.client.get(path="/authentication/validate/")
+        self.assertEqual(response.status_code, status.HTTP_200_OK)
+
+
+class TestRegistration(APITestCase):
+    def setUp(self):
+        self.client = APIClient()
+
+    def test_everything_is_missing(self):
+        response: Response = self.client.post(path="/authentication/register/", data={})
+        self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
+        self.assertEqual(response.data["username"][0].code, "required")
+        self.assertEqual(response.data["password"][0].code, "required")
+        self.assertEqual(response.data["email"][0].code, "required")
+
+    def test_everything_is_empty(self):
+        response: Response = self.client.post(path="/authentication/register/", data={
+            "username": "",
+            "email": "",
+            "password": ""
+        })
+        self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
+        self.assertEqual(response.data["username"][0].code, "blank")
+        self.assertEqual(response.data["password"][0].code, "blank")
+        self.assertEqual(response.data["email"][0].code, "blank")
+
+    def test_user_and_email_already_exists(self):
+        user = User.objects.create_user(username="Peter", password="password", email="e@mail.de")
+
+        response: Response = self.client.post(path="/authentication/register/", data={
+            "username": "Peter",
+            "password": "password",
+            "email": "e@mail.de"
+        })
+
+        self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
+        self.assertEqual(response.data["username"][0].code, "unique")
+        self.assertEqual(response.data["email"][0].code, "unique")
+
+    def test_username_is_not_alphanumeric(self):
+        response: Response = self.client.post(path="/authentication/register/", data={
+            "username": "NoWay%&/\/8)(?=!"'``´',
+            "password": "password",
+            "email": "e@mail.de"
+        })
+        self.assertEqual(response.data["username"][0].code, "invalid")
+
+    def test_register_valid_user(self):
+        response: Response = self.client.post(path="/authentication/register/", data={
+            "username": "another_user100",
+            "password": "another_password",
+            "email": "another_e@mail.de"
+        })
+        self.assertEqual(response.status_code, status.HTTP_201_CREATED)
+        token_user: User = Token.objects.get(key=response.data["token"]).user
+        user: User = User.objects.get(username="another_user100")
+        account: Account = Account.objects.get(user=user)
+        self.assertIsNotNone(account)
+        self.assertEqual(account.user, user)
+        self.assertEqual(token_user, user)
+
+
+class TestLogin(APITestCase):
+    def setUp(self):
+        self.client = APIClient()
+        self.user = User.objects.create_user(username="Bernd", email="Bernd@Brot.com", password="Brot")
+        self.user.save()
+
+    def test_valid_user_can_login(self):
+        response: Response = self.client.post(path="/authentication/login/", data={
+            "username": "Bernd", "password": "Brot"
+        })
+
+        self.assertEqual(response.status_code, status.HTTP_200_OK)
+
+        user: User = Token.objects.get(key=response.data["token"]).user
+        self.assertEqual(self.user, user)
+        user: User = authenticate(username="Bernd", password="Brot")
+        self.assertIsNotNone(user)
+
+    def test_token_gets_refreshed_after_new_login(self):
+        response: Response = self.client.post(path="/authentication/login/", data={
+            "username": "Bernd", "password": "Brot"
+        })
+
+        self.assertEqual(response.status_code, status.HTTP_200_OK)
+
+        token_old: Token = Token.objects.get(key=response.data["token"])
+        self.assertIsNotNone(token_old)
+
+        response: Response = self.client.post(path="/authentication/login/", data={
+            "username": "Bernd", "password": "Brot"
+        })
+
+        self.assertEqual(response.status_code, status.HTTP_200_OK)
+
+        token_new: Token = Token.objects.get(key=response.data["token"])
+        self.assertIsNotNone(token_new)
+
+        self.assertNotEqual(token_old, token_new)
+
+    def test_user_can_not_login_with_wrong_username(self):
+        response: Response = self.client.post(path="/authentication/login/", data={
+            "username": "Berndy", "password": "Brot"
+        })
+
+        self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
+        self.assertEqual(response.data["user"][0].code, "invalid")
+
+    def test_user_can_not_login_with_wrong_password(self):
+        response: Response = self.client.post(path="/authentication/login/", data={
+            "username": "Bernd", "password": "Brötchen"
+        })
+
+        self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
+        self.assertEqual(response.data["user"][0].code, "invalid")
+
+    def test_user_can_not_login_without_username(self):
+        response: Response = self.client.post(path="/authentication/login/", data={
+            "password": "Brot"
+        })
+
+        self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
+        self.assertEqual(response.data["username"][0].code, "required")
+
+    def test_user_can_not_login_with_empty_username(self):
+        response: Response = self.client.post(path="/authentication/login/", data={
+            "username": "", "password": "Brot"
+        })
+
+        self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
+        self.assertEqual(response.data["username"][0].code, "blank")
+
+    def test_user_can_not_login_without_password(self):
+        response: Response = self.client.post(path="/authentication/login/", data={
+            "username": "Bernd"
+        })
+
+        self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
+        self.assertEqual(response.data["password"][0].code, "required")
+
+    def test_user_can_not_login_with_empty_password(self):
+        response: Response = self.client.post(path="/authentication/login/", data={
+            "username": "Bernd", "password": ""
+        })
+
+        self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
+        self.assertEqual(response.data["password"][0].code, "blank")
+
+    def tearDown(self):
+        self.user.delete()
+        try:
+            user = User.objects.get(username="Bernd")
+        except Exception as exception:
+            user = None
+        self.assertIsNone(user)
+
+
+class TestLogout(APITestCase):
+    def setUp(self):
+        self.client = APIClient()
+        self.user = User.objects.create_user(username="Beate", email="Rote@Beate.com", password="Rote")
+        self.user.save()
+
+    def test_valid_user_can_logout(self):
+        response: Response = self.client.post(path="/authentication/login/", data={
+            "username": "Beate", "password": "Rote"
+        })
+
+        self.assertEqual(response.status_code, status.HTTP_200_OK)
+
+        token: Token = Token.objects.get(key=response.data["token"])
+        user: User = token.user
+        self.assertEqual(self.user, user)
+        self.client.credentials(HTTP_AUTHORIZATION='Token ' + str(token))
+        response: Response = self.client.post(path="/authentication/logout/")
+        self.assertEqual(response.status_code, status.HTTP_200_OK)
+        token: Token = Token.objects.filter(user=user).first()
+        self.assertIsNone(token)
+
+    def test_valid_user_can_not_logout_twice(self):
+        response: Response = self.client.post(path="/authentication/login/", data={
+            "username": "Beate", "password": "Rote"
+        })
+
+        self.assertEqual(response.status_code, status.HTTP_200_OK)
+
+        user: User = Token.objects.get(key=response.data["token"]).user
+        token: Token = Token.objects.get(key=response.data["token"])
+        self.assertEqual(self.user, user)
+
+        self.client.credentials(HTTP_AUTHORIZATION='Token ' + str(token))
+        response: Response = self.client.post(path="/authentication/logout/")
+        self.assertEqual(response.status_code, status.HTTP_200_OK)
+        token: Token = Token.objects.filter(user=user).first()
+        self.assertIsNone(token)
+
+        self.client.credentials(HTTP_AUTHORIZATION='Token ' + str(token))
+        response: Response = self.client.post(path="/authentication/logout/")
+        self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED)
+
+    def tearDown(self):
+        self.user.delete()
+        try:
+            user = User.objects.get(username="Rote")
+        except Exception as exception:
+            user = None
+        self.assertIsNone(user)
+
+
+class TestStatement(TestCase):
+    def setUp(self):
+        self.user_bernd = User.objects.create_user(username="Bernd", email="Bernd@Brot.de", password="Brot")
+        self.account_bernd: Account = Account.objects.create(user=self.user_bernd)
+
+        self.user_beate = User.objects.create_user(username="Beate", email="Rote@Beate.de", password="Beate")
+        self.account_beate: Account = Account.objects.create(user=self.user_beate)
+
+        self.statement: Statement = Statement.objects.create(author=self.account_bernd, content="I like Beate")
+        self.statement_with_hashtags_and_mentioning: Statement = Statement.objects.create(author=self.account_bernd,
+                                                                                          content="I like #eating the #/&%! whopper #Burger_King2020 with @Beate @NoOne")
+        self.hashtag: Hashtag = Hashtag.objects.create(tag="Burger_King2020")
+
+    def test_statement_can_mention_account(self):
+        created = self.statement.add_mentioning(self.account_beate)
+        self.assertTrue(created)
+        mentions = self.statement.get_mentioning()
+        self.assertNotEqual(mentions, [])
+        self.assertEqual(mentions[0], self.account_beate)
+        deleted = self.statement.remove_mentioning(self.account_beate)
+        self.assertTrue(deleted)
+        mentions = self.statement.get_mentioning()
+        self.assertEqual(mentions, [])
+
+    def test_account_has_statement_from_database(self):
+        statements: List[Statement] = self.account_bernd.get_statements()
+        self.assertNotEqual(statements, [])
+        self.assertEqual(statements[1], self.statement)
+
+    def test_account_can_add_statement(self):
+        self.account_bernd.add_statement("I <3 burgers")
+        self.assertEqual(len(self.account_bernd.get_statements()), 3)
+        self.assertEqual(self.account_bernd.get_statements()[0].content, "I <3 burgers")
+
+    def test_statement_resolves_hashtags(self):
+        hashtags = self.statement_with_hashtags_and_mentioning.get_hashtags()
+        self.assertEqual(len(hashtags), 2)
+        self.assertEqual(hashtags[0].tag, "eating")
+        self.assertEqual(hashtags[1].tag, "Burger_King2020")
+
+    def test_statement_resolves_mentions(self):
+        mentions = self.statement_with_hashtags_and_mentioning.get_mentioning()
+        self.assertNotEqual(mentions, [])
+        self.assertEqual(len(mentions), 1)
+        self.assertEqual(mentions[0], self.account_beate)
+
+    def test_statement_can_add_hashtag(self):
+        created = self.statement.add_hashtag(self.hashtag)
+        self.assertTrue(created)
+
+        hashtags = self.statement.get_hashtags()
+        self.assertNotEqual(hashtags, [])
+        self.assertEqual(self.hashtag, hashtags[0])
+
+        deleted = self.statement.remove_hashtag(self.hashtag)
+        self.assertTrue(deleted)
+
+        hashtags = self.statement.get_hashtags()
+        self.assertEqual(hashtags, [])
+
+    def test_statement_can_add_reaction(self):
+        created = self.statement.add_reaction(self.statement_with_hashtags_and_mentioning, 1)
+        self.assertTrue(created)
+        reactions: List[Reaction] = self.statement.get_reactions()
+        self.assertEqual(len(reactions), 1)
+        reaction: Reaction = reactions[0]
+        self.assertEqual(reaction.get_vote_display(), "like")
+        self.assertEqual(reaction.child, self.statement_with_hashtags_and_mentioning)
+        deleted = self.statement_with_hashtags_and_mentioning.remove_as_reaction()
+        self.assertTrue(deleted)
+
+    def tearDown(self):
+        self.user_bernd.delete()
+        try:
+            user_exists = User.objects.get(username=self.user_bernd.username)
+        except Exception as exception:
+            user_exists = None
+        self.assertIsNone(user_exists)
+        # check if bernds account is deleted
+        try:
+            account_exists = Account.objects.get(user=self.user_bernd)
+        except Exception as exception:
+            account_exists = None
+        self.assertIsNone(account_exists)
+        # check if bernds statements are deleted
+        try:
+            statements_exists = Statement.objects.get(user=self.user_bernd)
+        except Exception as exception:
+            statements_exists = None
+        self.assertIsNone(statements_exists)
+        try:
+            hashtag_exists = Statement.objects.get(user=self.hashtag)
+        except Exception as exception:
+            hashtag_exists = None
+        self.assertIsNone(hashtag_exists)
+
+
+class TestGetStatement(APITestCase):
+    def setUp(self):
+        self.client = APIClient()
+        self.user_bernd = User.objects.create_user(username="Bernd", email="Bernd@Brot.de", password="Brot")
+        self.account_bernd: Account = Account.objects.create(user=self.user_bernd)
+        self.token_bernd = Token.objects.create(user=self.user_bernd)
+        self.statement_1: Statement = Statement.objects.create(author=self.account_bernd, content="I like @Bernd #Foo")
+        self.statement_2: Statement = Statement.objects.create(author=self.account_bernd, content="I like Beate")
+
+    def test_statement_provides_data(self):
+        self.statement_1.add_reaction(self.statement_2, 2)
+        self.client.credentials(HTTP_AUTHORIZATION='Token ' + str(self.token_bernd))
+        response: Response = self.client.get(path="/contents/statements/get/{id}/".format(id=self.statement_1.id))
+        self.assertEqual(response.data[0]["id"], self.statement_1.id)
+        self.assertEqual(len(response.data[0]["mentioned"]), 1)
+        self.assertEqual(len(response.data[0]["tagged"]), 1)
+        self.assertEqual(len(response.data[0]["reactions"]), 1)
+        reaction = response.data[0]["reactions"][0]
+        self.assertEqual(reaction["vote"], 2)
+        self.assertEqual(reaction["child"]["id"], self.statement_2.id)
+        self.assertEqual(self.statement_2.get_parent(), self.statement_1)
+        self.assertIsNone(self.statement_1.get_parent())
+        self.assertEqual(self.statement_2.get_reaction_to_parent()[0].vote, 2)
+
+    def test_statements_with_hashtags_can_be_provided(self):
+        self.client.credentials(HTTP_AUTHORIZATION='Token ' + str(self.token_bernd))
+        response: Response = self.client.get(path="/contents/statements/with/hashtag/?q=Foo")
+        self.assertTrue(len(response.data) != 0)
+
+        self.assertEqual(response.data[0]["id"], self.statement_1.id)
+
+
+class TestGetStatementFeed(APITestCase):
+    def setUp(self):
+        self.client = APIClient()
+        self.user_bernd = User.objects.create_user(username="Bernd", email="Bernd@Brot.de", password="Brot")
+        self.account_bernd: Account = Account.objects.create(user=self.user_bernd)
+
+        self.user_beate = User.objects.create_user(username="Beate", email="Rote@Beate.de", password="Beate")
+        self.account_beate: Account = Account.objects.create(user=self.user_beate)
+        self.account_beate.add_relationship(self.account_bernd)
+        self.token_beate = Token.objects.create(user=self.user_beate)
+
+        self.statement_1: Statement = Statement.objects.create(author=self.account_bernd, content="I like @Bernd #Foo")
+        self.statement_2: Statement = Statement.objects.create(author=self.account_bernd, content="I like Beate")
+        self.statement_3: Statement = Statement.objects.create(author=self.account_beate, content="I like Bernd")
+        self.statement_1.add_reaction(self.statement_2, 2)
+
+    def test_feed_contains_correct_data(self):
+        self.statement_1.add_reaction(self.statement_2, 2)
+        self.client.credentials(HTTP_AUTHORIZATION='Token ' + str(self.token_beate))
+        response: Response = self.client.get(path="/contents/statements/feed/")
+        result = response.data
+        self.assertTrue(len(result), 3)
+        print(result[0].get("id"))
+        print(result[1].get("id"))
+        print(result[2].get("id"))
+        print(self.statement_1.id)
+        print(self.statement_2.id)
+        print(self.statement_3.id)
+        self.assertEqual(result[0].get("id"), self.statement_3.id)
+        self.assertEqual(result[1].get("id"), self.statement_2.id)
+        self.assertEqual(result[2].get("id"), self.statement_1.id)
+        self.assertTrue(result[0].get("id") > result[1].get("id"))
+        self.assertTrue(result[0].get("created") > result[1].get("created"))
+        self.assertTrue(result[1].get("id") > result[2].get("id"))
+        self.assertTrue(result[1].get("created") > result[2].get("created"))
+
+
+class TestTrendingHashtag(APITestCase):
+    def setUp(self):
+        self.client = APIClient()
+        self.user_bernd = User.objects.create_user(username="Bernd", email="Bernd@Brot.de", password="Brot")
+        self.account_bernd: Account = Account.objects.create(user=self.user_bernd)
+
+        self.user_beate = User.objects.create_user(username="Beate", email="Rote@Beate.de", password="Beate")
+        self.account_beate: Account = Account.objects.create(user=self.user_beate)
+        self.token_beate = Token.objects.create(user=self.user_beate)
+
+    def test_trending_hashtag_is_empty(self):
+        self.client.credentials(HTTP_AUTHORIZATION='Token ' + str(self.token_beate))
+        response: Response = self.client.get(path="/contents/trending/hashtag/")
+        self.assertEqual(response.data, [])
+
+    def test_trending_hashtag_not_empty(self):
+        self.statement_1: Statement = Statement.objects.create(author=self.account_bernd, content="#Foo#Bar!")
+        self.statement_2: Statement = Statement.objects.create(author=self.account_beate, content="#Foo #Bar#Baz")
+        self.statement_3: Statement = Statement.objects.create(author=self.account_beate,
+                                                               content="I like @Beate#Foo#Baz#Bizz!")
+        self.statement_1.add_reaction(self.statement_3, 2)
+        self.client.credentials(HTTP_AUTHORIZATION='Token ' + str(self.token_beate))
+        response: Response = self.client.get(path="/contents/trending/hashtag/")
+        self.assertEqual(response.data[0]["count"], 3)
+        self.assertEqual(response.data[0]["tag"], "Foo")
+        self.assertEqual(len(response.data[0]["participants"]), 1)
+        self.assertEqual(response.data[0]["participants"][0]["user"]["id"], self.user_bernd.id)
+        self.assertEqual(response.data[1]["count"], 2)
+        self.assertEqual(response.data[1]["tag"], "Bar")
+        self.assertEqual(len(response.data[1]["participants"]), 1)
+        self.assertEqual(response.data[1]["participants"][0]["user"]["id"], self.user_bernd.id)
+        self.assertTrue(response.data[2]["count"], 2)
+        self.assertEqual(response.data[2]["tag"], "Baz")
+        self.assertEqual(len(response.data[2]["participants"]), 0)
+
+
+class TestSearch(APITestCase):
+    def setUp(self):
+        self.client = APIClient()
+        self.user_bernd = User.objects.create_user(username="Bernd", email="Bernd@Brot.de", password="Brot")
+        self.token_bernd = Token.objects.create(user=self.user_bernd)
+        self.account_bernd: Account = Account.objects.create(user=self.user_bernd)
+        self.hashtag: Hashtag = Hashtag.objects.create(tag="Berg")
+
+    def clear_up_users(self, users: 'list[User]'):
+        for user in users:
+            user.delete()
+            try:
+                user_exists = User.objects.get(username=user.username)
+            except Exception as exception:
+                user_exists = None
+            self.assertIsNone(user_exists)
+        # check if the accounts are also removed if the user is deleted
+        for user in users:
+            try:
+                account_exists = Account.objects.get(user=user)
+            except Exception as exception:
+                account_exists = None
+            self.assertIsNone(account_exists)
+
+    def tearDown(self):
+        self.clear_up_users([self.user_bernd])
+        self.hashtag.delete()
+
+    def test_user_can_search(self):
+        self.client.credentials(HTTP_AUTHORIZATION='Token ' + str(self.token_bernd))
+        response: Response = self.client.get(path="/search/?q=Ber")
+        self.assertEqual(len(response.data["accounts"]), 1)
+        self.assertEqual(response.data["accounts"][0]["user"]["username"], self.user_bernd.username)
+        self.assertEqual(len(response.data["hashtags"]), 1)
+        self.assertEqual(response.data["hashtags"][0]["tag"], self.hashtag.tag)
+
+    def test_user_can_filter_search(self):
+        self.client.credentials(HTTP_AUTHORIZATION='Token ' + str(self.token_bernd))
+        response: Response = self.client.get(path="/search/?q=Ber&filter=account")
+        self.assertEqual(len(response.data["accounts"]), 1)
+        self.assertEqual(response.data["accounts"][0]["user"]["username"], self.user_bernd.username)
+        self.assertTrue("hashtags" not in response.data.keys())
+        response: Response = self.client.get(path="/search/?q=Ber&filter=hashtag")
+        self.assertEqual(len(response.data["hashtags"]), 1)
+        self.assertEqual(response.data["hashtags"][0]["tag"], self.hashtag.tag)
+        self.assertTrue("accounts" not in response.data.keys())
diff --git a/the_social_network/core/urls/accountUrls.py b/the_social_network/core/urls/accountUrls.py
new file mode 100644
index 0000000000000000000000000000000000000000..31f663ff0feb7354b5aa558224d1937799de4918
--- /dev/null
+++ b/the_social_network/core/urls/accountUrls.py
@@ -0,0 +1,13 @@
+from django.urls import path
+
+from ..views.accountViews import *
+
+urlpatterns = [
+    path('show/<int:id>/', PublicAccounts.as_view(), name='show'),
+    path('show/all/', AllPublicAccounts.as_view(), name='showAll'),
+    path('show/own/', OwnAccount.as_view(), name='own'),
+    path('update/', OwnAccountUpdate.as_view(), name='update'),
+    path('follow/<int:id>/', OwnAccountFollow.as_view(), name='follow'),
+    path('unfollow/<int:id>/', OwnAccountUnfollow.as_view(), name='unfollow'),
+    path('operation/add/statement/', AddStatement.as_view(), name='addStatement'),
+]
\ No newline at end of file
diff --git a/the_social_network/core/urls/authenticationUrls.py b/the_social_network/core/urls/authenticationUrls.py
new file mode 100644
index 0000000000000000000000000000000000000000..dfe496d721ea8974d1207e38dab10dde26dc0a00
--- /dev/null
+++ b/the_social_network/core/urls/authenticationUrls.py
@@ -0,0 +1,12 @@
+from django.conf.urls import url
+from rest_framework.authtoken.views import obtain_auth_token
+
+from ..views.authenticationViews import *
+
+urlpatterns = [
+    url(r'obtain/', obtain_auth_token, name='obtain'),
+    url(r'register/', Register.as_view(), name='register'),
+    url(r'login/', Login.as_view(), name='login'),
+    url(r'logout/', Logout.as_view(), name='logout'),
+    url(r'validate/', TokenValidation.as_view(), name='validate'),
+]
diff --git a/the_social_network/core/urls/contentUrls.py b/the_social_network/core/urls/contentUrls.py
new file mode 100644
index 0000000000000000000000000000000000000000..575325426a1d3e8cb10242c357789588c9e17233
--- /dev/null
+++ b/the_social_network/core/urls/contentUrls.py
@@ -0,0 +1,10 @@
+from django.urls import path
+
+from ..views.contentViews import *
+
+urlpatterns = [
+    path('statements/get/<int:id>/', ShowStatement.as_view(), name="show_statement"),
+    path('statements/with/hashtag/', ShowStatementsWithHashtag.as_view(), name="show_statement_with_hashtag"),
+    path('statements/feed/', ShowStatementFeed.as_view(), name="show_statement_feed"),
+    path('trending/hashtag/', ShowTrendingHashtag.as_view(), name="show_trending_hashtags"),
+]
\ No newline at end of file
diff --git a/the_social_network/core/urls/searchUrls.py b/the_social_network/core/urls/searchUrls.py
new file mode 100644
index 0000000000000000000000000000000000000000..d382879525dbb3c48edf98353649acc310239f3a
--- /dev/null
+++ b/the_social_network/core/urls/searchUrls.py
@@ -0,0 +1,7 @@
+from django.urls import path
+
+from ..views.searchViews import *
+
+urlpatterns = [
+    path('', Search.as_view(), name='search'),
+]
\ No newline at end of file
diff --git a/the_social_network/core/validation.py b/the_social_network/core/validation.py
new file mode 100644
index 0000000000000000000000000000000000000000..8e11ba7f535fe5d7cfd2cde323b02993f0e2a710
--- /dev/null
+++ b/the_social_network/core/validation.py
@@ -0,0 +1,34 @@
+import logging
+
+from rest_framework import status
+from rest_framework.request import Request
+from rest_framework.response import Response
+
+from . import Operations
+from .serializers.authenticationSerializers import UserRegisterSerializer, UserDefaultSerializer
+
+logger = logging.getLogger(__name__)
+
+
+def validate_request_data_for(operation: Operations, request: Request) -> Response:
+    """
+    This method validates the a request regarding user its user information.
+
+    :param operation: Which operation was used? This influences which serializer is used and which fields are checked.
+    :param request: The request regarding an user.
+    :return:    400_BAD_REQUEST if the provided data is sparse or one of the values is empty or there are duplicated values.
+                201_CREATE if the new user is created.
+                200_OK if the user is valid.
+    """
+    serializer = UserDefaultSerializer(data=request.data)
+
+    if operation is Operations.REGISTER:
+        serializer = UserRegisterSerializer(data=request.data)
+
+    if serializer.is_valid():
+        if operation is Operations.REGISTER:
+            serializer.save()  # this calls update or create based on the existence of the corresponding instance
+            return Response(data=serializer.validated_data, status=status.HTTP_201_CREATED)
+        return Response(data=serializer.validated_data, status=status.HTTP_200_OK)
+    else:
+        return Response(data=serializer.errors, status=status.HTTP_400_BAD_REQUEST)
diff --git a/the_social_network/core/views/accountViews.py b/the_social_network/core/views/accountViews.py
new file mode 100644
index 0000000000000000000000000000000000000000..a1df217cbd69453e92ff8093a9cabfaa727daea6
--- /dev/null
+++ b/the_social_network/core/views/accountViews.py
@@ -0,0 +1,204 @@
+# Create your views here.
+import logging
+from io import BytesIO
+
+from PIL import Image
+from django.contrib.auth.models import User
+from django.core.files.uploadedfile import InMemoryUploadedFile
+from django.db.models import Q
+from rest_framework import status
+from rest_framework.authentication import TokenAuthentication
+from rest_framework.permissions import IsAuthenticated
+from rest_framework.request import Request
+from rest_framework.response import Response
+from rest_framework.views import APIView
+
+from ..models import Account, Statement
+from ..serializers.accountSerializers import AccountPublicSerializer, AccountOwnSerializer
+from ..serializers.contentSerializers import ReactionSerializer, StatementSerializer
+
+logger = logging.getLogger(__name__)
+
+
+class PublicAccounts(APIView):
+    """
+    This view is used to represent the accounts.
+    It can be used to get public information about accounts from the perspective of the calling account.
+    To get this information the calling account must use its token.
+    """
+    authentication_classes = [TokenAuthentication]
+    permission_classes = (IsAuthenticated,)
+
+    def get(self, request: Request, *args, **kwargs):
+        """
+        This method is used to get all public information regarding a specific account.
+        :param request: Not used.
+        :param args: Not used.
+        :param kwargs: Should have the id of the requested account (see view.py)
+        :return:
+        """
+        calling_account: Account = Account.objects.filter(user=request.user).first()
+        account: Account = Account.objects.filter(user=int(kwargs.get("id")))
+        serializer: AccountPublicSerializer = AccountPublicSerializer(instance=account,
+                                                                      many=True,
+                                                                      context={"calling_account": calling_account})
+        return Response(data=serializer.data, status=status.HTTP_200_OK)
+
+
+class AllPublicAccounts(APIView):
+    """
+    This view is for showing all public accounts.
+    It requires the user token to see which account is calling the overview.
+    The calling account is then removed from the result.
+    """
+    authentication_classes = [TokenAuthentication]
+    permission_classes = (IsAuthenticated,)
+
+    def get(self, request: Request):
+        """
+        This method gets all available public accounts.
+        Furthermore the calling account is excluded from the result.
+        :param request: Used to get the calling account.
+        :return:
+        """
+        calling_account: Account = Account.objects.filter(user=request.user).first()
+        accounts: Account = Account.objects.filter(~Q(user=request.user))
+        serializer: AccountPublicSerializer = AccountPublicSerializer(instance=accounts,
+                                                                      many=True,
+                                                                      context={"calling_account": calling_account})
+        return Response(data=serializer.data, status=status.HTTP_200_OK)
+
+
+class OwnAccount(APIView):
+    """
+    This view is used to represent the private account of an user.
+    To access the information one have to use its token.
+    """
+    authentication_classes = [TokenAuthentication]
+    permission_classes = (IsAuthenticated,)
+
+    def get(self, request: Request):
+        """
+        This method is used to get the own account data.
+        :param request: To access the user from its token.
+        :return: Data regarding the own account.
+        """
+        account: Account = Account.objects.filter(user=request.user)
+        serializer: AccountOwnSerializer = AccountOwnSerializer(instance=account, many=True)
+        return Response(data=serializer.data, status=status.HTTP_200_OK)
+
+
+class OwnAccountFollow(APIView):
+    """
+    This view is for adding a follow relation from the calling account to the targeted one.
+    To access this view the requesting account has to use its token.
+    """
+    authentication_classes = [TokenAuthentication]
+    permission_classes = (IsAuthenticated,)
+
+    def post(self, request: Request, *args, **kwargs):
+        own_account: Account = Account.objects.filter(user=request.user).first()
+        foreign_account: Account = Account.objects.filter(user=kwargs.get("id")).first()
+        if not foreign_account:
+            return Response(status=status.HTTP_409_CONFLICT)
+        created: bool = own_account.add_relationship(foreign_account)
+        if created:
+            return Response(status=status.HTTP_200_OK)
+        return Response(status=status.HTTP_409_CONFLICT)
+
+
+class OwnAccountUnfollow(APIView):
+    """
+    This view is for deleting a follow relation from the calling account to the targeted one.
+    To access this view the requesting account has to use its token.
+    """
+    authentication_classes = [TokenAuthentication]
+    permission_classes = (IsAuthenticated,)
+
+    def post(self, request: Request, *args, **kwargs):
+        own_account: Account = Account.objects.filter(user=request.user).first()
+        foreign_account: Account = Account.objects.filter(user=kwargs.get("id")).first()
+        if not foreign_account:
+            return Response(status=status.HTTP_409_CONFLICT)
+        deleted: bool = own_account.remove_relationship(foreign_account)
+        if deleted:
+            return Response(status=status.HTTP_200_OK)
+        return Response(status=status.HTTP_409_CONFLICT)
+
+
+class OwnAccountUpdate(APIView):
+    """
+    This view is for updating the account data.
+    It will update an image.
+    """
+    authentication_classes = [TokenAuthentication]
+    permission_classes = (IsAuthenticated,)
+
+    @staticmethod
+    def put(request: Request):
+        """
+        This method updates the image as well as the biography.
+        :param request: The request send by the user.
+        :return: A response with an 200 status.
+        """
+        user: User = request.user
+        account: Account = Account.objects.filter(user=user).first()
+
+        if "biography" in request.data.keys():
+            biography: str = request.data["biography"]
+            account.update_biography(biography)
+        if "file" in request.FILES.keys():
+            file: InMemoryUploadedFile = request.FILES["file"]
+            file.name = "{name}.{extension}".format(name="account{user}{secret}".format(user=user, secret=hash(user)),
+                                                    extension="jpeg")
+            # compress image
+            image: Image = Image.open(file)
+            image = image.convert('RGB')
+            io_stream = BytesIO()
+            image.save(io_stream, format="JPEG", quality=50, optimize=True)
+            compressed_image: InMemoryUploadedFile = InMemoryUploadedFile(file=io_stream,
+                                                                          field_name=None,
+                                                                          name=file.name,
+                                                                          content_type="image/jpeg",
+                                                                          size=io_stream.tell(),
+                                                                          charset=None)
+            # update with compressed image
+            account.update_image(compressed_image)
+        return Response(status=status.HTTP_200_OK)
+
+
+class AddStatement(APIView):
+    """
+    This view serves to add statements for an specific user.
+    The user must be authenticated.
+    """
+    authentication_classes = [TokenAuthentication]
+    permission_classes = (IsAuthenticated,)
+
+    @staticmethod
+    def post(request: Request):
+        """
+        This method handles the post of an new statement.
+        :param request: The request to be handled, containing the input.
+        :return: Response with an 200 OK if everything is okay. 400 if there is no statement input.
+        If there is an reaction then this will return 200 and the serialized reaction.
+        This is necessary, because the frontend must only add this element to the overview of reaction and needs the
+        analysis regarding the mentions and tags by the backend.
+        todo: Make it possible for single statement
+
+        """
+        account: Account = Account.objects.filter(user=request.user).first()
+        statement: str = request.data.get("input", None)
+        if not statement:
+            return Response(status=status.HTTP_400_BAD_REQUEST)
+        statement: Statement = account.add_statement(statement)
+        # if there is an reaction given then is must be added to the parent element.
+        reaction: dict = request.data.get("reaction", None)
+        if reaction:
+            parent: Statement = Statement.objects.get(id=reaction.get("to"))
+            vote: int = 1 if reaction.get("relation") == "support" else 2
+            reaction, _ = parent.add_reaction(reaction_statement=statement, vote=vote)
+            serializer: ReactionSerializer = ReactionSerializer(instance=reaction, many=False)
+            return Response(status=status.HTTP_200_OK, data=serializer.data)
+        serializer: StatementSerializer = StatementSerializer(instance=statement, many=False)
+        return Response(status=status.HTTP_200_OK, data=serializer.data)
diff --git a/the_social_network/core/views/authenticationViews.py b/the_social_network/core/views/authenticationViews.py
new file mode 100644
index 0000000000000000000000000000000000000000..e74d31879a263744e39213244e264c2775988800
--- /dev/null
+++ b/the_social_network/core/views/authenticationViews.py
@@ -0,0 +1,154 @@
+import logging
+
+from django.contrib.auth import login, logout
+from django.contrib.auth.models import User
+from rest_framework import status
+from rest_framework.authentication import TokenAuthentication
+from rest_framework.authtoken.models import Token
+from rest_framework.exceptions import ValidationError
+from rest_framework.permissions import IsAuthenticated
+from rest_framework.request import Request
+from rest_framework.response import Response
+from rest_framework.views import APIView
+
+from ..models import Account
+from .. import Operations
+from ..validation import validate_request_data_for
+
+logger = logging.getLogger(__name__)
+
+
+class Register(APIView):
+    """
+    This APIView takes care of the registration of new users.
+    It checks if the new user has entered all fields for registration.
+    When a new user logs in, he is also directly logged in and receives a token.
+    """
+
+    @staticmethod
+    def validate(request: Request) -> Response:
+        """
+        This method validates the data provided for the new user.
+        It validates if the username, email and the password is set and they are not empty.
+
+        :param request: The request which should be validated.
+        :return: 400_BAD_REQUEST if the provided data is sparse or one of the values is empty.
+                 201_CREATED otherwise.
+        """
+        return validate_request_data_for(Operations.REGISTER, request)
+
+    def post(self, request: Request) -> Response:
+        """
+        This method handles the actual POST-request of the new user.
+        First the data send is checked for mistakes, missing or empty values.
+        Afterwards the User is created and logged in.
+
+        :param request: The request of the new user containing all necessary information for an registration.
+        :return: 400_BAD_REQUEST if the provided data is sparse or one of the values is empty or the user existing.
+                 201_CREATE if the new user is created (Contains the token in the data-section).
+        """
+        valid: Response = self.validate(request)
+        if valid.status_code != 201:
+            return valid
+
+        username: str = valid.data["username"]
+        user: User = User.objects.filter(username=username).first()
+        account: Account = Account.objects.create(user=user)
+        login(request, account.user)
+        return Response(status=valid.status_code, data={"token": Token.objects.create(user=account.user).__str__()})
+
+
+class Login(APIView):
+    """
+    This APIView takes care of the login of a requesting users.
+    It checks if the user has entered all fields for login.
+    When a user logs in, he receives a token.
+    """
+
+    @staticmethod
+    def validate(request: Request) -> Response:
+        """
+        This method validates the data provided for the requesting user.
+        It validates if the username and the password is set and they are not empty.
+
+        :param request: The data provided by the requesting user.
+        :return: 400_BAD_REQUEST if the provided data is sparse or one of the values is empty.
+                 200_OK otherwise.
+        """
+        return validate_request_data_for(Operations.LOGIN, request)
+
+    def post(self, request):
+        """
+        This method handles the actual POST-request of the requesting user.
+        First the data send is checked for mistakes, missing or empty values.
+        Afterwards the User is authenticated and logged in.
+        
+        :param request: The request of the user containing all necessary information for an login.
+        :return: 400_BAD_REQUEST if the provided data is sparse or one of the values is empty or wrong.
+                 200_OK if the user is authenticated (Contains the token in the data-section).
+        """
+        valid: Response = self.validate(request)
+        if valid.status_code != 200:
+            return valid
+
+        username: str = valid.data["username"]
+        user: User = User.objects.filter(username=username).first()
+        token, operation_was_create = Token.objects.get_or_create(user=user)
+
+        if not operation_was_create:
+            # refresh the token if there was a previous token detected
+            token.delete()
+            token = Token.objects.create(user=user)
+        login(request, user)
+
+        return Response(status=valid.status_code, data={"token": token.key.__str__()})
+
+
+class Logout(APIView):
+    """
+    This APIView takes care of the logout of a requesting users.
+    It checks if the user has entered all fields for logout.
+    When a user logs out, his token will be destroyed.
+    """
+
+    authentication_classes = [TokenAuthentication]
+    permission_classes = (IsAuthenticated,)
+
+    @staticmethod
+    def post(request):
+        """
+        This method handles the actual POST-request of the requesting user.
+        First the data send is checked for mistakes, missing or empty values.
+        Afterwards the User is authenticated and logged out.
+
+        :param request: The request of the user containing all necessary information for an logout.
+        :return: 400_BAD_REQUEST if the provided data is sparse or one of the values is empty or wrong or the user is not logged in.
+                 200_OK if the user is authenticated (will destroy the users token).
+        """
+        user: User = request.user
+        token: Token = Token.objects.filter(user=user).first()
+        if token:
+            token.delete()
+        logout(request)
+        return Response(status=status.HTTP_200_OK)
+
+
+class TokenValidation(APIView):
+    """
+    This view can be used to validate a token of an user.
+    Therefore it can be used for the frontend to validate if the token has expired e.g. if the user has logged in
+    on another device.
+
+    """
+    authentication_classes = [TokenAuthentication]
+    permission_classes = (IsAuthenticated,)
+
+    def get(self, request) -> Response:
+        """
+        This method is allways called if the token is valid.
+        Otherwise the permission_classes will return 401 indication an invalid token.
+
+        :param request: Unused
+        :return: Status 200 Ok if the token is authorized.
+        """
+        return Response(status=status.HTTP_200_OK)
diff --git a/the_social_network/core/views/contentViews.py b/the_social_network/core/views/contentViews.py
new file mode 100644
index 0000000000000000000000000000000000000000..dfc9760721e0cc22094c91e49d1ec118490912b2
--- /dev/null
+++ b/the_social_network/core/views/contentViews.py
@@ -0,0 +1,128 @@
+import logging
+# Create your views here.
+from typing import Optional, List, Dict
+
+from django.db.models import QuerySet, Count
+from rest_framework import status
+from rest_framework.authentication import TokenAuthentication
+from rest_framework.permissions import IsAuthenticated
+from rest_framework.request import Request
+from rest_framework.response import Response
+from rest_framework.views import APIView
+
+from ..models import Account, Statement, Hashtag, HashtagTagging
+from ..serializers.contentSerializers import StatementObservationSerializer, StatementSerializer, TrendingHashtagSerializer
+
+logger = logging.getLogger(__name__)
+
+
+class ShowStatement(APIView):
+    """
+    This view can be used to get an specific statement and all correlated data by the statements id.
+    To get information about an statement one must provide an valid token for identification.
+    """
+    authentication_classes = [TokenAuthentication]
+    permission_classes = (IsAuthenticated,)
+
+    @staticmethod
+    def get(request: Request, *args, **kwargs):
+        """
+        This method returns all information about an specific statement.
+        :param request: Not used.
+        :param args: Not used.
+        :param kwargs: Additional information to get the id of the requested statement.
+        :return:
+        """
+        statement: Statement = Statement.objects.filter(id=int(kwargs.get("id")))
+        serializer: StatementObservationSerializer = StatementObservationSerializer(instance=statement, many=True)
+        return Response(status=status.HTTP_200_OK, data=serializer.data)
+
+
+class ShowStatementsWithHashtag(APIView):
+    """
+    This view is representative for the hashtag view.
+    It can be used to get all statements with containing an specific hashtag.
+    To get the information one must have an valid token.
+    """
+    authentication_classes = [TokenAuthentication]
+    permission_classes = (IsAuthenticated,)
+
+    @staticmethod
+    def get(request: Request):
+        """
+        This method returns all statements containing the given hashtag string.
+        If there is no data or if there is no hashtag one get 200.
+        If there is data one get data and 200.
+        If the request is wrong one get 400.
+
+        :param request: Request with the parameter q, which is the string representation of the hashtag.
+        :return: 200 if there are statements with the hashtag or if there is no data, 400 if the request is invalid.
+        """
+        query: str = request.query_params.get('q', None)
+        if not query:
+            return Response(status=status.HTTP_400_BAD_REQUEST)
+        hashtag: Optional[Hashtag] = Hashtag.objects.filter(tag=query).first()
+        if not hashtag:
+            return Response(status=status.HTTP_200_OK)
+        statement: List[Statement] = Statement.objects.filter(tagged=hashtag)
+        serializer: StatementSerializer = StatementSerializer(instance=statement, many=True)
+        return Response(status=status.HTTP_200_OK, data=serializer.data)
+
+
+class ShowStatementFeed(APIView):
+    """
+    This view is for querying the feed for an calling account.
+    The feed is generated by the accounts the calling account is following.
+    To get the feed the calling account must be authenticated.
+    """
+    authentication_classes = [TokenAuthentication]
+    permission_classes = (IsAuthenticated,)
+
+    @staticmethod
+    def get(request: Request):
+        """
+        This is for getting the feed.
+        Todo: Add pagination for infinite scrolling.
+        :param request: The request containing the token to identify the calling user.
+        :return: Feed for the calling user based on the actions of those the calling account follows.
+        """
+        account: Account = Account.objects.get(user=request.user)
+        following: List[Account] = account.get_related_to() + [account]
+        feed: QuerySet[Statement] = Statement.objects.filter(author__in=following)
+        serializer: StatementSerializer = StatementSerializer(instance=feed, many=True)
+        return Response(status=status.HTTP_200_OK, data=serializer.data)
+
+
+class ShowTrendingHashtag(APIView):
+    """
+    This view is for getting the five most trending hashtags.
+    The calling user must be authenticated.
+    Also the calling user is not included as an participant of the hashtag,
+    since those others are for recommendation.
+    """
+    authentication_classes = [TokenAuthentication]
+    permission_classes = (IsAuthenticated,)
+
+    @staticmethod
+    def get(request: Request):
+        """
+        This method handles the request for trending hashtags.
+        Therefore the tagging of hashtags are counted and turned into an trending hashtag representation.
+        The TrendingHashtagSerializer adds all needed information like the count of uses and other participants.
+        The calling account is excluded from the participants.
+        :param request: Request containing the the token for identification.
+        :return: 200 OK with empty or not empty data section. The data section is empty if there are not hashtags.
+        """
+        hashtags: QuerySet[Dict] = HashtagTagging.objects.values('hashtag')
+        hashtags_counted: QuerySet[Dict] = hashtags.annotate(
+            the_count=Count('hashtag')
+        ).order_by("-the_count")
+        counted: Dict = {item["hashtag"]: item["the_count"] for item in hashtags_counted}
+        hashtags: QuerySet[Hashtag] = Hashtag.objects.filter(id__in=counted.keys())
+        if not hashtags_counted:
+            return Response(status=status.HTTP_200_OK, data=[])
+        serializer: TrendingHashtagSerializer = TrendingHashtagSerializer(
+            instance=hashtags,
+            many=True,
+            context={"counted": counted, "calling_user": request.user.id})
+        return Response(status=status.HTTP_200_OK, data=serializer.data[:3])
diff --git a/the_social_network/core/views/searchViews.py b/the_social_network/core/views/searchViews.py
new file mode 100644
index 0000000000000000000000000000000000000000..650f9fb798c029c381f778a256f494d8bc8080b7
--- /dev/null
+++ b/the_social_network/core/views/searchViews.py
@@ -0,0 +1,57 @@
+# Create your views here.
+import logging
+
+from rest_framework import status
+from rest_framework.authentication import TokenAuthentication
+from rest_framework.permissions import IsAuthenticated
+from rest_framework.request import Request
+from rest_framework.response import Response
+from rest_framework.views import APIView
+
+from ..models import Account, Hashtag
+from ..serializers.accountSerializers import AccountSerializer
+from ..serializers.contentSerializers import HashtagSerializer
+
+logger = logging.getLogger(__name__)
+
+class Search(APIView):
+    """
+    This view is for searching hashtags and accounts.
+    The search requires an user registration.
+    """
+    authentication_classes = [TokenAuthentication]
+    permission_classes = (IsAuthenticated,)
+
+    @staticmethod
+    def get(request: Request, *args, **kwargs) -> Response:
+        """
+        This method searches for matching hashtags and account for a given search query.
+        Then the results are returned in an corresponding composed dict.
+
+        :param request: The request send by the user.
+        :param args: Not used.
+        :param kwargs: Additional arguments which provides the search parameter q.
+        :return: Composed dict of results in the Response with status code 200, otherwise if no query q is given it will
+        return an empty Response with status code 400.
+        The results can also be filtered for single categories. Those categories are: account and hashtag.
+        """
+        query: str = request.query_params.get('q', None)
+        limit: int = 5
+        if not query:
+            return Response(status=status.HTTP_400_BAD_REQUEST)
+        result_filter: str = request.query_params.get('filter', None)
+
+        result: dict = {}
+        
+        if result_filter == "account" or not result_filter:
+            accounts: Account = Account.objects.filter(user__username__contains=query)[:limit]
+            result["accounts"] = AccountSerializer(instance=accounts, many=True).data
+
+        if result_filter == "hashtag" or not result_filter:
+            hashtags: Hashtag = Hashtag.objects.filter(tag__contains=query)[:limit]
+            result["hashtags"] = HashtagSerializer(instance=hashtags, many=True).data
+        
+        if result:
+            return Response(data=result, status=status.HTTP_200_OK)
+
+        return Response(status=status.HTTP_400_BAD_REQUEST)
\ No newline at end of file
diff --git a/the_social_network/manage.py b/the_social_network/manage.py
new file mode 100755
index 0000000000000000000000000000000000000000..f7f55f928f7d3ac725a2ead5ea368033dd57a52f
--- /dev/null
+++ b/the_social_network/manage.py
@@ -0,0 +1,22 @@
+#!/usr/bin/env python
+"""Django's command-line utility for administrative tasks."""
+import os
+import sys
+
+
+def main():
+    """Run administrative tasks."""
+    os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'the_social_network.settings')
+    try:
+        from django.core.management import execute_from_command_line
+    except ImportError as exc:
+        raise ImportError(
+            "Couldn't import Django. Are you sure it's installed and "
+            "available on your PYTHONPATH environment variable? Did you "
+            "forget to activate a virtual environment?"
+        ) from exc
+    execute_from_command_line(sys.argv)
+
+
+if __name__ == '__main__':
+    main()
diff --git a/the_social_network/the_social_network/__init__.py b/the_social_network/the_social_network/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/the_social_network/the_social_network/asgi.py b/the_social_network/the_social_network/asgi.py
new file mode 100644
index 0000000000000000000000000000000000000000..5fea914abe523144f7d1c154e3a0c3da2990c303
--- /dev/null
+++ b/the_social_network/the_social_network/asgi.py
@@ -0,0 +1,16 @@
+"""
+ASGI config for the_social_network project.
+
+It exposes the ASGI callable as a module-level variable named ``application``.
+
+For more information on this file, see
+https://docs.djangoproject.com/en/3.2/howto/deployment/asgi/
+"""
+
+import os
+
+from django.core.asgi import get_asgi_application
+
+os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'the_social_network.settings')
+
+application = get_asgi_application()
diff --git a/the_social_network/the_social_network/settings.py b/the_social_network/the_social_network/settings.py
new file mode 100644
index 0000000000000000000000000000000000000000..f19f1ca7142d95bd8b298c2155864d72f63a29f7
--- /dev/null
+++ b/the_social_network/the_social_network/settings.py
@@ -0,0 +1,137 @@
+"""
+Django settings for the_social_network project.
+
+Generated by 'django-admin startproject' using Django 3.2.9.
+
+For more information on this file, see
+https://docs.djangoproject.com/en/3.2/topics/settings/
+
+For the full list of settings and their values, see
+https://docs.djangoproject.com/en/3.2/ref/settings/
+"""
+import os
+from pathlib import Path
+
+# Build paths inside the project like this: BASE_DIR / 'subdir'.
+BASE_DIR = Path(__file__).resolve().parent.parent
+
+# Quick-start development settings - unsuitable for production
+# See https://docs.djangoproject.com/en/3.2/howto/deployment/checklist/
+
+# SECURITY WARNING: keep the secret key used in production secret!
+SECRET_KEY = 'django-insecure-hpjug(8bb2&mx*lv-$h!a6ried17*-34or7ngwee*1x#f6kak^'
+
+# SECURITY WARNING: don't run with debug turned on in production!
+DEBUG = True
+
+ALLOWED_HOSTS = []
+
+# Application definition
+
+
+INSTALLED_APPS = [
+    'django.contrib.admin',
+    'django.contrib.auth',
+    'django.contrib.contenttypes',
+    'django.contrib.sessions',
+    'django.contrib.messages',
+    'django.contrib.staticfiles',
+    'corsheaders',
+    'rest_framework',
+    'rest_framework.authtoken',
+    'core',
+]
+
+MIDDLEWARE = [
+    'corsheaders.middleware.CorsMiddleware',
+    'django.middleware.security.SecurityMiddleware',
+    'django.contrib.sessions.middleware.SessionMiddleware',
+    'django.middleware.common.CommonMiddleware',
+    'django.middleware.csrf.CsrfViewMiddleware',
+    'django.contrib.auth.middleware.AuthenticationMiddleware',
+    'django.contrib.messages.middleware.MessageMiddleware',
+    'django.middleware.clickjacking.XFrameOptionsMiddleware',
+]
+
+ROOT_URLCONF = 'the_social_network.urls'
+
+TEMPLATES = [
+    {
+        'BACKEND': 'django.template.backends.django.DjangoTemplates',
+        'DIRS': [],
+        'APP_DIRS': True,
+        'OPTIONS': {
+            'context_processors': [
+                'django.template.context_processors.debug',
+                'django.template.context_processors.request',
+                'django.contrib.auth.context_processors.auth',
+                'django.contrib.messages.context_processors.messages',
+            ],
+        },
+    },
+]
+
+WSGI_APPLICATION = 'the_social_network.wsgi.application'
+
+# Database
+# https://docs.djangoproject.com/en/3.2/ref/settings/#databases
+
+DATABASES = {
+    'default': {
+        'ENGINE': 'django.db.backends.sqlite3',
+        'NAME': BASE_DIR / 'db.sqlite3',
+    }
+}
+
+# Password validation
+# https://docs.djangoproject.com/en/3.2/ref/settings/#auth-password-validators
+
+AUTH_PASSWORD_VALIDATORS = [
+    {
+        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
+    },
+    {
+        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
+    },
+    {
+        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
+    },
+    {
+        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
+    },
+]
+
+# Internationalization
+# https://docs.djangoproject.com/en/3.2/topics/i18n/
+
+LANGUAGE_CODE = 'en-us'
+
+TIME_ZONE = 'UTC'
+
+USE_I18N = True
+
+USE_L10N = True
+
+USE_TZ = True
+
+# Static files (CSS, JavaScript, Images)
+# https://docs.djangoproject.com/en/3.2/howto/static-files/
+
+STATIC_URL = '/django_static/'
+STATIC_ROOT = os.path.join(BASE_DIR, "django_static/")
+
+# REST Framework settings
+REST_FRAMEWORK = {
+    'DEFAULT_AUTHENTICATION_CLASSES': [
+        'rest_framework.authentication.TokenAuthentication',
+    ],
+}
+
+# Folder to store media data
+MEDIA_URL = '/media/'
+MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
+
+# Default primary key field type
+# https://docs.djangoproject.com/en/3.2/ref/settings/#default-auto-field
+
+DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
diff --git a/the_social_network/the_social_network/urls.py b/the_social_network/the_social_network/urls.py
new file mode 100644
index 0000000000000000000000000000000000000000..1acc893cfeb1de6fb679a7bedcf40ccf3f608500
--- /dev/null
+++ b/the_social_network/the_social_network/urls.py
@@ -0,0 +1,28 @@
+"""the_social_network URL Configuration
+
+The `urlpatterns` list routes URLs to views. For more information please see:
+    https://docs.djangoproject.com/en/3.2/topics/http/urls/
+Examples:
+Function views
+    1. Add an import:  from my_app import views
+    2. Add a URL to urlpatterns:  path('', views.home, name='home')
+Class-based views
+    1. Add an import:  from other_app.views import Home
+    2. Add a URL to urlpatterns:  path('', Home.as_view(), name='home')
+Including another URLconf
+    1. Import the include() function: from django.urls import include, path
+    2. Add a URL to urlpatterns:  path('blog/', include('blog.urls'))
+"""
+from django.conf import settings
+from django.conf.urls import url
+from django.conf.urls.static import static
+from django.contrib import admin
+from django.urls import path, include
+
+urlpatterns = [
+                  path('admin/', admin.site.urls),
+                  url(r'^authentication/', include('core.urls.authenticationUrls')),
+                  url(r'^accounts/', include('core.urls.accountUrls')),
+                  url(r'^search/', include('core.urls.searchUrls')),
+                  url(r'^contents/', include('core.urls.contentUrls')),
+              ] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
diff --git a/the_social_network/the_social_network/wsgi.py b/the_social_network/the_social_network/wsgi.py
new file mode 100644
index 0000000000000000000000000000000000000000..21d6cfa778697bf5ead31733e197c347f0d7e97f
--- /dev/null
+++ b/the_social_network/the_social_network/wsgi.py
@@ -0,0 +1,16 @@
+"""
+WSGI config for the_social_network project.
+
+It exposes the WSGI callable as a module-level variable named ``application``.
+
+For more information on this file, see
+https://docs.djangoproject.com/en/3.2/howto/deployment/wsgi/
+"""
+
+import os
+
+from django.core.wsgi import get_wsgi_application
+
+os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'the_social_network.settings')
+
+application = get_wsgi_application()