overhaul frontend, typography, noise pattern, badge, notify audio

This commit is contained in:
2024-12-22 08:51:15 -06:00
parent a0417e0b19
commit 6f7139d5d7
11 changed files with 604 additions and 41 deletions

View File

@@ -12,9 +12,15 @@
"@astrojs/preact": "^4.0.1",
"@astrojs/sitemap": "^3.2.1",
"@astrojs/tailwind": "^5.1.4",
"@tailwindcss/typography": "^0.5.15",
"astro": "^5.1.1",
"clsx": "^2.1.1",
"preact": "^10.25.3",
"tailwind-merge": "^2.5.5",
"tailwindcss": "^3.4.17"
},
"packageManager": "pnpm@9.15.1+sha512.1acb565e6193efbebda772702950469150cf12bcc764262e7587e71d19dc98a423dff9536e57ea44c49bdf790ff694e83c27be5faa23d67e0c033b583be4bfcf"
"packageManager": "pnpm@9.15.1+sha512.1acb565e6193efbebda772702950469150cf12bcc764262e7587e71d19dc98a423dff9536e57ea44c49bdf790ff694e83c27be5faa23d67e0c033b583be4bfcf",
"devDependencies": {
"sass-embedded": "^1.83.0"
}
}

374
frontend/pnpm-lock.yaml generated
View File

