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 @@ +/// +/// + +// NOTE: This file should not be edited +// see https://nextjs.org/docs/app/api-reference/config/typescript for more information. diff --git a/frontend/package-lock.json b/frontend/package-lock.json new file mode 100644 index 0000000..2d84f1b --- /dev/null +++ b/frontend/package-lock.json @@ -0,0 +1,965 @@ +{ + "name": "frontend", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "dependencies": { + "next": "^15.3.3", + "react": "^19.1.0", + "react-dom": "^19.1.0" + }, + "devDependencies": { + "@types/node": "24.0.3", + "@types/react": "19.1.8", + "typescript": "5.8.3" + } + }, + "node_modules/@emnapi/runtime": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.4.3.tgz", + "integrity": "sha512-pBPWdu6MLKROBX05wSNKcNb++m5Er+KQ9QkB+WVM+pW2Kx9hoSrVTnu3BdkI5eBLZoKu/J6mW/B6i6bJB2ytXQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@img/sharp-darwin-arm64": { + "version": "0.34.2", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.34.2.tgz", + "integrity": "sha512-OfXHZPppddivUJnqyKoi5YVeHRkkNE2zUFT2gbpKxp/JZCFYEYubnMg+gOp6lWfasPrTS+KPosKqdI+ELYVDtg==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-arm64": "1.1.0" + } + }, + "node_modules/@img/sharp-darwin-x64": { + "version": "0.34.2", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.34.2.tgz", + "integrity": "sha512-dYvWqmjU9VxqXmjEtjmvHnGqF8GrVjM2Epj9rJ6BUIXvk8slvNDJbhGFvIoXzkDhrJC2jUxNLz/GUjjvSzfw+g==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-x64": "1.1.0" + } + }, + "node_modules/@img/sharp-libvips-darwin-arm64": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.1.0.tgz", + "integrity": "sha512-HZ/JUmPwrJSoM4DIQPv/BfNh9yrOA8tlBbqbLz4JZ5uew2+o22Ik+tHQJcih7QJuSa0zo5coHTfD5J8inqj9DA==", + "cpu": [ + "arm64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-darwin-x64": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.1.0.tgz", + "integrity": "sha512-Xzc2ToEmHN+hfvsl9wja0RlnXEgpKNmftriQp6XzY/RaSfwD9th+MSh0WQKzUreLKKINb3afirxW7A0fz2YWuQ==", + "cpu": [ + "x64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-arm": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.1.0.tgz", + "integrity": "sha512-s8BAd0lwUIvYCJyRdFqvsj+BJIpDBSxs6ivrOPm/R7piTs5UIwY5OjXrP2bqXC9/moGsyRa37eYWYCOGVXxVrA==", + "cpu": [ + "arm" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-arm64": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.1.0.tgz", + "integrity": "sha512-IVfGJa7gjChDET1dK9SekxFFdflarnUB8PwW8aGwEoF3oAsSDuNUTYS+SKDOyOJxQyDC1aPFMuRYLoDInyV9Ew==", + "cpu": [ + "arm64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-ppc64": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.1.0.tgz", + "integrity": "sha512-tiXxFZFbhnkWE2LA8oQj7KYR+bWBkiV2nilRldT7bqoEZ4HiDOcePr9wVDAZPi/Id5fT1oY9iGnDq20cwUz8lQ==", + "cpu": [ + "ppc64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-s390x": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.1.0.tgz", + "integrity": "sha512-xukSwvhguw7COyzvmjydRb3x/09+21HykyapcZchiCUkTThEQEOMtBj9UhkaBRLuBrgLFzQ2wbxdeCCJW/jgJA==", + "cpu": [ + "s390x" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-x64": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.1.0.tgz", + "integrity": "sha512-yRj2+reB8iMg9W5sULM3S74jVS7zqSzHG3Ol/twnAAkAhnGQnpjj6e4ayUz7V+FpKypwgs82xbRdYtchTTUB+Q==", + "cpu": [ + "x64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linuxmusl-arm64": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.1.0.tgz", + "integrity": "sha512-jYZdG+whg0MDK+q2COKbYidaqW/WTz0cc1E+tMAusiDygrM4ypmSCjOJPmFTvHHJ8j/6cAGyeDWZOsK06tP33w==", + "cpu": [ + "arm64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linuxmusl-x64": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.1.0.tgz", + "integrity": "sha512-wK7SBdwrAiycjXdkPnGCPLjYb9lD4l6Ze2gSdAGVZrEL05AOUJESWU2lhlC+Ffn5/G+VKuSm6zzbQSzFX/P65A==", + "cpu": [ + "x64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-linux-arm": { + "version": "0.34.2", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.34.2.tgz", + "integrity": "sha512-0DZzkvuEOqQUP9mo2kjjKNok5AmnOr1jB2XYjkaoNRwpAYMDzRmAqUIa1nRi58S2WswqSfPOWLNOr0FDT3H5RQ==", + "cpu": [ + "arm" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm": "1.1.0" + } + }, + "node_modules/@img/sharp-linux-arm64": { + "version": "0.34.2", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.34.2.tgz", + "integrity": "sha512-D8n8wgWmPDakc83LORcfJepdOSN6MvWNzzz2ux0MnIbOqdieRZwVYY32zxVx+IFUT8er5KPcyU3XXsn+GzG/0Q==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm64": "1.1.0" + } + }, + "node_modules/@img/sharp-linux-s390x": { + "version": "0.34.2", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.34.2.tgz", + "integrity": "sha512-EGZ1xwhBI7dNISwxjChqBGELCWMGDvmxZXKjQRuqMrakhO8QoMgqCrdjnAqJq/CScxfRn+Bb7suXBElKQpPDiw==", + "cpu": [ + "s390x" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-s390x": "1.1.0" + } + }, + "node_modules/@img/sharp-linux-x64": { + "version": "0.34.2", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.34.2.tgz", + "integrity": "sha512-sD7J+h5nFLMMmOXYH4DD9UtSNBD05tWSSdWAcEyzqW8Cn5UxXvsHAxmxSesYUsTOBmUnjtxghKDl15EvfqLFbQ==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-x64": "1.1.0" + } + }, + "node_modules/@img/sharp-linuxmusl-arm64": { + "version": "0.34.2", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.34.2.tgz", + "integrity": "sha512-NEE2vQ6wcxYav1/A22OOxoSOGiKnNmDzCYFOZ949xFmrWZOVII1Bp3NqVVpvj+3UeHMFyN5eP/V5hzViQ5CZNA==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-arm64": "1.1.0" + } + }, + "node_modules/@img/sharp-linuxmusl-x64": { + "version": "0.34.2", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.34.2.tgz", + "integrity": "sha512-DOYMrDm5E6/8bm/yQLCWyuDJwUnlevR8xtF8bs+gjZ7cyUNYXiSf/E8Kp0Ss5xasIaXSHzb888V1BE4i1hFhAA==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-x64": "1.1.0" + } + }, + "node_modules/@img/sharp-wasm32": { + "version": "0.34.2", + "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.34.2.tgz", + "integrity": "sha512-/VI4mdlJ9zkaq53MbIG6rZY+QRN3MLbR6usYlgITEzi4Rpx5S6LFKsycOQjkOGmqTNmkIdLjEvooFKwww6OpdQ==", + "cpu": [ + "wasm32" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", + "optional": true, + "dependencies": { + "@emnapi/runtime": "^1.4.3" + }, + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-arm64": { + "version": "0.34.2", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.34.2.tgz", + "integrity": "sha512-cfP/r9FdS63VA5k0xiqaNaEoGxBg9k7uE+RQGzuK9fHt7jib4zAVVseR9LsE4gJcNWgT6APKMNnCcnyOtmSEUQ==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-ia32": { + "version": "0.34.2", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.34.2.tgz", + "integrity": "sha512-QLjGGvAbj0X/FXl8n1WbtQ6iVBpWU7JO94u/P2M4a8CFYsvQi4GW2mRy/JqkRx0qpBzaOdKJKw8uc930EX2AHw==", + "cpu": [ + "ia32" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-x64": { + "version": "0.34.2", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.34.2.tgz", + "integrity": "sha512-aUdT6zEYtDKCaxkofmmJDJYGCf0+pJg3eU9/oBuqvEeoB9dKI6ZLc/1iLJCTuJQDO4ptntAlkUmHgGjyuobZbw==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@next/env": { + "version": "15.3.3", + "resolved": "https://registry.npmjs.org/@next/env/-/env-15.3.3.tgz", + "integrity": "sha512-OdiMrzCl2Xi0VTjiQQUK0Xh7bJHnOuET2s+3V+Y40WJBAXrJeGA3f+I8MZJ/YQ3mVGi5XGR1L66oFlgqXhQ4Vw==", + "license": "MIT" + }, + "node_modules/@next/swc-darwin-arm64": { + "version": "15.3.3", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-15.3.3.tgz", + "integrity": "sha512-WRJERLuH+O3oYB4yZNVahSVFmtxRNjNF1I1c34tYMoJb0Pve+7/RaLAJJizyYiFhjYNGHRAE1Ri2Fd23zgDqhg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-darwin-x64": { + "version": "15.3.3", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-15.3.3.tgz", + "integrity": "sha512-XHdzH/yBc55lu78k/XwtuFR/ZXUTcflpRXcsu0nKmF45U96jt1tsOZhVrn5YH+paw66zOANpOnFQ9i6/j+UYvw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm64-gnu": { + "version": "15.3.3", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-15.3.3.tgz", + "integrity": "sha512-VZ3sYL2LXB8znNGcjhocikEkag/8xiLgnvQts41tq6i+wql63SMS1Q6N8RVXHw5pEUjiof+II3HkDd7GFcgkzw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm64-musl": { + "version": "15.3.3", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-15.3.3.tgz", + "integrity": "sha512-h6Y1fLU4RWAp1HPNJWDYBQ+e3G7sLckyBXhmH9ajn8l/RSMnhbuPBV/fXmy3muMcVwoJdHL+UtzRzs0nXOf9SA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-x64-gnu": { + "version": "15.3.3", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-15.3.3.tgz", + "integrity": "sha512-jJ8HRiF3N8Zw6hGlytCj5BiHyG/K+fnTKVDEKvUCyiQ/0r5tgwO7OgaRiOjjRoIx2vwLR+Rz8hQoPrnmFbJdfw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-x64-musl": { + "version": "15.3.3", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-15.3.3.tgz", + "integrity": "sha512-HrUcTr4N+RgiiGn3jjeT6Oo208UT/7BuTr7K0mdKRBtTbT4v9zJqCDKO97DUqqoBK1qyzP1RwvrWTvU6EPh/Cw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-arm64-msvc": { + "version": "15.3.3", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-15.3.3.tgz", + "integrity": "sha512-SxorONgi6K7ZUysMtRF3mIeHC5aA3IQLmKFQzU0OuhuUYwpOBc1ypaLJLP5Bf3M9k53KUUUj4vTPwzGvl/NwlQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-x64-msvc": { + "version": "15.3.3", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-15.3.3.tgz", + "integrity": "sha512-4QZG6F8enl9/S2+yIiOiju0iCTFd93d8VC1q9LZS4p/Xuk81W2QDjCFeoogmrWWkAD59z8ZxepBQap2dKS5ruw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@swc/counter": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz", + "integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==", + "license": "Apache-2.0" + }, + "node_modules/@swc/helpers": { + "version": "0.5.15", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.15.tgz", + "integrity": "sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.8.0" + } + }, + "node_modules/@types/node": { + "version": "24.0.3", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.0.3.tgz", + "integrity": "sha512-R4I/kzCYAdRLzfiCabn9hxWfbuHS573x+r0dJMkkzThEa7pbrcDWK+9zu3e7aBOouf+rQAciqPFMnxwr0aWgKg==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~7.8.0" + } + }, + "node_modules/@types/react": { + "version": "19.1.8", + "resolved": "https://registry.npmjs.org/@types/react/-/react-19.1.8.tgz", + "integrity": "sha512-AwAfQ2Wa5bCx9WP8nZL2uMZWod7J7/JSplxbTmBQ5ms6QpqNYm672H0Vu9ZVKVngQ+ii4R/byguVEUZQyeg44g==", + "dev": true, + "license": "MIT", + "dependencies": { + "csstype": "^3.0.2" + } + }, + "node_modules/busboy": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", + "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", + "dependencies": { + "streamsearch": "^1.1.0" + }, + "engines": { + "node": ">=10.16.0" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001723", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001723.tgz", + "integrity": "sha512-1R/elMjtehrFejxwmexeXAtae5UO9iSyFn6G/I806CYC/BLyyBk1EPhrKBkWhy6wM6Xnm47dSJQec+tLJ39WHw==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/client-only": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", + "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==", + "license": "MIT" + }, + "node_modules/color": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz", + "integrity": "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==", + "license": "MIT", + "optional": true, + "dependencies": { + "color-convert": "^2.0.1", + "color-string": "^1.9.0" + }, + "engines": { + "node": ">=12.5.0" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "license": "MIT", + "optional": true + }, + "node_modules/color-string": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz", + "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==", + "license": "MIT", + "optional": true, + "dependencies": { + "color-name": "^1.0.0", + "simple-swizzle": "^0.2.2" + } + }, + "node_modules/csstype": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", + "dev": true, + "license": "MIT" + }, + "node_modules/detect-libc": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.4.tgz", + "integrity": "sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==", + "license": "Apache-2.0", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-arrayish": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", + "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==", + "license": "MIT", + "optional": true + }, + "node_modules/nanoid": { + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/next": { + "version": "15.3.3", + "resolved": "https://registry.npmjs.org/next/-/next-15.3.3.tgz", + "integrity": "sha512-JqNj29hHNmCLtNvd090SyRbXJiivQ+58XjCcrC50Crb5g5u2zi7Y2YivbsEfzk6AtVI80akdOQbaMZwWB1Hthw==", + "license": "MIT", + "dependencies": { + "@next/env": "15.3.3", + "@swc/counter": "0.1.3", + "@swc/helpers": "0.5.15", + "busboy": "1.6.0", + "caniuse-lite": "^1.0.30001579", + "postcss": "8.4.31", + "styled-jsx": "5.1.6" + }, + "bin": { + "next": "dist/bin/next" + }, + "engines": { + "node": "^18.18.0 || ^19.8.0 || >= 20.0.0" + }, + "optionalDependencies": { + "@next/swc-darwin-arm64": "15.3.3", + "@next/swc-darwin-x64": "15.3.3", + "@next/swc-linux-arm64-gnu": "15.3.3", + "@next/swc-linux-arm64-musl": "15.3.3", + "@next/swc-linux-x64-gnu": "15.3.3", + "@next/swc-linux-x64-musl": "15.3.3", + "@next/swc-win32-arm64-msvc": "15.3.3", + "@next/swc-win32-x64-msvc": "15.3.3", + "sharp": "^0.34.1" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.1.0", + "@playwright/test": "^1.41.2", + "babel-plugin-react-compiler": "*", + "react": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", + "react-dom": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", + "sass": "^1.3.0" + }, + "peerDependenciesMeta": { + "@opentelemetry/api": { + "optional": true + }, + "@playwright/test": { + "optional": true + }, + "babel-plugin-react-compiler": { + "optional": true + }, + "sass": { + "optional": true + } + } + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "license": "ISC" + }, + "node_modules/postcss": { + "version": "8.4.31", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", + "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.6", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/react": { + "version": "19.1.0", + "resolved": "https://registry.npmjs.org/react/-/react-19.1.0.tgz", + "integrity": "sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "19.1.0", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.1.0.tgz", + "integrity": "sha512-Xs1hdnE+DyKgeHJeJznQmYMIBG3TKIHJJT95Q58nHLSrElKlGQqDTR2HQ9fx5CN/Gk6Vh/kupBTDLU11/nDk/g==", + "license": "MIT", + "dependencies": { + "scheduler": "^0.26.0" + }, + "peerDependencies": { + "react": "^19.1.0" + } + }, + "node_modules/scheduler": { + "version": "0.26.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.26.0.tgz", + "integrity": "sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA==", + "license": "MIT" + }, + "node_modules/semver": { + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "license": "ISC", + "optional": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/sharp": { + "version": "0.34.2", + "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.34.2.tgz", + "integrity": "sha512-lszvBmB9QURERtyKT2bNmsgxXK0ShJrL/fvqlonCo7e6xBF8nT8xU6pW+PMIbLsz0RxQk3rgH9kd8UmvOzlMJg==", + "hasInstallScript": true, + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "color": "^4.2.3", + "detect-libc": "^2.0.4", + "semver": "^7.7.2" + }, + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-darwin-arm64": "0.34.2", + "@img/sharp-darwin-x64": "0.34.2", + "@img/sharp-libvips-darwin-arm64": "1.1.0", + "@img/sharp-libvips-darwin-x64": "1.1.0", + "@img/sharp-libvips-linux-arm": "1.1.0", + "@img/sharp-libvips-linux-arm64": "1.1.0", + "@img/sharp-libvips-linux-ppc64": "1.1.0", + "@img/sharp-libvips-linux-s390x": "1.1.0", + "@img/sharp-libvips-linux-x64": "1.1.0", + "@img/sharp-libvips-linuxmusl-arm64": "1.1.0", + "@img/sharp-libvips-linuxmusl-x64": "1.1.0", + "@img/sharp-linux-arm": "0.34.2", + "@img/sharp-linux-arm64": "0.34.2", + "@img/sharp-linux-s390x": "0.34.2", + "@img/sharp-linux-x64": "0.34.2", + "@img/sharp-linuxmusl-arm64": "0.34.2", + "@img/sharp-linuxmusl-x64": "0.34.2", + "@img/sharp-wasm32": "0.34.2", + "@img/sharp-win32-arm64": "0.34.2", + "@img/sharp-win32-ia32": "0.34.2", + "@img/sharp-win32-x64": "0.34.2" + } + }, + "node_modules/simple-swizzle": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", + "integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==", + "license": "MIT", + "optional": true, + "dependencies": { + "is-arrayish": "^0.3.1" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/streamsearch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", + "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/styled-jsx": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.6.tgz", + "integrity": "sha512-qSVyDTeMotdvQYoHWLNGwRFJHC+i+ZvdBRYosOFgC+Wg1vx4frN2/RG/NA7SYqqvKNLf39P2LSRA2pu6n0XYZA==", + "license": "MIT", + "dependencies": { + "client-only": "0.0.1" + }, + "engines": { + "node": ">= 12.0.0" + }, + "peerDependencies": { + "react": ">= 16.8.0 || 17.x.x || ^18.0.0-0 || ^19.0.0-0" + }, + "peerDependenciesMeta": { + "@babel/core": { + "optional": true + }, + "babel-plugin-macros": { + "optional": true + } + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/typescript": { + "version": "5.8.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz", + "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/undici-types": { + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.8.0.tgz", + "integrity": "sha512-9UJ2xGDvQ43tYyVMpuHlsgApydB8ZKfVYTsLDhXkFL/6gfkp+U8xTGdh8pMJv1SpZna0zxG1DwsKZsreLbXBxw==", + "dev": true, + "license": "MIT" + } + } +} diff --git a/frontend/package.json b/frontend/package.json new file mode 100644 index 0000000..28cbb17 --- /dev/null +++ b/frontend/package.json @@ -0,0 +1,18 @@ +{ + "dependencies": { + "next": "^15.3.3", + "react": "^19.1.0", + "react-dom": "^19.1.0" + }, + "scripts": { + "dev": "next dev", + "build": "next build", + "start": "next start", + "lint": "next lint" + }, + "devDependencies": { + "@types/node": "24.0.3", + "@types/react": "19.1.8", + "typescript": "5.8.3" + } +} diff --git a/frontend/public/meowl.png b/frontend/public/meowl.png new file mode 100644 index 0000000..aa55271 Binary files /dev/null and b/frontend/public/meowl.png differ diff --git a/frontend/src/app/layout.tsx b/frontend/src/app/layout.tsx new file mode 100644 index 0000000..225b603 --- /dev/null +++ b/frontend/src/app/layout.tsx @@ -0,0 +1,11 @@ +export default function RootLayout({ + children, +}: { + children: React.ReactNode; +}) { + return ( + + {children} + + ); +} diff --git a/frontend/src/app/page.tsx b/frontend/src/app/page.tsx new file mode 100644 index 0000000..701eeb9 --- /dev/null +++ b/frontend/src/app/page.tsx @@ -0,0 +1,10 @@ +import Image from "next/image"; + +export default function Page() { + return ( +
+

Hallo mooie wereld!

+ Meowl image +
+ ); +} diff --git a/frontend/tsconfig.json b/frontend/tsconfig.json new file mode 100644 index 0000000..f619795 --- /dev/null +++ b/frontend/tsconfig.json @@ -0,0 +1,35 @@ +{ + "compilerOptions": { + "target": "ES2017", + "lib": [ + "dom", + "dom.iterable", + "esnext" + ], + "allowJs": true, + "skipLibCheck": true, + "strict": false, + "noEmit": true, + "incremental": true, + "module": "esnext", + "esModuleInterop": true, + "moduleResolution": "node", + "resolveJsonModule": true, + "isolatedModules": true, + "jsx": "preserve", + "plugins": [ + { + "name": "next" + } + ] + }, + "include": [ + "next-env.d.ts", + ".next/types/**/*.ts", + "**/*.ts", + "**/*.tsx" + ], + "exclude": [ + "node_modules" + ] +}