diff --git a/backup.sh b/backend/backup.sh
similarity index 100%
rename from backup.sh
rename to backend/backup.sh
diff --git a/example.env b/backend/example.env
similarity index 100%
rename from example.env
rename to backend/example.env
diff --git a/manage.py b/backend/manage.py
similarity index 100%
rename from manage.py
rename to backend/manage.py
diff --git a/muzak/__init__.py b/backend/muzak/__init__.py
similarity index 100%
rename from muzak/__init__.py
rename to backend/muzak/__init__.py
diff --git a/muzak/asgi.py b/backend/muzak/asgi.py
similarity index 100%
rename from muzak/asgi.py
rename to backend/muzak/asgi.py
diff --git a/muzak/celery.py b/backend/muzak/celery.py
similarity index 100%
rename from muzak/celery.py
rename to backend/muzak/celery.py
diff --git a/muzak/settings.py b/backend/muzak/settings.py
similarity index 100%
rename from muzak/settings.py
rename to backend/muzak/settings.py
diff --git a/muzak/urls.py b/backend/muzak/urls.py
similarity index 100%
rename from muzak/urls.py
rename to backend/muzak/urls.py
diff --git a/muzak/wsgi.py b/backend/muzak/wsgi.py
similarity index 100%
rename from muzak/wsgi.py
rename to backend/muzak/wsgi.py
diff --git a/playlist/__init__.py b/backend/playlist/__init__.py
similarity index 100%
rename from playlist/__init__.py
rename to backend/playlist/__init__.py
diff --git a/playlist/admin.py b/backend/playlist/admin.py
similarity index 100%
rename from playlist/admin.py
rename to backend/playlist/admin.py
diff --git a/playlist/apps.py b/backend/playlist/apps.py
similarity index 100%
rename from playlist/apps.py
rename to backend/playlist/apps.py
diff --git a/backend/playlist/migrations/0001_initial.py b/backend/playlist/migrations/0001_initial.py
new file mode 100644
index 0000000..531def3
--- /dev/null
+++ b/backend/playlist/migrations/0001_initial.py
@@ -0,0 +1,48 @@
+# Generated by Django 5.0.1 on 2024-02-04 22:50
+
+import django.db.models.deletion
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ initial = True
+
+ dependencies = [
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='Artist',
+ fields=[
+ ('id', models.CharField(max_length=128, primary_key=True, serialize=False)),
+ ('name', models.CharField(max_length=255)),
+ ('popularity', models.SmallIntegerField(blank=True, null=True)),
+ ('genres', models.JSONField()),
+ ],
+ ),
+ migrations.CreateModel(
+ name='Album',
+ fields=[
+ ('id', models.CharField(max_length=128, primary_key=True, serialize=False)),
+ ('name', models.CharField(max_length=255)),
+ ('album_type', models.CharField(max_length=255)),
+ ('total_tracks', models.PositiveSmallIntegerField(null=True)),
+ ('image', models.ImageField(upload_to='albums/')),
+ ('artists', models.ManyToManyField(to='playlist.artist')),
+ ],
+ ),
+ migrations.CreateModel(
+ name='Track',
+ fields=[
+ ('id', models.CharField(max_length=128, primary_key=True, serialize=False)),
+ ('title', models.CharField(max_length=255)),
+ ('explicit', models.BooleanField(default=False)),
+ ('duration_ms', models.PositiveIntegerField(null=True)),
+ ('popularity', models.PositiveIntegerField(null=True)),
+ ('banter', models.TextField()),
+ ('album', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='playlist.album')),
+ ('artists', models.ManyToManyField(to='playlist.artist')),
+ ],
+ ),
+ ]
diff --git a/backend/playlist/migrations/0002_track_old.py b/backend/playlist/migrations/0002_track_old.py
new file mode 100644
index 0000000..2de80e7
--- /dev/null
+++ b/backend/playlist/migrations/0002_track_old.py
@@ -0,0 +1,18 @@
+# Generated by Django 5.0.1 on 2024-02-05 21:06
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('playlist', '0001_initial'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='track',
+ name='old',
+ field=models.BooleanField(default=False),
+ ),
+ ]
diff --git a/backend/playlist/migrations/0003_rename_title_track_name.py b/backend/playlist/migrations/0003_rename_title_track_name.py
new file mode 100644
index 0000000..146e1ce
--- /dev/null
+++ b/backend/playlist/migrations/0003_rename_title_track_name.py
@@ -0,0 +1,18 @@
+# Generated by Django 5.0.1 on 2024-02-05 21:11
+
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('playlist', '0002_track_old'),
+ ]
+
+ operations = [
+ migrations.RenameField(
+ model_name='track',
+ old_name='title',
+ new_name='name',
+ ),
+ ]
diff --git a/backend/playlist/migrations/0004_alter_artist_genres_alter_track_banter.py b/backend/playlist/migrations/0004_alter_artist_genres_alter_track_banter.py
new file mode 100644
index 0000000..788823e
--- /dev/null
+++ b/backend/playlist/migrations/0004_alter_artist_genres_alter_track_banter.py
@@ -0,0 +1,23 @@
+# Generated by Django 5.0.1 on 2024-02-05 22:11
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('playlist', '0003_rename_title_track_name'),
+ ]
+
+ operations = [
+ migrations.AlterField(
+ model_name='artist',
+ name='genres',
+ field=models.JSONField(null=True),
+ ),
+ migrations.AlterField(
+ model_name='track',
+ name='banter',
+ field=models.TextField(blank=True),
+ ),
+ ]
diff --git a/backend/playlist/migrations/0005_vote.py b/backend/playlist/migrations/0005_vote.py
new file mode 100644
index 0000000..a4c760a
--- /dev/null
+++ b/backend/playlist/migrations/0005_vote.py
@@ -0,0 +1,28 @@
+# Generated by Django 5.0.1 on 2024-02-07 12:26
+
+import django.db.models.deletion
+from django.conf import settings
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('playlist', '0004_alter_artist_genres_alter_track_banter'),
+ migrations.swappable_dependency(settings.AUTH_USER_MODEL),
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='Vote',
+ fields=[
+ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('points', models.IntegerField()),
+ ('track', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='playlist.track')),
+ ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
+ ],
+ options={
+ 'unique_together': {('user', 'track')},
+ },
+ ),
+ ]
diff --git a/backend/playlist/migrations/0006_track_banter_done.py b/backend/playlist/migrations/0006_track_banter_done.py
new file mode 100644
index 0000000..ba4b771
--- /dev/null
+++ b/backend/playlist/migrations/0006_track_banter_done.py
@@ -0,0 +1,18 @@
+# Generated by Django 5.0.1 on 2024-02-07 19:48
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('playlist', '0005_vote'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='track',
+ name='banter_done',
+ field=models.BooleanField(default=False),
+ ),
+ ]
diff --git a/backend/playlist/migrations/0007_album_image_url.py b/backend/playlist/migrations/0007_album_image_url.py
new file mode 100644
index 0000000..d75eaa5
--- /dev/null
+++ b/backend/playlist/migrations/0007_album_image_url.py
@@ -0,0 +1,18 @@
+# Generated by Django 5.0.1 on 2024-02-12 13:42
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('playlist', '0006_track_banter_done'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='album',
+ name='image_url',
+ field=models.URLField(null=True),
+ ),
+ ]
diff --git a/backend/playlist/migrations/0008_background_profile.py b/backend/playlist/migrations/0008_background_profile.py
new file mode 100644
index 0000000..50813df
--- /dev/null
+++ b/backend/playlist/migrations/0008_background_profile.py
@@ -0,0 +1,32 @@
+# Generated by Django 5.0.1 on 2024-02-21 13:26
+
+import django.db.models.deletion
+from django.conf import settings
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('playlist', '0007_album_image_url'),
+ migrations.swappable_dependency(settings.AUTH_USER_MODEL),
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='Background',
+ fields=[
+ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('image', models.ImageField(upload_to='wallpapers/')),
+ ('repeat', models.BooleanField(default=False)),
+ ],
+ ),
+ migrations.CreateModel(
+ name='Profile',
+ fields=[
+ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('background', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='playlist.background')),
+ ('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
+ ],
+ ),
+ ]
diff --git a/backend/playlist/migrations/0009_background_name.py b/backend/playlist/migrations/0009_background_name.py
new file mode 100644
index 0000000..a8d24c6
--- /dev/null
+++ b/backend/playlist/migrations/0009_background_name.py
@@ -0,0 +1,19 @@
+# Generated by Django 5.0.1 on 2024-02-21 13:31
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('playlist', '0008_background_profile'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='background',
+ name='name',
+ field=models.CharField(default='Wallpaper', max_length=128),
+ preserve_default=False,
+ ),
+ ]
diff --git a/backend/playlist/migrations/0010_background_color.py b/backend/playlist/migrations/0010_background_color.py
new file mode 100644
index 0000000..38b18ea
--- /dev/null
+++ b/backend/playlist/migrations/0010_background_color.py
@@ -0,0 +1,18 @@
+# Generated by Django 5.0.1 on 2024-02-21 14:38
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('playlist', '0009_background_name'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='background',
+ name='color',
+ field=models.CharField(blank=True, max_length=32),
+ ),
+ ]
diff --git a/backend/playlist/migrations/0011_alter_background_image.py b/backend/playlist/migrations/0011_alter_background_image.py
new file mode 100644
index 0000000..411f103
--- /dev/null
+++ b/backend/playlist/migrations/0011_alter_background_image.py
@@ -0,0 +1,18 @@
+# Generated by Django 5.0.1 on 2024-02-21 14:38
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('playlist', '0010_background_color'),
+ ]
+
+ operations = [
+ migrations.AlterField(
+ model_name='background',
+ name='image',
+ field=models.ImageField(null=True, upload_to='wallpapers/'),
+ ),
+ ]
diff --git a/backend/playlist/migrations/0012_alter_background_image.py b/backend/playlist/migrations/0012_alter_background_image.py
new file mode 100644
index 0000000..9f5bbf5
--- /dev/null
+++ b/backend/playlist/migrations/0012_alter_background_image.py
@@ -0,0 +1,18 @@
+# Generated by Django 5.0.1 on 2024-02-21 14:39
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('playlist', '0011_alter_background_image'),
+ ]
+
+ operations = [
+ migrations.AlterField(
+ model_name='background',
+ name='image',
+ field=models.ImageField(blank=True, null=True, upload_to='wallpapers/'),
+ ),
+ ]
diff --git a/backend/playlist/migrations/0013_profile_last_voted.py b/backend/playlist/migrations/0013_profile_last_voted.py
new file mode 100644
index 0000000..0265d00
--- /dev/null
+++ b/backend/playlist/migrations/0013_profile_last_voted.py
@@ -0,0 +1,19 @@
+# Generated by Django 5.0.1 on 2024-02-26 18:38
+
+import django.db.models.deletion
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('playlist', '0012_alter_background_image'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='profile',
+ name='last_voted',
+ field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='playlist.track'),
+ ),
+ ]
diff --git a/backend/playlist/migrations/0014_profile_quota_profile_quota_last_updated.py b/backend/playlist/migrations/0014_profile_quota_profile_quota_last_updated.py
new file mode 100644
index 0000000..005b083
--- /dev/null
+++ b/backend/playlist/migrations/0014_profile_quota_profile_quota_last_updated.py
@@ -0,0 +1,23 @@
+# Generated by Django 5.0.1 on 2024-02-26 20:46
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('playlist', '0013_profile_last_voted'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='profile',
+ name='quota',
+ field=models.FloatField(default=10.0),
+ ),
+ migrations.AddField(
+ model_name='profile',
+ name='quota_last_updated',
+ field=models.DateTimeField(auto_now=True),
+ ),
+ ]
diff --git a/backend/playlist/migrations/0015_alter_profile_quota_last_updated.py b/backend/playlist/migrations/0015_alter_profile_quota_last_updated.py
new file mode 100644
index 0000000..d72a495
--- /dev/null
+++ b/backend/playlist/migrations/0015_alter_profile_quota_last_updated.py
@@ -0,0 +1,19 @@
+# Generated by Django 5.0.1 on 2024-02-26 22:17
+
+import django.utils.timezone
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('playlist', '0014_profile_quota_profile_quota_last_updated'),
+ ]
+
+ operations = [
+ migrations.AlterField(
+ model_name='profile',
+ name='quota_last_updated',
+ field=models.DateTimeField(default=django.utils.timezone.now),
+ ),
+ ]
diff --git a/backend/playlist/migrations/0016_profile_spt_access_token_profile_spt_refresh_token_and_more.py b/backend/playlist/migrations/0016_profile_spt_access_token_profile_spt_refresh_token_and_more.py
new file mode 100644
index 0000000..d214378
--- /dev/null
+++ b/backend/playlist/migrations/0016_profile_spt_access_token_profile_spt_refresh_token_and_more.py
@@ -0,0 +1,31 @@
+# Generated by Django 5.0.1 on 2024-03-08 23:53
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('playlist', '0015_alter_profile_quota_last_updated'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='profile',
+ name='spt_access_token',
+ field=models.CharField(default='', max_length=128),
+ ),
+ migrations.AddField(
+ model_name='profile',
+ name='spt_refresh_token',
+ field=models.CharField(default='', max_length=128),
+ ),
+ migrations.CreateModel(
+ name='Playlist',
+ fields=[
+ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('name', models.CharField(max_length=255)),
+ ('tracks', models.ManyToManyField(to='playlist.track')),
+ ],
+ ),
+ ]
diff --git a/backend/playlist/migrations/0017_profile_spt_expires.py b/backend/playlist/migrations/0017_profile_spt_expires.py
new file mode 100644
index 0000000..0e7c65b
--- /dev/null
+++ b/backend/playlist/migrations/0017_profile_spt_expires.py
@@ -0,0 +1,18 @@
+# Generated by Django 5.0.1 on 2024-03-08 23:56
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('playlist', '0016_profile_spt_access_token_profile_spt_refresh_token_and_more'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='profile',
+ name='spt_expires',
+ field=models.DateTimeField(default=None, null=True),
+ ),
+ ]
diff --git a/backend/playlist/migrations/0018_alter_profile_spt_access_token_and_more.py b/backend/playlist/migrations/0018_alter_profile_spt_access_token_and_more.py
new file mode 100644
index 0000000..b6f1d5f
--- /dev/null
+++ b/backend/playlist/migrations/0018_alter_profile_spt_access_token_and_more.py
@@ -0,0 +1,23 @@
+# Generated by Django 5.0.1 on 2024-03-13 08:38
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('playlist', '0017_profile_spt_expires'),
+ ]
+
+ operations = [
+ migrations.AlterField(
+ model_name='profile',
+ name='spt_access_token',
+ field=models.CharField(default='', max_length=128, null=True),
+ ),
+ migrations.AlterField(
+ model_name='profile',
+ name='spt_refresh_token',
+ field=models.CharField(default='', max_length=128, null=True),
+ ),
+ ]
diff --git a/backend/playlist/migrations/0019_vote_skipped.py b/backend/playlist/migrations/0019_vote_skipped.py
new file mode 100644
index 0000000..2953c9d
--- /dev/null
+++ b/backend/playlist/migrations/0019_vote_skipped.py
@@ -0,0 +1,18 @@
+# Generated by Django 5.0.4 on 2024-07-20 06:58
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('playlist', '0018_alter_profile_spt_access_token_and_more'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='vote',
+ name='skipped',
+ field=models.BooleanField(default=False),
+ ),
+ ]
diff --git a/backend/playlist/migrations/0020_track_nominated_by_alter_profile_spt_access_token_and_more.py b/backend/playlist/migrations/0020_track_nominated_by_alter_profile_spt_access_token_and_more.py
new file mode 100644
index 0000000..7f2073a
--- /dev/null
+++ b/backend/playlist/migrations/0020_track_nominated_by_alter_profile_spt_access_token_and_more.py
@@ -0,0 +1,31 @@
+# Generated by Django 5.0.4 on 2024-07-21 07:59
+
+import django.db.models.deletion
+from django.conf import settings
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('playlist', '0019_vote_skipped'),
+ migrations.swappable_dependency(settings.AUTH_USER_MODEL),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='track',
+ name='nominated_by',
+ field=models.ForeignKey(default=None, null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL),
+ ),
+ migrations.AlterField(
+ model_name='profile',
+ name='spt_access_token',
+ field=models.CharField(blank=True, default='', max_length=256, null=True),
+ ),
+ migrations.AlterField(
+ model_name='profile',
+ name='spt_refresh_token',
+ field=models.CharField(blank=True, default='', max_length=256, null=True),
+ ),
+ ]
diff --git a/backend/playlist/migrations/0021_track_from_playlist_alter_track_album_and_more.py b/backend/playlist/migrations/0021_track_from_playlist_alter_track_album_and_more.py
new file mode 100644
index 0000000..3dddeff
--- /dev/null
+++ b/backend/playlist/migrations/0021_track_from_playlist_alter_track_album_and_more.py
@@ -0,0 +1,46 @@
+# Generated by Django 5.0.4 on 2024-07-22 20:32
+
+import django.db.models.deletion
+from django.conf import settings
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('playlist', '0020_track_nominated_by_alter_profile_spt_access_token_and_more'),
+ migrations.swappable_dependency(settings.AUTH_USER_MODEL),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='track',
+ name='from_playlist',
+ field=models.CharField(blank=True, default=None, max_length=255, null=True),
+ ),
+ migrations.AlterField(
+ model_name='track',
+ name='album',
+ field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='playlist.album'),
+ ),
+ migrations.AlterField(
+ model_name='track',
+ name='banter',
+ field=models.TextField(blank=True, null=True),
+ ),
+ migrations.AlterField(
+ model_name='track',
+ name='duration_ms',
+ field=models.PositiveIntegerField(blank=True, null=True),
+ ),
+ migrations.AlterField(
+ model_name='track',
+ name='nominated_by',
+ field=models.ForeignKey(blank=True, default=None, null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL),
+ ),
+ migrations.AlterField(
+ model_name='track',
+ name='popularity',
+ field=models.PositiveIntegerField(blank=True, null=True),
+ ),
+ ]
diff --git a/backend/playlist/migrations/0022_background_cover.py b/backend/playlist/migrations/0022_background_cover.py
new file mode 100644
index 0000000..9f28d43
--- /dev/null
+++ b/backend/playlist/migrations/0022_background_cover.py
@@ -0,0 +1,18 @@
+# Generated by Django 5.0.4 on 2024-07-23 11:29
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('playlist', '0021_track_from_playlist_alter_track_album_and_more'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='background',
+ name='cover',
+ field=models.BooleanField(default=False),
+ ),
+ ]
diff --git a/backend/playlist/migrations/__init__.py b/backend/playlist/migrations/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/playlist/models/__init__.py b/backend/playlist/models/__init__.py
similarity index 100%
rename from playlist/models/__init__.py
rename to backend/playlist/models/__init__.py
diff --git a/playlist/models/album.py b/backend/playlist/models/album.py
similarity index 100%
rename from playlist/models/album.py
rename to backend/playlist/models/album.py
diff --git a/playlist/models/artist.py b/backend/playlist/models/artist.py
similarity index 100%
rename from playlist/models/artist.py
rename to backend/playlist/models/artist.py
diff --git a/playlist/models/playlist.py b/backend/playlist/models/playlist.py
similarity index 100%
rename from playlist/models/playlist.py
rename to backend/playlist/models/playlist.py
diff --git a/playlist/models/profile.py b/backend/playlist/models/profile.py
similarity index 100%
rename from playlist/models/profile.py
rename to backend/playlist/models/profile.py
diff --git a/playlist/models/track.py b/backend/playlist/models/track.py
similarity index 100%
rename from playlist/models/track.py
rename to backend/playlist/models/track.py
diff --git a/playlist/models/vote.py b/backend/playlist/models/vote.py
similarity index 100%
rename from playlist/models/vote.py
rename to backend/playlist/models/vote.py
diff --git a/playlist/serializers/__init__.py b/backend/playlist/serializers/__init__.py
similarity index 100%
rename from playlist/serializers/__init__.py
rename to backend/playlist/serializers/__init__.py
diff --git a/playlist/serializers/album.py b/backend/playlist/serializers/album.py
similarity index 100%
rename from playlist/serializers/album.py
rename to backend/playlist/serializers/album.py
diff --git a/playlist/serializers/artist.py b/backend/playlist/serializers/artist.py
similarity index 100%
rename from playlist/serializers/artist.py
rename to backend/playlist/serializers/artist.py
diff --git a/playlist/serializers/profile.py b/backend/playlist/serializers/profile.py
similarity index 100%
rename from playlist/serializers/profile.py
rename to backend/playlist/serializers/profile.py
diff --git a/playlist/serializers/track.py b/backend/playlist/serializers/track.py
similarity index 100%
rename from playlist/serializers/track.py
rename to backend/playlist/serializers/track.py
diff --git a/playlist/serializers/user.py b/backend/playlist/serializers/user.py
similarity index 100%
rename from playlist/serializers/user.py
rename to backend/playlist/serializers/user.py
diff --git a/playlist/serializers/vote.py b/backend/playlist/serializers/vote.py
similarity index 100%
rename from playlist/serializers/vote.py
rename to backend/playlist/serializers/vote.py
diff --git a/playlist/spotify.py b/backend/playlist/spotify.py
similarity index 100%
rename from playlist/spotify.py
rename to backend/playlist/spotify.py
diff --git a/playlist/static/98.css/LICENSE b/backend/playlist/static/98.css/LICENSE
similarity index 100%
rename from playlist/static/98.css/LICENSE
rename to backend/playlist/static/98.css/LICENSE
diff --git a/playlist/static/98.css/fonts/ms_sans_serif.woff b/backend/playlist/static/98.css/fonts/ms_sans_serif.woff
similarity index 100%
rename from playlist/static/98.css/fonts/ms_sans_serif.woff
rename to backend/playlist/static/98.css/fonts/ms_sans_serif.woff
diff --git a/playlist/static/98.css/fonts/ms_sans_serif.woff2 b/backend/playlist/static/98.css/fonts/ms_sans_serif.woff2
similarity index 100%
rename from playlist/static/98.css/fonts/ms_sans_serif.woff2
rename to backend/playlist/static/98.css/fonts/ms_sans_serif.woff2
diff --git a/playlist/static/98.css/fonts/ms_sans_serif_bold.woff b/backend/playlist/static/98.css/fonts/ms_sans_serif_bold.woff
similarity index 100%
rename from playlist/static/98.css/fonts/ms_sans_serif_bold.woff
rename to backend/playlist/static/98.css/fonts/ms_sans_serif_bold.woff
diff --git a/playlist/static/98.css/fonts/ms_sans_serif_bold.woff2 b/backend/playlist/static/98.css/fonts/ms_sans_serif_bold.woff2
similarity index 100%
rename from playlist/static/98.css/fonts/ms_sans_serif_bold.woff2
rename to backend/playlist/static/98.css/fonts/ms_sans_serif_bold.woff2
diff --git a/playlist/static/98.css/style.css b/backend/playlist/static/98.css/style.css
similarity index 100%
rename from playlist/static/98.css/style.css
rename to backend/playlist/static/98.css/style.css
diff --git a/playlist/static/android-chrome-192x192.png b/backend/playlist/static/android-chrome-192x192.png
similarity index 100%
rename from playlist/static/android-chrome-192x192.png
rename to backend/playlist/static/android-chrome-192x192.png
diff --git a/playlist/static/android-chrome-512x512.png b/backend/playlist/static/android-chrome-512x512.png
similarity index 100%
rename from playlist/static/android-chrome-512x512.png
rename to backend/playlist/static/android-chrome-512x512.png
diff --git a/playlist/static/apple-touch-icon.png b/backend/playlist/static/apple-touch-icon.png
similarity index 100%
rename from playlist/static/apple-touch-icon.png
rename to backend/playlist/static/apple-touch-icon.png
diff --git a/playlist/static/bsod.css b/backend/playlist/static/bsod.css
similarity index 100%
rename from playlist/static/bsod.css
rename to backend/playlist/static/bsod.css
diff --git a/playlist/static/favicon-16x16.png b/backend/playlist/static/favicon-16x16.png
similarity index 100%
rename from playlist/static/favicon-16x16.png
rename to backend/playlist/static/favicon-16x16.png
diff --git a/playlist/static/favicon-32x32.png b/backend/playlist/static/favicon-32x32.png
similarity index 100%
rename from playlist/static/favicon-32x32.png
rename to backend/playlist/static/favicon-32x32.png
diff --git a/playlist/static/favicon.ico b/backend/playlist/static/favicon.ico
similarity index 100%
rename from playlist/static/favicon.ico
rename to backend/playlist/static/favicon.ico
diff --git a/playlist/static/favicon_io.zip b/backend/playlist/static/favicon_io.zip
similarity index 100%
rename from playlist/static/favicon_io.zip
rename to backend/playlist/static/favicon_io.zip
diff --git a/playlist/static/img/back.svg b/backend/playlist/static/img/back.svg
similarity index 100%
rename from playlist/static/img/back.svg
rename to backend/playlist/static/img/back.svg
diff --git a/playlist/static/img/check.png b/backend/playlist/static/img/check.png
similarity index 100%
rename from playlist/static/img/check.png
rename to backend/playlist/static/img/check.png
diff --git a/playlist/static/img/download.png b/backend/playlist/static/img/download.png
similarity index 100%
rename from playlist/static/img/download.png
rename to backend/playlist/static/img/download.png
diff --git a/playlist/static/img/draakje/draakje-headphones.gif b/backend/playlist/static/img/draakje/draakje-headphones.gif
similarity index 100%
rename from playlist/static/img/draakje/draakje-headphones.gif
rename to backend/playlist/static/img/draakje/draakje-headphones.gif
diff --git a/playlist/static/img/draakje/draakje-headphones2.gif b/backend/playlist/static/img/draakje/draakje-headphones2.gif
similarity index 100%
rename from playlist/static/img/draakje/draakje-headphones2.gif
rename to backend/playlist/static/img/draakje/draakje-headphones2.gif
diff --git a/playlist/static/img/draakje/draakje-headphones3.gif b/backend/playlist/static/img/draakje/draakje-headphones3.gif
similarity index 100%
rename from playlist/static/img/draakje/draakje-headphones3.gif
rename to backend/playlist/static/img/draakje/draakje-headphones3.gif
diff --git a/playlist/static/img/draakje/draakje-waiting.gif b/backend/playlist/static/img/draakje/draakje-waiting.gif
similarity index 100%
rename from playlist/static/img/draakje/draakje-waiting.gif
rename to backend/playlist/static/img/draakje/draakje-waiting.gif
diff --git a/playlist/static/img/eject.svg b/backend/playlist/static/img/eject.svg
similarity index 100%
rename from playlist/static/img/eject.svg
rename to backend/playlist/static/img/eject.svg
diff --git a/playlist/static/img/error.png b/backend/playlist/static/img/error.png
similarity index 100%
rename from playlist/static/img/error.png
rename to backend/playlist/static/img/error.png
diff --git a/playlist/static/img/forward.svg b/backend/playlist/static/img/forward.svg
similarity index 100%
rename from playlist/static/img/forward.svg
rename to backend/playlist/static/img/forward.svg
diff --git a/playlist/static/img/gears.png b/backend/playlist/static/img/gears.png
similarity index 100%
rename from playlist/static/img/gears.png
rename to backend/playlist/static/img/gears.png
diff --git a/playlist/static/img/login.png b/backend/playlist/static/img/login.png
similarity index 100%
rename from playlist/static/img/login.png
rename to backend/playlist/static/img/login.png
diff --git a/playlist/static/img/muted.png b/backend/playlist/static/img/muted.png
similarity index 100%
rename from playlist/static/img/muted.png
rename to backend/playlist/static/img/muted.png
diff --git a/playlist/static/img/next.svg b/backend/playlist/static/img/next.svg
similarity index 100%
rename from playlist/static/img/next.svg
rename to backend/playlist/static/img/next.svg
diff --git a/playlist/static/img/pause-inactive.svg b/backend/playlist/static/img/pause-inactive.svg
similarity index 100%
rename from playlist/static/img/pause-inactive.svg
rename to backend/playlist/static/img/pause-inactive.svg
diff --git a/playlist/static/img/pause.svg b/backend/playlist/static/img/pause.svg
similarity index 100%
rename from playlist/static/img/pause.svg
rename to backend/playlist/static/img/pause.svg
diff --git a/playlist/static/img/pawel.png b/backend/playlist/static/img/pawel.png
similarity index 100%
rename from playlist/static/img/pawel.png
rename to backend/playlist/static/img/pawel.png
diff --git a/playlist/static/img/play-inactive.svg b/backend/playlist/static/img/play-inactive.svg
similarity index 100%
rename from playlist/static/img/play-inactive.svg
rename to backend/playlist/static/img/play-inactive.svg
diff --git a/playlist/static/img/play.svg b/backend/playlist/static/img/play.svg
similarity index 100%
rename from playlist/static/img/play.svg
rename to backend/playlist/static/img/play.svg
diff --git a/playlist/static/img/prev.svg b/backend/playlist/static/img/prev.svg
similarity index 100%
rename from playlist/static/img/prev.svg
rename to backend/playlist/static/img/prev.svg
diff --git a/playlist/static/img/seek.svg b/backend/playlist/static/img/seek.svg
similarity index 100%
rename from playlist/static/img/seek.svg
rename to backend/playlist/static/img/seek.svg
diff --git a/playlist/static/img/slider.svg b/backend/playlist/static/img/slider.svg
similarity index 100%
rename from playlist/static/img/slider.svg
rename to backend/playlist/static/img/slider.svg
diff --git a/playlist/static/img/sound.png b/backend/playlist/static/img/sound.png
similarity index 100%
rename from playlist/static/img/sound.png
rename to backend/playlist/static/img/sound.png
diff --git a/playlist/static/img/spotify-cancel.png b/backend/playlist/static/img/spotify-cancel.png
similarity index 100%
rename from playlist/static/img/spotify-cancel.png
rename to backend/playlist/static/img/spotify-cancel.png
diff --git a/playlist/static/img/spotify.png b/backend/playlist/static/img/spotify.png
similarity index 100%
rename from playlist/static/img/spotify.png
rename to backend/playlist/static/img/spotify.png
diff --git a/playlist/static/img/star-inactive.png b/backend/playlist/static/img/star-inactive.png
similarity index 100%
rename from playlist/static/img/star-inactive.png
rename to backend/playlist/static/img/star-inactive.png
diff --git a/playlist/static/img/star.png b/backend/playlist/static/img/star.png
similarity index 100%
rename from playlist/static/img/star.png
rename to backend/playlist/static/img/star.png
diff --git a/playlist/static/img/stop-inactive.svg b/backend/playlist/static/img/stop-inactive.svg
similarity index 100%
rename from playlist/static/img/stop-inactive.svg
rename to backend/playlist/static/img/stop-inactive.svg
diff --git a/playlist/static/img/stop.svg b/backend/playlist/static/img/stop.svg
similarity index 100%
rename from playlist/static/img/stop.svg
rename to backend/playlist/static/img/stop.svg
diff --git a/playlist/static/img/undo.png b/backend/playlist/static/img/undo.png
similarity index 100%
rename from playlist/static/img/undo.png
rename to backend/playlist/static/img/undo.png
diff --git a/playlist/static/img/vol-select.svg b/backend/playlist/static/img/vol-select.svg
similarity index 100%
rename from playlist/static/img/vol-select.svg
rename to backend/playlist/static/img/vol-select.svg
diff --git a/playlist/static/img/volume.png b/backend/playlist/static/img/volume.png
similarity index 100%
rename from playlist/static/img/volume.png
rename to backend/playlist/static/img/volume.png
diff --git a/playlist/static/img/warning.png b/backend/playlist/static/img/warning.png
similarity index 100%
rename from playlist/static/img/warning.png
rename to backend/playlist/static/img/warning.png
diff --git a/playlist/static/js/countdown.js b/backend/playlist/static/js/countdown.js
similarity index 100%
rename from playlist/static/js/countdown.js
rename to backend/playlist/static/js/countdown.js
diff --git a/playlist/static/js/htmx.min.js b/backend/playlist/static/js/htmx.min.js
similarity index 100%
rename from playlist/static/js/htmx.min.js
rename to backend/playlist/static/js/htmx.min.js
diff --git a/playlist/static/js/interact.js b/backend/playlist/static/js/interact.js
similarity index 100%
rename from playlist/static/js/interact.js
rename to backend/playlist/static/js/interact.js
diff --git a/playlist/static/kankerherrie.mp3 b/backend/playlist/static/kankerherrie.mp3
similarity index 100%
rename from playlist/static/kankerherrie.mp3
rename to backend/playlist/static/kankerherrie.mp3
diff --git a/playlist/static/site.webmanifest b/backend/playlist/static/site.webmanifest
similarity index 100%
rename from playlist/static/site.webmanifest
rename to backend/playlist/static/site.webmanifest
diff --git a/playlist/static/startup.wav b/backend/playlist/static/startup.wav
similarity index 100%
rename from playlist/static/startup.wav
rename to backend/playlist/static/startup.wav
diff --git a/playlist/static/style.css b/backend/playlist/static/style.css
similarity index 100%
rename from playlist/static/style.css
rename to backend/playlist/static/style.css
diff --git a/playlist/tasks.py b/backend/playlist/tasks.py
similarity index 100%
rename from playlist/tasks.py
rename to backend/playlist/tasks.py
diff --git a/playlist/templates/Base.html b/backend/playlist/templates/Base.html
similarity index 100%
rename from playlist/templates/Base.html
rename to backend/playlist/templates/Base.html
diff --git a/playlist/templates/Clippy.html b/backend/playlist/templates/Clippy.html
similarity index 100%
rename from playlist/templates/Clippy.html
rename to backend/playlist/templates/Clippy.html
diff --git a/playlist/templates/Login.html b/backend/playlist/templates/Login.html
similarity index 100%
rename from playlist/templates/Login.html
rename to backend/playlist/templates/Login.html
diff --git a/playlist/templates/MediaPlayer.html b/backend/playlist/templates/MediaPlayer.html
similarity index 100%
rename from playlist/templates/MediaPlayer.html
rename to backend/playlist/templates/MediaPlayer.html
diff --git a/playlist/templates/Nominate.html b/backend/playlist/templates/Nominate.html
similarity index 100%
rename from playlist/templates/Nominate.html
rename to backend/playlist/templates/Nominate.html
diff --git a/playlist/templates/Overview.html b/backend/playlist/templates/Overview.html
similarity index 100%
rename from playlist/templates/Overview.html
rename to backend/playlist/templates/Overview.html
diff --git a/playlist/templates/PlaylistDetail.html b/backend/playlist/templates/PlaylistDetail.html
similarity index 100%
rename from playlist/templates/PlaylistDetail.html
rename to backend/playlist/templates/PlaylistDetail.html
diff --git a/playlist/templates/PlaylistList.html b/backend/playlist/templates/PlaylistList.html
similarity index 100%
rename from playlist/templates/PlaylistList.html
rename to backend/playlist/templates/PlaylistList.html
diff --git a/playlist/templates/Popup.html b/backend/playlist/templates/Popup.html
similarity index 100%
rename from playlist/templates/Popup.html
rename to backend/playlist/templates/Popup.html
diff --git a/playlist/templates/Settings.html b/backend/playlist/templates/Settings.html
similarity index 100%
rename from playlist/templates/Settings.html
rename to backend/playlist/templates/Settings.html
diff --git a/playlist/templates/Vote.html b/backend/playlist/templates/Vote.html
similarity index 100%
rename from playlist/templates/Vote.html
rename to backend/playlist/templates/Vote.html
diff --git a/playlist/templates/background.css b/backend/playlist/templates/background.css
similarity index 100%
rename from playlist/templates/background.css
rename to backend/playlist/templates/background.css
diff --git a/playlist/templates/head.html b/backend/playlist/templates/head.html
similarity index 100%
rename from playlist/templates/head.html
rename to backend/playlist/templates/head.html
diff --git a/playlist/urls.py b/backend/playlist/urls.py
similarity index 100%
rename from playlist/urls.py
rename to backend/playlist/urls.py
diff --git a/playlist/utils.py b/backend/playlist/utils.py
similarity index 100%
rename from playlist/utils.py
rename to backend/playlist/utils.py
diff --git a/playlist/views/__init__.py b/backend/playlist/views/__init__.py
similarity index 100%
rename from playlist/views/__init__.py
rename to backend/playlist/views/__init__.py
diff --git a/playlist/views/api/album.py b/backend/playlist/views/api/album.py
similarity index 100%
rename from playlist/views/api/album.py
rename to backend/playlist/views/api/album.py
diff --git a/playlist/views/api/artist.py b/backend/playlist/views/api/artist.py
similarity index 100%
rename from playlist/views/api/artist.py
rename to backend/playlist/views/api/artist.py
diff --git a/playlist/views/api/profile.py b/backend/playlist/views/api/profile.py
similarity index 100%
rename from playlist/views/api/profile.py
rename to backend/playlist/views/api/profile.py
diff --git a/playlist/views/api/root.py b/backend/playlist/views/api/root.py
similarity index 100%
rename from playlist/views/api/root.py
rename to backend/playlist/views/api/root.py
diff --git a/playlist/views/api/track.py b/backend/playlist/views/api/track.py
similarity index 70%
rename from playlist/views/api/track.py
rename to backend/playlist/views/api/track.py
index d247839..3249bf8 100644
--- a/playlist/views/api/track.py
+++ b/backend/playlist/views/api/track.py
@@ -32,16 +32,3 @@ class TrackDetailView(APIView):
track = Track.objects.get(pk=id)
serializer = TrackSerializer(track, context={'request': request})
return Response(serializer.data)
- def put(self, request, id):
- track = Track.objects.get(pk=id)
- serializer = TrackSerializer(track, data=request.data, context={'request': request})
- if serializer.is_valid():
- serializer.save()
- return Response(serializer.data)
- return Response(serializer.errors, status=400)
- def post(self, request):
- serializer = TrackSerializer(data=request.data, context={'request': request})
- if serializer.is_valid():
- serializer.save()
- return Response(serializer.data)
- return Response(serializer.errors, status=400)
diff --git a/playlist/views/api/user.py b/backend/playlist/views/api/user.py
similarity index 100%
rename from playlist/views/api/user.py
rename to backend/playlist/views/api/user.py
diff --git a/playlist/views/api/vote.py b/backend/playlist/views/api/vote.py
similarity index 100%
rename from playlist/views/api/vote.py
rename to backend/playlist/views/api/vote.py
diff --git a/playlist/views/static.py b/backend/playlist/views/static.py
similarity index 100%
rename from playlist/views/static.py
rename to backend/playlist/views/static.py
diff --git a/requirements.txt b/backend/requirements.txt
similarity index 100%
rename from requirements.txt
rename to backend/requirements.txt
diff --git a/docker-compose.yml b/docker-compose.yml
new file mode 100644
index 0000000..87d01ff
--- /dev/null
+++ b/docker-compose.yml
@@ -0,0 +1,26 @@
+services:
+ backend:
+ image: python:3.13
+ working_dir: /app/backend
+ volumes:
+ - ./backend:/app/backend
+ command: sh -c "pip install -r requirements.txt && python manage.py migrate && python manage.py runserver 0.0.0.0:8000"
+ ports:
+ - "8001:8000"
+ networks:
+ - app_network
+
+ frontend:
+ image: node:20
+ working_dir: /app/frontend
+ volumes:
+ - ./frontend:/app/frontend
+ command: sh -c "npm install && npm run dev"
+ ports:
+ - "3001:3000"
+ networks:
+ - app_network
+
+networks:
+ app_network:
+ driver: bridge
diff --git a/frontend/next-env.d.ts b/frontend/next-env.d.ts
new file mode 100644
index 0000000..1b3be08
--- /dev/null
+++ b/frontend/next-env.d.ts
@@ -0,0 +1,5 @@
+///