@@ -10,22 +10,35 @@ importers:
dependencies:
'@astrojs/preact':
specifier: ^4.0.1
version: 4.0.1(@babel/core@7.26.0)(jiti@2.4.2)(preact@10.25.3)(yaml@2.6.1)
version: 4.0.1(@babel/core@7.26.0)(jiti@2.4.2)(preact@10.25.3)(sass-embedded@1.83.0)(yaml@2.6.1)
'@astrojs/sitemap':
specifier: ^3.2.1
version: 3.2.1
'@astrojs/tailwind':
specifier: ^5.1.4
version: 5.1.4(astro@5.1.1(jiti@2.4.2)(rollup@4.29.1)(typescript@5.7.2)(yaml@2.6.1))(tailwindcss@3.4.17)
version: 5.1.4(astro@5.1.1(jiti@2.4.2)(rollup@4.29.1)(sass-embedded@1.83.0)(typescript@5.7.2)(yaml@2.6.1))(tailwindcss@3.4.17)
'@tailwindcss/typography':
specifier: ^0.5.15
version: 0.5.15(tailwindcss@3.4.17)
astro:
specifier: ^5.1.1
version: 5.1.1(jiti@2.4.2)(rollup@4.29.1)(typescript@5.7.2)(yaml@2.6.1)
version: 5.1.1(jiti@2.4.2)(rollup@4.29.1)(sass-embedded@1.83.0)(typescript@5.7.2)(yaml@2.6.1)
clsx:
specifier: ^2.1.1
version: 2.1.1
preact:
specifier: ^10.25.3
version: 10.25.3
tailwind-merge:
specifier: ^2.5.5
version: 2.5.5
tailwindcss:
specifier: ^3.4.17
version: 3.4.17
devDependencies:
sass-embedded:
specifier: ^1.83.0
version: 1.83.0
packages:
@@ -158,6 +171,9 @@ packages:
resolution: {integrity: sha512-vN5p+1kl59GVKMvTHt55NzzmYVxprfJD+ql7U9NFIfKCBkYE55LYtS+WtPlaYOyzydrKI8Nezd+aZextrd+FMA==}
engines: {node: '>=6.9.0'}
'@bufbuild/protobuf@2.2.3':
resolution: {integrity: sha512-tFQoXHJdkEOSwj5tRIZSPNUuXK3RaR7T1nUrPgbYX1pUbvqqaaZAsfo+NXBPsz5rZMSKVFrgK1WL8Q/MSLvprg==}
'@emnapi/runtime@1.3.1':
resolution: {integrity: sha512-kEBmG8KyqtxJZv+ygbEim+KCGtIq1fC22Ms3S4ziXmYKm8uyoLX0MHONVKwp+9opg390VaKRNt4a7A9NwmpNhw==}
@@ -831,6 +847,11 @@ packages:
'@shikijs/vscode-textmate@9.3.1':
resolution: {integrity: sha512-79QfK1393x9Ho60QFyLti+QfdJzRQCVLFb97kOIV7Eo9vQU/roINgk7m24uv0a7AUvN//RDH36FLjjK48v0s9g==}
'@tailwindcss/typography@0.5.15':
resolution: {integrity: sha512-AqhlCXl+8grUz8uqExv5OTtgpjuVIwFTSXTrh8y9/pw6q2ek7fJ+Y8ZEVw7EB2DCcuCOtEjf9w3+J3rzts01uA==}
peerDependencies:
tailwindcss: '>=3.0.0 || insiders || >=4.0.0-alpha.20'
'@types/cookie@0.6.0':
resolution: {integrity: sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==}
@@ -964,6 +985,9 @@ packages:
engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
hasBin: true
buffer-builder@0.2.0:
resolution: {integrity: sha512-7VPMEPuYznPSoR21NE1zvd2Xna6c/CloiZCfcMXR1Jny6PjX0N4Nsa38zcBFo/FMK+BlA+FLKbJCQ0i2yxp+Xg==}
camelcase-css@2.0.1:
resolution: {integrity: sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==}
engines: {node: '>= 6'}
@@ -1028,6 +1052,9 @@ packages:
resolution: {integrity: sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==}
engines: {node: '>=12.5.0'}
colorjs.io@0.5.2:
resolution: {integrity: sha512-twmVoizEW7ylZSN32OgKdXRmo1qg+wT5/6C3xu5b9QsWzSFAhHLn2xd8ro0diCsKfCj1RdaTP/nrcW+vAoQPIw==}
comma-separated-tokens@2.0.3:
resolution: {integrity: sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==}
@@ -1287,6 +1314,10 @@ packages:
h3@1.13.0:
resolution: {integrity: sha512-vFEAu/yf8UMUcB4s43OaDaigcqpQd14yanmOsn+NcRX3/guSKncyE2rOYhq8RIchgJrPSs/QiIddnTTR1ddiAg==}
has-flag@4.0.0:
resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==}
engines: {node: '>=8'}
hasown@2.0.2:
resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==}
engines: {node: '>= 0.4'}
@@ -1342,6 +1373,9 @@ packages:
resolution: {integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==}
engines: {node: '>=16.17.0'}
immutable@5.0.3:
resolution: {integrity: sha512-P8IdPQHq3lA1xVeBRi5VPqUm5HDgKnx0Ru51wZz5mjxHr5n3RWhjIpOFU7ybkUxfB+5IToy+OLaHYDBIWsv+uw==}
import-meta-resolve@4.1.0:
resolution: {integrity: sha512-I6fiaX09Xivtk+THaMfAwnA3MVA5Big1WHF1Dfx9hFuvNIWpXnorlkzhcQf6ehrqQiiZECRt1poOAkPmer3ruw==}
@@ -1466,6 +1500,15 @@ packages:
resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==}
engines: {node: '>=8'}
lodash.castarray@4.4.0:
resolution: {integrity: sha512-aVx8ztPv7/2ULbArGJ2Y42bG1mEQ5mGjpdvrbJcJFU3TbYybe+QlLS4pst9zV52ymy2in1KpFPiZnAOATxD4+Q==}
lodash.isplainobject@4.0.6:
resolution: {integrity: sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==}
lodash.merge@4.6.2:
resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==}
longest-streak@3.1.0:
resolution: {integrity: sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==}
@@ -1831,6 +1874,10 @@ packages:
peerDependencies:
postcss: ^8.2.14
postcss-selector-parser@6.0.10:
resolution: {integrity: sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==}
engines: {node: '>=4'}
postcss-selector-parser@6.1.2:
resolution: {integrity: sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==}
engines: {node: '>=4'}
@@ -1944,6 +1991,134 @@ packages:
run-parallel@1.2.0:
resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==}
rxjs@7.8.1:
resolution: {integrity: sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==}
sass-embedded-android-arm64@1.83.0:
resolution: {integrity: sha512-GBiCvM4a2rkWBLdYDxI6XYnprfk5U5c81g69RC2X6kqPuzxzx8qTArQ9M6keFK4+iDQ5N9QTwFCr0KbZTn+ZNQ==}
engines: {node: '>=14.0.0'}
cpu: [arm64]
os: [android]
sass-embedded-android-arm@1.83.0:
resolution: {integrity: sha512-uwFSXzJlfbd4Px189xE5l+cxN8+TQpXdQgJec7TIrb4HEY7imabtpYufpVdqUVwT1/uiis5V4+qIEC4Vl5XObQ==}
engines: {node: '>=14.0.0'}
cpu: [arm]
os: [android]
sass-embedded-android-ia32@1.83.0:
resolution: {integrity: sha512-5ATPdGo2SICqAhiJl/Z8KQ23zH4sGgobGgux0TnrNtt83uHZ+r+To/ubVJ7xTkZxed+KJZnIpolGD8dQyQqoTg==}
engines: {node: '>=14.0.0'}
cpu: [ia32]
os: [android]
sass-embedded-android-riscv64@1.83.0:
resolution: {integrity: sha512-aveknUOB8GZewOzVn2Uwk+DKcncTR50Q6vtzslNMGbYnxtgQNHzy8A1qVEviNUruex+pHofppeMK4iMPFAbiEQ==}
engines: {node: '>=14.0.0'}
cpu: [riscv64]
os: [android]
sass-embedded-android-x64@1.83.0:
resolution: {integrity: sha512-WqIay/72ncyf9Ph4vS742J3a73wZihWmzFUwpn1OD6lme1Aj4eWzWIve5IVnlTEJgcZcDHu6ECID9IZgehJKoA==}
engines: {node: '>=14.0.0'}
cpu: [x64]
os: [android]
sass-embedded-darwin-arm64@1.83.0:
resolution: {integrity: sha512-XQl9QqgxFFIPm/CzHhmppse5o9ocxrbaAdC2/DAnlAqvYWBBtgFqPjGoYlej13h9SzfvNoogx+y9r+Ap+e+hYg==}
engines: {node: '>=14.0.0'}
cpu: [arm64]
os: [darwin]
sass-embedded-darwin-x64@1.83.0:
resolution: {integrity: sha512-ERQ7Tvp1kFOW3ux4VDFIxb7tkYXHYc+zJpcrbs0hzcIO5ilIRU2tIOK1OrNwrFO6Qxyf7AUuBwYKLAtIU/Nz7g==}
engines: {node: '>=14.0.0'}
cpu: [x64]
os: [darwin]
sass-embedded-linux-arm64@1.83.0:
resolution: {integrity: sha512-syEAVTJt4qhaMLxrSwOWa46zdqHJdnqJkLUK+t9aCr8xqBZLPxSUeIGji76uOehQZ1C+KGFj6n9xstHN6wzOJw==}
engines: {node: '>=14.0.0'}
cpu: [arm64]
os: [linux]
sass-embedded-linux-arm@1.83.0:
resolution: {integrity: sha512-baG9RYBJxUFmqwDNC9h9ZFElgJoyO3jgHGjzEZ1wHhIS9anpG+zZQvO8bHx3dBpKEImX+DBeLX+CxsFR9n81gQ==}
engines: {node: '>=14.0.0'}
cpu: [arm]
os: [linux]
sass-embedded-linux-ia32@1.83.0:
resolution: {integrity: sha512-RRBxQxMpoxu5+XcSSc6QR/o9asEwUzR8AbCS83RaXcdTIHTa/CccQsiAoDDoPlRsMTLqnzs0LKL4CfOsf7zBbA==}
engines: {node: '>=14.0.0'}
cpu: [ia32]
os: [linux]
sass-embedded-linux-musl-arm64@1.83.0:
resolution: {integrity: sha512-Y7juhPHClUO2H5O+u+StRy6SEAcwZ+hTEk5WJdEmo1Bb1gDtfHvJaWB/iFZJ2tW0W1e865AZeUrC4OcOFjyAQA==}
engines: {node: '>=14.0.0'}
cpu: [arm64]
os: [linux]
sass-embedded-linux-musl-arm@1.83.0:
resolution: {integrity: sha512-Yc7u2TelCfBab+PRob9/MNJFh3EooMiz4urvhejXkihTiKSHGCv5YqDdtWzvyb9tY2Jb7YtYREVuHwfdVn3dTQ==}
engines: {node: '>=14.0.0'}
cpu: [arm]
os: [linux]
sass-embedded-linux-musl-ia32@1.83.0:
resolution: {integrity: sha512-arQeYwGmwXV8byx5G1PtSzZWW1jbkfR5qrIHMEbTFSAvAxpqjgSvCvrHMOFd73FcMxVaYh4BX9LQNbKinkbEdg==}
engines: {node: '>=14.0.0'}
cpu: [ia32]
os: [linux]
sass-embedded-linux-musl-riscv64@1.83.0:
resolution: {integrity: sha512-E6uzlIWz59rut+Z3XR6mLG915zNzv07ISvj3GUNZENdHM7dF8GQ//ANoIpl5PljMQKp89GnYdvo6kj2gnaBf/g==}
engines: {node: '>=14.0.0'}
cpu: [riscv64]
os: [linux]
sass-embedded-linux-musl-x64@1.83.0:
resolution: {integrity: sha512-eAMK6tyGqvqr21r9g8BnR3fQc1rYFj85RGduSQ3xkITZ6jOAnOhuU94N5fwRS852Hpws0lXhET+7JHXgg3U18w==}
engines: {node: '>=14.0.0'}
cpu: [x64]
os: [linux]
sass-embedded-linux-riscv64@1.83.0:
resolution: {integrity: sha512-Ojpi78pTv02sy2fUYirRGXHLY3fPnV/bvwuC2i5LwPQw2LpCcFyFTtN0c5h4LJDk9P6wr+/ZB/JXU8tHIOlK+Q==}
engines: {node: '>=14.0.0'}
cpu: [riscv64]
os: [linux]
sass-embedded-linux-x64@1.83.0:
resolution: {integrity: sha512-3iLjlXdoPfgZRtX4odhRvka1BQs5mAXqfCtDIQBgh/o0JnGPzJIWWl9bYLpHxK8qb+uyVBxXYgXpI0sCzArBOw==}
engines: {node: '>=14.0.0'}
cpu: [x64]
os: [linux]
sass-embedded-win32-arm64@1.83.0:
resolution: {integrity: sha512-iOHw/8/t2dlTW3lOFwG5eUbiwhEyGWawivlKWJ8lkXH7fjMpVx2VO9zCFAm8RvY9xOHJ9sf1L7g5bx3EnNP9BQ==}
engines: {node: '>=14.0.0'}
cpu: [arm64]
os: [win32]
sass-embedded-win32-ia32@1.83.0:
resolution: {integrity: sha512-2PxNXJ8Pad4geVcTXY4rkyTr5AwbF8nfrCTDv0ulbTvPhzX2mMKEGcBZUXWn5BeHZTBc6whNMfS7d5fQXR9dDQ==}
engines: {node: '>=14.0.0'}
cpu: [ia32]
os: [win32]
sass-embedded-win32-x64@1.83.0:
resolution: {integrity: sha512-muBXkFngM6eLTNqOV0FQi7Dv9s+YRQ42Yem26mosdan/GmJQc81deto6uDTgrYn+bzFNmiXcOdfm+0MkTWK3OQ==}
engines: {node: '>=14.0.0'}
cpu: [x64]
os: [win32]
sass-embedded@1.83.0:
resolution: {integrity: sha512-/8cYZeL39evUqe0o//193na51Q1VWZ61qhxioQvLJwOtWIrX+PgNhCyD8RSuTtmzc4+6+waFZf899bfp/MCUwA==}
engines: {node: '>=16.0.0'}
hasBin: true
sax@1.4.1:
resolution: {integrity: sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==}
@@ -2046,14 +2221,29 @@ packages:
engines: {node: '>=16 || 14 >=14.17'}
hasBin: true
supports-color@8.1.1:
resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==}
engines: {node: '>=10'}
supports-preserve-symlinks-flag@1.0.0:
resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==}
engines: {node: '>= 0.4'}
sync-child-process@1.0.2:
resolution: {integrity: sha512-8lD+t2KrrScJ/7KXCSyfhT3/hRq78rC0wBFqNJXv3mZyn6hW2ypM05JmlSvtqRbeq6jqA94oHbxAr2vYsJ8vDA==}
engines: {node: '>=16.0.0'}
sync-message-port@1.1.3:
resolution: {integrity: sha512-GTt8rSKje5FilG+wEdfCkOcLL7LWqpMlr2c3LRuKt/YXxcJ52aGSbGBAdI4L3aaqfrBt6y711El53ItyH1NWzg==}
engines: {node: '>=16.0.0'}
system-architecture@0.1.0:
resolution: {integrity: sha512-ulAk51I9UVUyJgxlv9M6lFot2WP3e7t8Kz9+IS6D4rVba1tR9kON+Ey69f+1R4Q8cd45Lod6a4IcJIxnzGc/zA==}
engines: {node: '>=18'}
tailwind-merge@2.5.5:
resolution: {integrity: sha512-0LXunzzAZzo0tEPxV3I297ffKZPlKDrjj7NXphC8V5ak9yHC5zRmxnOe2m/Rd/7ivsOMJe3JZ2JVocoDdQTRBA==}
tailwindcss@3.4.17:
resolution: {integrity: sha512-w33E2aCvSDP0tW9RZuNXadXlkHXqFzSkQew/aIa2i/Sj8fThxwovwlXHSPXTbAHwEIhBFXAedUhP2tueAKP8Og==}
engines: {node: '>=14.0.0'}
@@ -2221,6 +2411,9 @@ packages:
util-deprecate@1.0.2:
resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}
varint@6.0.0:
resolution: {integrity: sha512-cXEIW6cfr15lFv563k4GuVuW/fiwjknytD37jIOLSdSWuOI6WnO/oKwmP2FQTU2l01LP8/M5TSAJpzUaGe3uWg==}
vfile-location@5.0.3:
resolution: {integrity: sha512-5yXvWDEgqeiYiBe1lbxYF7UMAIm/IcopxMHrMQDq3nvKcjPKIhZklUKL+AE7J7uApI4kwe2snsK+eI6UTj9EHg==}
@@ -2391,16 +2584,16 @@ snapshots:
transitivePeerDependencies:
- supports-color
'@astrojs/preact@4.0.1(@babel/core@7.26.0)(jiti@2.4.2)(preact@10.25.3)(yaml@2.6.1)':
'@astrojs/preact@4.0.1(@babel/core@7.26.0)(jiti@2.4.2)(preact@10.25.3)(sass-embedded@1.83.0)(yaml@2.6.1)':
dependencies:
'@babel/plugin-transform-react-jsx': 7.25.9(@babel/core@7.26.0)
'@babel/plugin-transform-react-jsx-development': 7.25.9(@babel/core@7.26.0)
'@preact/preset-vite': 2.8.2(@babel/core@7.26.0)(preact@10.25.3)(vite@6.0.5(jiti@2.4.2)(yaml@2.6.1))
'@preact/preset-vite': 2.8.2(@babel/core@7.26.0)(preact@10.25.3)(vite@6.0.5(jiti@2.4.2)(sass-embedded@1.83.0)(yaml@2.6.1))
'@preact/signals': 1.3.1(preact@10.25.3)
babel-plugin-transform-hook-names: 1.0.2(@babel/core@7.26.0)
preact: 10.25.3
preact-render-to-string: 6.5.12(preact@10.25.3)
vite: 6.0.5(jiti@2.4.2)(yaml@2.6.1)
vite: 6.0.5(jiti@2.4.2)(sass-embedded@1.83.0)(yaml@2.6.1)
transitivePeerDependencies:
- '@babel/core'
- '@types/node'
@@ -2426,9 +2619,9 @@ snapshots:
stream-replace-string: 2.0.0
zod: 3.24.1
'@astrojs/tailwind@5.1.4(astro@5.1.1(jiti@2.4.2)(rollup@4.29.1)(typescript@5.7.2)(yaml@2.6.1))(tailwindcss@3.4.17)':
'@astrojs/tailwind@5.1.4(astro@5.1.1(jiti@2.4.2)(rollup@4.29.1)(sass-embedded@1.83.0)(typescript@5.7.2)(yaml@2.6.1))(tailwindcss@3.4.17)':
dependencies:
astro: 5.1.1(jiti@2.4.2)(rollup@4.29.1)(typescript@5.7.2)(yaml@2.6.1)
astro: 5.1.1(jiti@2.4.2)(rollup@4.29.1)(sass-embedded@1.83.0)(typescript@5.7.2)(yaml@2.6.1)
autoprefixer: 10.4.20(postcss@8.4.49)
postcss: 8.4.49
postcss-load-config: 4.0.2(postcss@8.4.49)
@@ -2575,6 +2768,8 @@ snapshots:
'@babel/helper-string-parser': 7.25.9
'@babel/helper-validator-identifier': 7.25.9
'@bufbuild/protobuf@2.2.3': {}
'@emnapi/runtime@1.3.1':
dependencies:
tslib: 2.8.1
@@ -2904,12 +3099,12 @@ snapshots:
'@pkgjs/parseargs@0.11.0':
optional: true
'@preact/preset-vite@2.8.2(@babel/core@7.26.0)(preact@10.25.3)(vite@6.0.5(jiti@2.4.2)(yaml@2.6.1))':
'@preact/preset-vite@2.8.2(@babel/core@7.26.0)(preact@10.25.3)(vite@6.0.5(jiti@2.4.2)(sass-embedded@1.83.0)(yaml@2.6.1))':
dependencies:
'@babel/core': 7.26.0
'@babel/plugin-transform-react-jsx': 7.25.9(@babel/core@7.26.0)
'@babel/plugin-transform-react-jsx-development': 7.25.9(@babel/core@7.26.0)
'@prefresh/vite': 2.4.6(preact@10.25.3)(vite@6.0.5(jiti@2.4.2)(yaml@2.6.1))
'@prefresh/vite': 2.4.6(preact@10.25.3)(vite@6.0.5(jiti@2.4.2)(sass-embedded@1.83.0)(yaml@2.6.1))
'@rollup/pluginutils': 4.2.1
babel-plugin-transform-hook-names: 1.0.2(@babel/core@7.26.0)
debug: 4.4.0
@@ -2919,7 +3114,7 @@ snapshots:
resolve: 1.22.10
source-map: 0.7.4
stack-trace: 1.0.0-pre2
vite: 6.0.5(jiti@2.4.2)(yaml@2.6.1)
vite: 6.0.5(jiti@2.4.2)(sass-embedded@1.83.0)(yaml@2.6.1)
transitivePeerDependencies:
- preact
- supports-color
@@ -2939,7 +3134,7 @@ snapshots:
'@prefresh/utils@1.2.0': {}
'@prefresh/vite@2.4.6(preact@10.25.3)(vite@6.0.5(jiti@2.4.2)(yaml@2.6.1))':
'@prefresh/vite@2.4.6(preact@10.25.3)(vite@6.0.5(jiti@2.4.2)(sass-embedded@1.83.0)(yaml@2.6.1))':
dependencies:
'@babel/core': 7.26.0
'@prefresh/babel-plugin': 0.5.1
@@ -2947,7 +3142,7 @@ snapshots:
'@prefresh/utils': 1.2.0
'@rollup/pluginutils': 4.2.1
preact: 10.25.3
vite: 6.0.5(jiti@2.4.2)(yaml@2.6.1)
vite: 6.0.5(jiti@2.4.2)(sass-embedded@1.83.0)(yaml@2.6.1)
transitivePeerDependencies:
- supports-color
@@ -3048,6 +3243,14 @@ snapshots:
'@shikijs/vscode-textmate@9.3.1': {}
'@tailwindcss/typography@0.5.15(tailwindcss@3.4.17)':
dependencies:
lodash.castarray: 4.4.0
lodash.isplainobject: 4.0.6
lodash.merge: 4.6.2
postcss-selector-parser: 6.0.10
tailwindcss: 3.4.17
'@types/cookie@0.6.0': {}
'@types/debug@4.1.12':
@@ -3115,7 +3318,7 @@ snapshots:
array-iterate@2.0.1: {}
astro@5.1.1(jiti@2.4.2)(rollup@4.29.1)(typescript@5.7.2)(yaml@2.6.1):
astro@5.1.1(jiti@2.4.2)(rollup@4.29.1)(sass-embedded@1.83.0)(typescript@5.7.2)(yaml@2.6.1):
dependencies:
'@astrojs/compiler': 2.10.3
'@astrojs/internal-helpers': 0.4.2
@@ -3167,8 +3370,8 @@ snapshots:
unist-util-visit: 5.0.0
unstorage: 1.14.1
vfile: 6.0.3
vite: 6.0.5(jiti@2.4.2)(yaml@2.6.1)
vitefu: 1.0.4(vite@6.0.5(jiti@2.4.2)(yaml@2.6.1))
vite: 6.0.5(jiti@2.4.2)(sass-embedded@1.83.0)(yaml@2.6.1)
vitefu: 1.0.4(vite@6.0.5(jiti@2.4.2)(sass-embedded@1.83.0)(yaml@2.6.1))
which-pm: 3.0.0
xxhash-wasm: 1.1.0
yargs-parser: 21.1.1
@@ -3264,6 +3467,8 @@ snapshots:
node-releases: 2.0.19
update-browserslist-db: 1.1.1(browserslist@4.24.3)
buffer-builder@0.2.0: {}
camelcase-css@2.0.1: {}
camelcase@8.0.0: {}
@@ -3326,6 +3531,8 @@ snapshots:
color-string: 1.9.1
optional: true
colorjs.io@0.5.2: {}
comma-separated-tokens@2.0.3: {}
commander@4.1.1: {}
@@ -3602,6 +3809,8 @@ snapshots:
uncrypto: 0.1.3
unenv: 1.10.0
has-flag@4.0.0: {}
hasown@2.0.2:
dependencies:
function-bind: 1.1.2
@@ -3705,6 +3914,8 @@ snapshots:
human-signals@5.0.0: {}
immutable@5.0.3: {}
import-meta-resolve@4.1.0: {}
iron-webcrypto@1.2.1: {}
@@ -3817,6 +4028,12 @@ snapshots:
dependencies:
p-locate: 4.1.0
lodash.castarray@4.4.0: {}
lodash.isplainobject@4.0.6: {}
lodash.merge@4.6.2: {}
longest-streak@3.1.0: {}
lru-cache@10.4.3: {}
@@ -4340,6 +4557,11 @@ snapshots:
postcss: 8.4.49
postcss-selector-parser: 6.1.2
postcss-selector-parser@6.0.10:
dependencies:
cssesc: 3.0.0
util-deprecate: 1.0.2
postcss-selector-parser@6.1.2:
dependencies:
cssesc: 3.0.0
@@ -4524,6 +4746,102 @@ snapshots:
dependencies:
queue-microtask: 1.2.3
rxjs@7.8.1:
dependencies:
tslib: 2.8.1
sass-embedded-android-arm64@1.83.0:
optional: true
sass-embedded-android-arm@1.83.0:
optional: true
sass-embedded-android-ia32@1.83.0:
optional: true
sass-embedded-android-riscv64@1.83.0:
optional: true
sass-embedded-android-x64@1.83.0:
optional: true
sass-embedded-darwin-arm64@1.83.0:
optional: true
sass-embedded-darwin-x64@1.83.0:
optional: true
sass-embedded-linux-arm64@1.83.0:
optional: true
sass-embedded-linux-arm@1.83.0:
optional: true
sass-embedded-linux-ia32@1.83.0:
optional: true
sass-embedded-linux-musl-arm64@1.83.0:
optional: true
sass-embedded-linux-musl-arm@1.83.0:
optional: true
sass-embedded-linux-musl-ia32@1.83.0:
optional: true
sass-embedded-linux-musl-riscv64@1.83.0:
optional: true
sass-embedded-linux-musl-x64@1.83.0:
optional: true
sass-embedded-linux-riscv64@1.83.0:
optional: true
sass-embedded-linux-x64@1.83.0:
optional: true
sass-embedded-win32-arm64@1.83.0:
optional: true
sass-embedded-win32-ia32@1.83.0:
optional: true
sass-embedded-win32-x64@1.83.0:
optional: true
sass-embedded@1.83.0:
dependencies:
'@bufbuild/protobuf': 2.2.3
buffer-builder: 0.2.0
colorjs.io: 0.5.2
immutable: 5.0.3
rxjs: 7.8.1
supports-color: 8.1.1
sync-child-process: 1.0.2
varint: 6.0.0
optionalDependencies:
sass-embedded-android-arm: 1.83.0
sass-embedded-android-arm64: 1.83.0
sass-embedded-android-ia32: 1.83.0
sass-embedded-android-riscv64: 1.83.0
sass-embedded-android-x64: 1.83.0
sass-embedded-darwin-arm64: 1.83.0
sass-embedded-darwin-x64: 1.83.0
sass-embedded-linux-arm: 1.83.0
sass-embedded-linux-arm64: 1.83.0
sass-embedded-linux-ia32: 1.83.0
sass-embedded-linux-musl-arm: 1.83.0
sass-embedded-linux-musl-arm64: 1.83.0
sass-embedded-linux-musl-ia32: 1.83.0
sass-embedded-linux-musl-riscv64: 1.83.0
sass-embedded-linux-musl-x64: 1.83.0
sass-embedded-linux-riscv64: 1.83.0
sass-embedded-linux-x64: 1.83.0
sass-embedded-win32-arm64: 1.83.0
sass-embedded-win32-ia32: 1.83.0
sass-embedded-win32-x64: 1.83.0
sax@1.4.1: {}
semver@6.3.1: {}
@@ -4647,10 +4965,22 @@ snapshots:
pirates: 4.0.6
ts-interface-checker: 0.1.13
supports-color@8.1.1:
dependencies:
has-flag: 4.0.0
supports-preserve-symlinks-flag@1.0.0: {}
sync-child-process@1.0.2:
dependencies:
sync-message-port: 1.1.3
sync-message-port@1.1.3: {}
system-architecture@0.1.0: {}
tailwind-merge@2.5.5: {}
tailwindcss@3.4.17:
dependencies:
'@alloc/quick-lru': 5.2.0
@@ -4702,8 +5032,7 @@ snapshots:
optionalDependencies:
typescript: 5.7.2
tslib@2.8.1:
optional: true
tslib@2.8.1: {}
type-fest@4.30.2: {}
@@ -4804,6 +5133,8 @@ snapshots:
util-deprecate@1.0.2: {}
varint@6.0.0: {}
vfile-location@5.0.3:
dependencies:
'@types/unist': 3.0.3
@@ -4819,7 +5150,7 @@ snapshots:
'@types/unist': 3.0.3
vfile-message: 4.0.2
vite@6.0.5(jiti@2.4.2)(yaml@2.6.1):
vite@6.0.5(jiti@2.4.2)(sass-embedded@1.83.0)(yaml@2.6.1):
dependencies:
esbuild: 0.24.0
postcss: 8.4.49
@@ -4827,11 +5158,12 @@ snapshots:
optionalDependencies:
fsevents: 2.3.3
jiti: 2.4.2
sass-embedded: 1.83.0
yaml: 2.6.1
vitefu@1.0.4(vite@6.0.5(jiti@2.4.2)(yaml@2.6.1)):
vitefu@1.0.4(vite@6.0.5(jiti@2.4.2)(sass-embedded@1.83.0)(yaml@2.6.1)):
optionalDependencies:
vite: 6.0.5(jiti@2.4.2)(yaml@2.6.1)
vite: 6.0.5(jiti@2.4.2)(sass-embedded@1.83.0)(yaml@2.6.1)
web-namespaces@2.0.1: {}

BIN
frontend/public/noise.png Normal file
View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 176 KiB

BIN
frontend/public/notify.wav Normal file
View File

Binary file not shown.

View File

@@ -0,0 +1,48 @@
import { cn, type ClassValue } from "@/util";
import type { JSX } from "astro/jsx-runtime";
type BadgeProps = {
className?: ClassValue;
onClick?: () => void;
children: JSX.Element | JSX.Element[];
screenReaderLabel?: string;
};
const Badge = ({
className,
children,
onClick,
screenReaderLabel,
}: BadgeProps) => {
return (
<span
id="badge-dismiss-dark"
class={cn(
className,
"inline-flex items-center px-2 py-1 me-2 text-sm font-medium text-zinc-800 bg-zinc-100 rounded dark:bg-zinc-700 dark:text-zinc-300"
)}
>
{children}
<button
type="button"
onClick={onClick}
class="inline-flex items-center p-1 ms-1 text-sm text-zinc-400 bg-transparent rounded-sm hover:bg-zinc-200 hover:text-zinc-900 dark:hover:bg-zinc-600 dark:hover:text-zinc-300"
data-dismiss-target="#badge-dismiss-dark"
aria-label="Remove"
>
<svg class="w-2 h-2" aria-hidden="true" fill="none" viewBox="0 0 14 14">
<path
stroke="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="m1 1 6 6m0 0 6 6M7 7l6-6M7 7l-6 6"
/>
</svg>
<span class="sr-only">{screenReaderLabel ?? "Remove"}</span>
</button>
</span>
);
};
export default Badge;

View File

@@ -0,0 +1,48 @@
import Badge from "@/components/Badge";
import { useState } from "preact/hooks";
type StatefulDemoProps = {
class?: string;
};
type SessionData = {
id: string;
downloads: string[];
};
const StatefulDemo = ({ class: className }: StatefulDemoProps) => {
const [session, setSession] = useState<SessionData>({
id: "0x59AF5",
downloads: ["0xABF4"],
});
return (
<div class="px-5 leading-6">
<p class="mt-3">
This demo uses websockets to communicate between the server and the
browser. Each download gets a unique identifier bound to the user
session.
<br />
Your session is{" "}
<b class="text-teal-400 font-inter">{session?.id ?? "loading"}</b>. You
have <b class="text-teal-400 font-inter">{session?.downloads.length}</b>{" "}
known downloads.
</p>
<div>
{session?.downloads.map((download) => (
<Badge
onClick={function onClick() {
const audio = new Audio("/notify.wav");
audio.volume = 0.3;
audio.play();
}}
>
{download}
</Badge>
))}
</div>
</div>
);
};
export default StatefulDemo;

81
frontend/src/globals.scss Normal file
View File

@@ -0,0 +1,81 @@
@tailwind base;
@import url("https://fonts.googleapis.com/css2?family=Bebas+Neue&family=Source+Serif+4:ital,opsz,wght@0,8..60,200..900;1,8..60,200..900&display=swap");
.noise::after {
background-image: url("/noise.png");
position: fixed;
z-index: 10;
left: 0;
right: 0;
top: 0;
bottom: 0;
opacity: 50%;
content: " ";
pointer-events: none;
}
.noise-card {
@apply bg-zinc-800;
&::before {
position: absolute;
z-index: 30;
left: 0;
right: 0;
top: 0;
bottom: 0;
content: " ";
pointer-events: none;
background-image: url("/noise.png");
background-position-x: 66px;
// background-color: rgba(255, 255, 255, 6%);
opacity: 80%;
// filter: brightness(100%);
// background: linear-gradient(rgba(0, 0, 0, 0.2), rgba(0, 0, 0, 0.2)), url("/noise.png");
// #202020;
}
}
html,
body {
@apply overflow-x-hidden;
background-color: #151413;
color: #bab1a8;
margin: 0;
width: 100%;
height: 100%;
}
@layer base {
* {
/* @apply border-border; */
}
body {
/* @apply bg-background text-foreground; */
}
ul,
ol {
list-style: revert;
}
/* NEW CODE */
/* width */
::-webkit-scrollbar {
@apply w-2 rounded-lg;
}
/* Track */
::-webkit-scrollbar-track {
@apply bg-zinc-700 rounded-lg;
}
/* Handle */
::-webkit-scrollbar-thumb {
@apply bg-zinc-500 rounded-xl;
}
/* Handle on hover */
::-webkit-scrollbar-thumb:hover {
@apply bg-zinc-400 rounded-lg;
}
}

View File

@@ -6,16 +6,7 @@
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<title>Dynamic Preauth</title>
</head>
<body>
<body class="noise after:opacity-70">
<slot />
</body>
</html>
<style>
html,
body {
margin: 0;
width: 100%;
height: 100%;
}
</style>

View File

@@ -1,6 +1,51 @@
---
// import Welcome from '@/components/Welcome.astro';
import Layout from "@/layouts/Base.astro";
import Base from "@/layouts/Base.astro";
import StatefulDemo from "@/components/StatefulDemo.tsx";
import "@/globals.scss";
---
<Layout />
<Base>
<div class="w-screen h-screen flex flex-col items-center middle">
<div
class="noise-card rounded-sm relative z-20 border-zinc-700 border w-full max-w-[40rem] mt-16 mb-8 shadow-lg"
style={{
backgroundPosition:
Math.random() * 100 + "px " + Math.random() * 100 + "px",
}}
>
<div class="px-3 pt-4 pb-5 font-sans prose prose-zinc prose-invert">
<h1
class="text-5xl font-bebas bold text-center mb-3 text-zinc-300"
style={{ textShadow: "0 0 10px rgba(0,0,0,0.7)" }}
>
Dynamic Preauthentication
</h1>
<div class="px-5 leading-6">
<p class="mt-1">
This is a proof of concept for what I'm calling <b
class="text-teal-500">Dynamic Preauthentication</b
>. Essentially, a precompiled executable keeps a constant time
string that has a known (or easily extracted) pattern.
</p>
<p class="mt-0">
When a download is requested, the server can generate and embed a
token that allows the application to authenticate the user
immediately.
</p>
<p class="mt-0">
This would allow users to skip the initial login process and
immediately start using the application. It could also be used to
track downloads, hint at user behaviors, or create unique user
experiences.
</p>
</div>
<div class="inline-flex items-center justify-center w-full">
<hr class="w-32 h-px border-0 bg-zinc-600 my-0" />
<span class="px-3 text-2xl font-bebas tracking-wide">Demo</span>
<hr class="w-32 h-px border-0 bg-zinc-600 my-0" />
</div>
<StatefulDemo client:load />
</div>
</div>
</div>
</Base>

7
frontend/src/util.ts Normal file
View File

@@ -0,0 +1,7 @@
import { clsx, type ClassValue } from "clsx";
import { twMerge } from "tailwind-merge";
export { type ClassValue };
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs));
}

View File

@@ -1,8 +1,13 @@
/** @type {import('tailwindcss').Config} */
export default {
content: ['./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}'],
theme: {
extend: {},
},
plugins: [],
}
content: ["./src/**/*.{astro,html,js,jsx,ts,tsx}"],
theme: {
extend: {
fontFamily: {
bebas: ["Bebas Neue", "sans-serif"],
sans: ["Inter", "sans-serif"],
},
},
},
plugins: [require("@tailwindcss/typography")],
};