See the best posts from any Bluesky account
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Migrate to Tailwind CSS 4, replace all custom CSS and inline styles with utility classes

Installs tailwindcss + @tailwindcss/vite, strips app.css down to Tailwind imports and a
custom scale-up animation, removes the inline <style> block from layout.edge, and converts
every template from inline style attributes to Tailwind utilities.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

+544 -473
+3 -1
package.json
··· 78 78 "@adonisjs/vite": "^5.1.0", 79 79 "@atproto/api": "^0.19.8", 80 80 "@clickhouse/client": "^1.18.2", 81 + "@tailwindcss/vite": "^4.2.2", 81 82 "@vinejs/vine": "^4.3.0", 82 83 "better-sqlite3": "^12.8.0", 83 84 "edge.js": "^6.5.0", 84 85 "luxon": "^3.7.2", 85 - "reflect-metadata": "^0.2.2" 86 + "reflect-metadata": "^0.2.2", 87 + "tailwindcss": "^4.2.2" 86 88 }, 87 89 "hotHook": { 88 90 "boundaries": [
+422 -54
pnpm-lock.yaml
··· 28 28 version: 2.0.1(@adonisjs/assembler@8.4.0(typescript@6.0.2))(@adonisjs/core@7.3.1(@adonisjs/assembler@8.4.0(typescript@6.0.2))(@vinejs/vine@4.3.1)(edge.js@6.5.0)(pino-pretty@13.1.3)(youch@4.1.1)) 29 29 '@adonisjs/vite': 30 30 specifier: ^5.1.0 31 - version: 5.1.0(@adonisjs/assembler@8.4.0(typescript@6.0.2))(@adonisjs/core@7.3.1(@adonisjs/assembler@8.4.0(typescript@6.0.2))(@vinejs/vine@4.3.1)(edge.js@6.5.0)(pino-pretty@13.1.3)(youch@4.1.1))(@adonisjs/shield@9.0.0(@adonisjs/assembler@8.4.0(typescript@6.0.2))(@adonisjs/core@7.3.1(@adonisjs/assembler@8.4.0(typescript@6.0.2))(@vinejs/vine@4.3.1)(edge.js@6.5.0)(pino-pretty@13.1.3)(youch@4.1.1))(@adonisjs/session@8.1.0(6ec8878f6288127aeb8665fba21971dc))(@japa/api-client@3.2.1(@japa/assert@4.2.0(@japa/runner@5.3.0))(@japa/runner@5.3.0))(@japa/plugin-adonisjs@5.2.0(@adonisjs/core@7.3.1(@adonisjs/assembler@8.4.0(typescript@6.0.2))(@vinejs/vine@4.3.1)(edge.js@6.5.0)(pino-pretty@13.1.3)(youch@4.1.1))(@japa/api-client@3.2.1(@japa/assert@4.2.0(@japa/runner@5.3.0))(@japa/runner@5.3.0))(@japa/browser-client@2.3.0(@japa/assert@4.2.0(@japa/runner@5.3.0))(@japa/runner@5.3.0)(playwright@1.59.1))(@japa/runner@5.3.0)(playwright@1.59.1))(edge.js@6.5.0))(edge.js@6.5.0)(vite@7.3.2(@types/node@25.5.2)) 31 + version: 5.1.0(36f2255f94509bfb806708f28e3d804e) 32 32 '@atproto/api': 33 33 specifier: ^0.19.8 34 34 version: 0.19.8 35 35 '@clickhouse/client': 36 36 specifier: ^1.18.2 37 37 version: 1.18.2 38 + '@tailwindcss/vite': 39 + specifier: ^4.2.2 40 + version: 4.2.2(vite@7.3.2(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.32.0)) 38 41 '@vinejs/vine': 39 42 specifier: ^4.3.0 40 43 version: 4.3.1 ··· 50 53 reflect-metadata: 51 54 specifier: ^0.2.2 52 55 version: 0.2.2 56 + tailwindcss: 57 + specifier: ^4.2.2 58 + version: 4.2.2 53 59 devDependencies: 54 60 '@adonisjs/assembler': 55 61 specifier: ^8.3.0 56 62 version: 8.4.0(typescript@6.0.2) 57 63 '@adonisjs/eslint-config': 58 64 specifier: ^3.0.0 59 - version: 3.0.0(eslint@10.2.0)(prettier@3.8.2)(typescript@6.0.2) 65 + version: 3.0.0(eslint@10.2.0(jiti@2.6.1))(prettier@3.8.2)(typescript@6.0.2) 60 66 '@adonisjs/prettier-config': 61 67 specifier: ^1.4.5 62 68 version: 1.4.5 ··· 95 101 version: 3.15.11 96 102 eslint: 97 103 specifier: ^10.1.0 98 - version: 10.2.0 104 + version: 10.2.0(jiti@2.6.1) 99 105 execa: 100 106 specifier: ^9.6.1 101 107 version: 9.6.1 ··· 113 119 version: 6.0.2 114 120 vite: 115 121 specifier: ^7.3.1 116 - version: 7.3.2(@types/node@25.5.2) 122 + version: 7.3.2(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.32.0) 117 123 youch: 118 124 specifier: ^4.1.1 119 125 version: 4.1.1 ··· 816 822 resolution: {integrity: sha512-DmdYgtezMkh3cpU8/1uyXakv3tJRcmcXxBOcO0tbaozPwpmh4YMsnWrQm9ZmZMfa5ocbxzbFk6O4bDPEc/iAnA==} 817 823 engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} 818 824 825 + '@jridgewell/gen-mapping@0.3.13': 826 + resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==} 827 + 828 + '@jridgewell/remapping@2.3.5': 829 + resolution: {integrity: sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==} 830 + 831 + '@jridgewell/resolve-uri@3.1.2': 832 + resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} 833 + engines: {node: '>=6.0.0'} 834 + 835 + '@jridgewell/sourcemap-codec@1.5.5': 836 + resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==} 837 + 838 + '@jridgewell/trace-mapping@0.3.31': 839 + resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} 840 + 819 841 '@lukeed/ms@2.0.2': 820 842 resolution: {integrity: sha512-9I2Zn6+NJLfaGoz9jN3lpwDgAYvfGeNYdbAIjJOqzs4Tpc+VU3Jqq4IofSUBKajiDS8k9fZIg18/z13mpk1bsA==} 821 843 engines: {node: '>=8'} ··· 1172 1194 '@swc/types@0.1.26': 1173 1195 resolution: {integrity: sha512-lyMwd7WGgG79RS7EERZV3T8wMdmPq3xwyg+1nmAM64kIhx5yl+juO2PYIHb7vTiPgPCj8LYjsNV2T5wiQHUEaw==} 1174 1196 1197 + '@tailwindcss/node@4.2.2': 1198 + resolution: {integrity: sha512-pXS+wJ2gZpVXqFaUEjojq7jzMpTGf8rU6ipJz5ovJV6PUGmlJ+jvIwGrzdHdQ80Sg+wmQxUFuoW1UAAwHNEdFA==} 1199 + 1200 + '@tailwindcss/oxide-android-arm64@4.2.2': 1201 + resolution: {integrity: sha512-dXGR1n+P3B6748jZO/SvHZq7qBOqqzQ+yFrXpoOWWALWndF9MoSKAT3Q0fYgAzYzGhxNYOoysRvYlpixRBBoDg==} 1202 + engines: {node: '>= 20'} 1203 + cpu: [arm64] 1204 + os: [android] 1205 + 1206 + '@tailwindcss/oxide-darwin-arm64@4.2.2': 1207 + resolution: {integrity: sha512-iq9Qjr6knfMpZHj55/37ouZeykwbDqF21gPFtfnhCCKGDcPI/21FKC9XdMO/XyBM7qKORx6UIhGgg6jLl7BZlg==} 1208 + engines: {node: '>= 20'} 1209 + cpu: [arm64] 1210 + os: [darwin] 1211 + 1212 + '@tailwindcss/oxide-darwin-x64@4.2.2': 1213 + resolution: {integrity: sha512-BlR+2c3nzc8f2G639LpL89YY4bdcIdUmiOOkv2GQv4/4M0vJlpXEa0JXNHhCHU7VWOKWT/CjqHdTP8aUuDJkuw==} 1214 + engines: {node: '>= 20'} 1215 + cpu: [x64] 1216 + os: [darwin] 1217 + 1218 + '@tailwindcss/oxide-freebsd-x64@4.2.2': 1219 + resolution: {integrity: sha512-YUqUgrGMSu2CDO82hzlQ5qSb5xmx3RUrke/QgnoEx7KvmRJHQuZHZmZTLSuuHwFf0DJPybFMXMYf+WJdxHy/nQ==} 1220 + engines: {node: '>= 20'} 1221 + cpu: [x64] 1222 + os: [freebsd] 1223 + 1224 + '@tailwindcss/oxide-linux-arm-gnueabihf@4.2.2': 1225 + resolution: {integrity: sha512-FPdhvsW6g06T9BWT0qTwiVZYE2WIFo2dY5aCSpjG/S/u1tby+wXoslXS0kl3/KXnULlLr1E3NPRRw0g7t2kgaQ==} 1226 + engines: {node: '>= 20'} 1227 + cpu: [arm] 1228 + os: [linux] 1229 + 1230 + '@tailwindcss/oxide-linux-arm64-gnu@4.2.2': 1231 + resolution: {integrity: sha512-4og1V+ftEPXGttOO7eCmW7VICmzzJWgMx+QXAJRAhjrSjumCwWqMfkDrNu1LXEQzNAwz28NCUpucgQPrR4S2yw==} 1232 + engines: {node: '>= 20'} 1233 + cpu: [arm64] 1234 + os: [linux] 1235 + libc: [glibc] 1236 + 1237 + '@tailwindcss/oxide-linux-arm64-musl@4.2.2': 1238 + resolution: {integrity: sha512-oCfG/mS+/+XRlwNjnsNLVwnMWYH7tn/kYPsNPh+JSOMlnt93mYNCKHYzylRhI51X+TbR+ufNhhKKzm6QkqX8ag==} 1239 + engines: {node: '>= 20'} 1240 + cpu: [arm64] 1241 + os: [linux] 1242 + libc: [musl] 1243 + 1244 + '@tailwindcss/oxide-linux-x64-gnu@4.2.2': 1245 + resolution: {integrity: sha512-rTAGAkDgqbXHNp/xW0iugLVmX62wOp2PoE39BTCGKjv3Iocf6AFbRP/wZT/kuCxC9QBh9Pu8XPkv/zCZB2mcMg==} 1246 + engines: {node: '>= 20'} 1247 + cpu: [x64] 1248 + os: [linux] 1249 + libc: [glibc] 1250 + 1251 + '@tailwindcss/oxide-linux-x64-musl@4.2.2': 1252 + resolution: {integrity: sha512-XW3t3qwbIwiSyRCggeO2zxe3KWaEbM0/kW9e8+0XpBgyKU4ATYzcVSMKteZJ1iukJ3HgHBjbg9P5YPRCVUxlnQ==} 1253 + engines: {node: '>= 20'} 1254 + cpu: [x64] 1255 + os: [linux] 1256 + libc: [musl] 1257 + 1258 + '@tailwindcss/oxide-wasm32-wasi@4.2.2': 1259 + resolution: {integrity: sha512-eKSztKsmEsn1O5lJ4ZAfyn41NfG7vzCg496YiGtMDV86jz1q/irhms5O0VrY6ZwTUkFy/EKG3RfWgxSI3VbZ8Q==} 1260 + engines: {node: '>=14.0.0'} 1261 + cpu: [wasm32] 1262 + bundledDependencies: 1263 + - '@napi-rs/wasm-runtime' 1264 + - '@emnapi/core' 1265 + - '@emnapi/runtime' 1266 + - '@tybys/wasm-util' 1267 + - '@emnapi/wasi-threads' 1268 + - tslib 1269 + 1270 + '@tailwindcss/oxide-win32-arm64-msvc@4.2.2': 1271 + resolution: {integrity: sha512-qPmaQM4iKu5mxpsrWZMOZRgZv1tOZpUm+zdhhQP0VhJfyGGO3aUKdbh3gDZc/dPLQwW4eSqWGrrcWNBZWUWaXQ==} 1272 + engines: {node: '>= 20'} 1273 + cpu: [arm64] 1274 + os: [win32] 1275 + 1276 + '@tailwindcss/oxide-win32-x64-msvc@4.2.2': 1277 + resolution: {integrity: sha512-1T/37VvI7WyH66b+vqHj/cLwnCxt7Qt3WFu5Q8hk65aOvlwAhs7rAp1VkulBJw/N4tMirXjVnylTR72uI0HGcA==} 1278 + engines: {node: '>= 20'} 1279 + cpu: [x64] 1280 + os: [win32] 1281 + 1282 + '@tailwindcss/oxide@4.2.2': 1283 + resolution: {integrity: sha512-qEUA07+E5kehxYp9BVMpq9E8vnJuBHfJEC0vPC5e7iL/hw7HR61aDKoVoKzrG+QKp56vhNZe4qwkRmMC0zDLvg==} 1284 + engines: {node: '>= 20'} 1285 + 1286 + '@tailwindcss/vite@4.2.2': 1287 + resolution: {integrity: sha512-mEiF5HO1QqCLXoNEfXVA1Tzo+cYsrqV7w9Juj2wdUFyW07JRenqMG225MvPwr3ZD9N1bFQj46X7r33iHxLUW0w==} 1288 + peerDependencies: 1289 + vite: ^5.2.0 || ^6 || ^7 || ^8 1290 + 1175 1291 '@tokenizer/inflate@0.4.1': 1176 1292 resolution: {integrity: sha512-2mAv+8pkG6GIZiF1kNg1jAjh27IDxEPKwdGul3snfztFerfPGI1LjDezZp3i7BElXompqEtPmoPx6c2wgtWsOA==} 1177 1293 engines: {node: '>=18'} ··· 1675 1791 end-of-stream@1.4.5: 1676 1792 resolution: {integrity: sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==} 1677 1793 1794 + enhanced-resolve@5.20.1: 1795 + resolution: {integrity: sha512-Qohcme7V1inbAfvjItgw0EaxVX5q2rdVEZHRBrEQdRZTssLDGsL8Lwrznl8oQ/6kuTJONLaDcGjkNP247XEhcA==} 1796 + engines: {node: '>=10.13.0'} 1797 + 1678 1798 enquirer@2.4.1: 1679 1799 resolution: {integrity: sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==} 1680 1800 engines: {node: '>=8.6'} ··· 1990 2110 resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} 1991 2111 engines: {node: '>= 0.4'} 1992 2112 2113 + graceful-fs@4.2.11: 2114 + resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} 2115 + 1993 2116 has-flag@4.0.0: 1994 2117 resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} 1995 2118 engines: {node: '>=8'} ··· 2148 2271 resolution: {integrity: sha512-n3q4PDQjS4LrKxfWB3Z5KNk1XjXtZTBwQp71OP0Jo03Z6V60x++K5L8k6ZrW8MY8pOFylZvHM0zsjS1RqlHJZQ==} 2149 2272 engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} 2150 2273 2274 + jiti@2.6.1: 2275 + resolution: {integrity: sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==} 2276 + hasBin: true 2277 + 2151 2278 joycon@3.1.1: 2152 2279 resolution: {integrity: sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==} 2153 2280 engines: {node: '>=10'} ··· 2256 2383 resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} 2257 2384 engines: {node: '>= 0.8.0'} 2258 2385 2386 + lightningcss-android-arm64@1.32.0: 2387 + resolution: {integrity: sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==} 2388 + engines: {node: '>= 12.0.0'} 2389 + cpu: [arm64] 2390 + os: [android] 2391 + 2392 + lightningcss-darwin-arm64@1.32.0: 2393 + resolution: {integrity: sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==} 2394 + engines: {node: '>= 12.0.0'} 2395 + cpu: [arm64] 2396 + os: [darwin] 2397 + 2398 + lightningcss-darwin-x64@1.32.0: 2399 + resolution: {integrity: sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==} 2400 + engines: {node: '>= 12.0.0'} 2401 + cpu: [x64] 2402 + os: [darwin] 2403 + 2404 + lightningcss-freebsd-x64@1.32.0: 2405 + resolution: {integrity: sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==} 2406 + engines: {node: '>= 12.0.0'} 2407 + cpu: [x64] 2408 + os: [freebsd] 2409 + 2410 + lightningcss-linux-arm-gnueabihf@1.32.0: 2411 + resolution: {integrity: sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==} 2412 + engines: {node: '>= 12.0.0'} 2413 + cpu: [arm] 2414 + os: [linux] 2415 + 2416 + lightningcss-linux-arm64-gnu@1.32.0: 2417 + resolution: {integrity: sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==} 2418 + engines: {node: '>= 12.0.0'} 2419 + cpu: [arm64] 2420 + os: [linux] 2421 + libc: [glibc] 2422 + 2423 + lightningcss-linux-arm64-musl@1.32.0: 2424 + resolution: {integrity: sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==} 2425 + engines: {node: '>= 12.0.0'} 2426 + cpu: [arm64] 2427 + os: [linux] 2428 + libc: [musl] 2429 + 2430 + lightningcss-linux-x64-gnu@1.32.0: 2431 + resolution: {integrity: sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==} 2432 + engines: {node: '>= 12.0.0'} 2433 + cpu: [x64] 2434 + os: [linux] 2435 + libc: [glibc] 2436 + 2437 + lightningcss-linux-x64-musl@1.32.0: 2438 + resolution: {integrity: sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==} 2439 + engines: {node: '>= 12.0.0'} 2440 + cpu: [x64] 2441 + os: [linux] 2442 + libc: [musl] 2443 + 2444 + lightningcss-win32-arm64-msvc@1.32.0: 2445 + resolution: {integrity: sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==} 2446 + engines: {node: '>= 12.0.0'} 2447 + cpu: [arm64] 2448 + os: [win32] 2449 + 2450 + lightningcss-win32-x64-msvc@1.32.0: 2451 + resolution: {integrity: sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==} 2452 + engines: {node: '>= 12.0.0'} 2453 + cpu: [x64] 2454 + os: [win32] 2455 + 2456 + lightningcss@1.32.0: 2457 + resolution: {integrity: sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==} 2458 + engines: {node: '>= 12.0.0'} 2459 + 2259 2460 locate-path@6.0.0: 2260 2461 resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} 2261 2462 engines: {node: '>=10'} ··· 2277 2478 luxon@3.7.2: 2278 2479 resolution: {integrity: sha512-vtEhXh/gNjI9Yg1u4jX/0YVPMvxzHuGgCm6tC5kZyb08yjGWGnqAjGJvcXbqQR2P3MyMEFnRbpcdFS6PBcLqew==} 2279 2480 engines: {node: '>=12'} 2481 + 2482 + magic-string@0.30.21: 2483 + resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} 2280 2484 2281 2485 math-intrinsics@1.1.0: 2282 2486 resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} ··· 2835 3039 resolution: {integrity: sha512-yEFYrVhod+hdNyx7g5Bnkkb0G6si8HJurOoOEgC8B/O0uXLHlaey/65KRv6cuWBNhBgHKAROVpc7QyYqE5gFng==} 2836 3040 engines: {node: '>=20'} 2837 3041 3042 + tailwindcss@4.2.2: 3043 + resolution: {integrity: sha512-KWBIxs1Xb6NoLdMVqhbhgwZf2PGBpPEiwOqgI4pFIYbNTfBXiKYyWoTsXgBQ9WFg/OlhnvHaY+AEpW7wSmFo2Q==} 3044 + 3045 + tapable@2.3.2: 3046 + resolution: {integrity: sha512-1MOpMXuhGzGL5TTCZFItxCc0AARf1EZFQkGqMm7ERKj8+Hgr5oLvJOVFcC+lRmR8hCe2S3jC4T5D7Vg/d7/fhA==} 3047 + engines: {node: '>=6'} 3048 + 2838 3049 tar-fs@2.1.4: 2839 3050 resolution: {integrity: sha512-mDAjwmZdh7LTT6pNleZ05Yt65HC3E+NiQzl672vQG38jIrehtJk/J3mNwIg+vShQPcLF/LV7CMnDW6vjj6sfYQ==} 2840 3051 ··· 3199 3410 '@poppinss/validator-lite': 2.1.2 3200 3411 split-lines: 3.0.0 3201 3412 3202 - '@adonisjs/eslint-config@3.0.0(eslint@10.2.0)(prettier@3.8.2)(typescript@6.0.2)': 3413 + '@adonisjs/eslint-config@3.0.0(eslint@10.2.0(jiti@2.6.1))(prettier@3.8.2)(typescript@6.0.2)': 3203 3414 dependencies: 3204 - '@adonisjs/eslint-plugin': 2.2.2(eslint@10.2.0)(typescript@6.0.2) 3205 - '@stylistic/eslint-plugin': 5.10.0(eslint@10.2.0) 3206 - eslint: 10.2.0 3207 - eslint-config-prettier: 10.1.8(eslint@10.2.0) 3208 - eslint-plugin-prettier: 5.5.5(eslint-config-prettier@10.1.8(eslint@10.2.0))(eslint@10.2.0)(prettier@3.8.2) 3209 - eslint-plugin-unicorn: 63.0.0(eslint@10.2.0) 3415 + '@adonisjs/eslint-plugin': 2.2.2(eslint@10.2.0(jiti@2.6.1))(typescript@6.0.2) 3416 + '@stylistic/eslint-plugin': 5.10.0(eslint@10.2.0(jiti@2.6.1)) 3417 + eslint: 10.2.0(jiti@2.6.1) 3418 + eslint-config-prettier: 10.1.8(eslint@10.2.0(jiti@2.6.1)) 3419 + eslint-plugin-prettier: 5.5.5(eslint-config-prettier@10.1.8(eslint@10.2.0(jiti@2.6.1)))(eslint@10.2.0(jiti@2.6.1))(prettier@3.8.2) 3420 + eslint-plugin-unicorn: 63.0.0(eslint@10.2.0(jiti@2.6.1)) 3210 3421 prettier: 3.8.2 3211 - typescript-eslint: 8.58.1(eslint@10.2.0)(typescript@6.0.2) 3422 + typescript-eslint: 8.58.1(eslint@10.2.0(jiti@2.6.1))(typescript@6.0.2) 3212 3423 transitivePeerDependencies: 3213 3424 - '@types/eslint' 3214 3425 - supports-color 3215 3426 - typescript 3216 3427 3217 - '@adonisjs/eslint-plugin@2.2.2(eslint@10.2.0)(typescript@6.0.2)': 3428 + '@adonisjs/eslint-plugin@2.2.2(eslint@10.2.0(jiti@2.6.1))(typescript@6.0.2)': 3218 3429 dependencies: 3219 - '@typescript-eslint/utils': 8.58.1(eslint@10.2.0)(typescript@6.0.2) 3220 - eslint: 10.2.0 3430 + '@typescript-eslint/utils': 8.58.1(eslint@10.2.0(jiti@2.6.1))(typescript@6.0.2) 3431 + eslint: 10.2.0(jiti@2.6.1) 3221 3432 micromatch: 4.0.8 3222 3433 read-package-up: 12.0.0 3223 3434 transitivePeerDependencies: ··· 3386 3597 3387 3598 '@adonisjs/tsconfig@2.0.0': {} 3388 3599 3389 - '@adonisjs/vite@5.1.0(@adonisjs/assembler@8.4.0(typescript@6.0.2))(@adonisjs/core@7.3.1(@adonisjs/assembler@8.4.0(typescript@6.0.2))(@vinejs/vine@4.3.1)(edge.js@6.5.0)(pino-pretty@13.1.3)(youch@4.1.1))(@adonisjs/shield@9.0.0(@adonisjs/assembler@8.4.0(typescript@6.0.2))(@adonisjs/core@7.3.1(@adonisjs/assembler@8.4.0(typescript@6.0.2))(@vinejs/vine@4.3.1)(edge.js@6.5.0)(pino-pretty@13.1.3)(youch@4.1.1))(@adonisjs/session@8.1.0(6ec8878f6288127aeb8665fba21971dc))(@japa/api-client@3.2.1(@japa/assert@4.2.0(@japa/runner@5.3.0))(@japa/runner@5.3.0))(@japa/plugin-adonisjs@5.2.0(@adonisjs/core@7.3.1(@adonisjs/assembler@8.4.0(typescript@6.0.2))(@vinejs/vine@4.3.1)(edge.js@6.5.0)(pino-pretty@13.1.3)(youch@4.1.1))(@japa/api-client@3.2.1(@japa/assert@4.2.0(@japa/runner@5.3.0))(@japa/runner@5.3.0))(@japa/browser-client@2.3.0(@japa/assert@4.2.0(@japa/runner@5.3.0))(@japa/runner@5.3.0)(playwright@1.59.1))(@japa/runner@5.3.0)(playwright@1.59.1))(edge.js@6.5.0))(edge.js@6.5.0)(vite@7.3.2(@types/node@25.5.2))': 3600 + '@adonisjs/vite@5.1.0(36f2255f94509bfb806708f28e3d804e)': 3390 3601 dependencies: 3391 3602 '@adonisjs/core': 7.3.1(@adonisjs/assembler@8.4.0(typescript@6.0.2))(@vinejs/vine@4.3.1)(edge.js@6.5.0)(pino-pretty@13.1.3)(youch@4.1.1) 3392 3603 '@poppinss/utils': 7.0.1 3393 3604 edge-error: 4.0.2 3394 - vite: 7.3.2(@types/node@25.5.2) 3395 - vite-plugin-restart: 2.0.0(vite@7.3.2(@types/node@25.5.2)) 3605 + vite: 7.3.2(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.32.0) 3606 + vite-plugin-restart: 2.0.0(vite@7.3.2(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.32.0)) 3396 3607 optionalDependencies: 3397 3608 '@adonisjs/assembler': 8.4.0(typescript@6.0.2) 3398 3609 '@adonisjs/shield': 9.0.0(@adonisjs/assembler@8.4.0(typescript@6.0.2))(@adonisjs/core@7.3.1(@adonisjs/assembler@8.4.0(typescript@6.0.2))(@vinejs/vine@4.3.1)(edge.js@6.5.0)(pino-pretty@13.1.3)(youch@4.1.1))(@adonisjs/session@8.1.0(6ec8878f6288127aeb8665fba21971dc))(@japa/api-client@3.2.1(@japa/assert@4.2.0(@japa/runner@5.3.0))(@japa/runner@5.3.0))(@japa/plugin-adonisjs@5.2.0(@adonisjs/core@7.3.1(@adonisjs/assembler@8.4.0(typescript@6.0.2))(@vinejs/vine@4.3.1)(edge.js@6.5.0)(pino-pretty@13.1.3)(youch@4.1.1))(@japa/api-client@3.2.1(@japa/assert@4.2.0(@japa/runner@5.3.0))(@japa/runner@5.3.0))(@japa/browser-client@2.3.0(@japa/assert@4.2.0(@japa/runner@5.3.0))(@japa/runner@5.3.0)(playwright@1.59.1))(@japa/runner@5.3.0)(playwright@1.59.1))(edge.js@6.5.0) ··· 3617 3828 '@esbuild/win32-x64@0.27.7': 3618 3829 optional: true 3619 3830 3620 - '@eslint-community/eslint-utils@4.9.1(eslint@10.2.0)': 3831 + '@eslint-community/eslint-utils@4.9.1(eslint@10.2.0(jiti@2.6.1))': 3621 3832 dependencies: 3622 - eslint: 10.2.0 3833 + eslint: 10.2.0(jiti@2.6.1) 3623 3834 eslint-visitor-keys: 3.4.3 3624 3835 3625 3836 '@eslint-community/regexpp@4.12.2': {} ··· 3738 3949 dependencies: 3739 3950 '@sinclair/typebox': 0.34.49 3740 3951 3952 + '@jridgewell/gen-mapping@0.3.13': 3953 + dependencies: 3954 + '@jridgewell/sourcemap-codec': 1.5.5 3955 + '@jridgewell/trace-mapping': 0.3.31 3956 + 3957 + '@jridgewell/remapping@2.3.5': 3958 + dependencies: 3959 + '@jridgewell/gen-mapping': 0.3.13 3960 + '@jridgewell/trace-mapping': 0.3.31 3961 + 3962 + '@jridgewell/resolve-uri@3.1.2': {} 3963 + 3964 + '@jridgewell/sourcemap-codec@1.5.5': {} 3965 + 3966 + '@jridgewell/trace-mapping@0.3.31': 3967 + dependencies: 3968 + '@jridgewell/resolve-uri': 3.1.2 3969 + '@jridgewell/sourcemap-codec': 1.5.5 3970 + 3741 3971 '@lukeed/ms@2.0.2': {} 3742 3972 3743 3973 '@noble/hashes@1.8.0': {} ··· 3935 4165 3936 4166 '@standard-schema/spec@1.1.0': {} 3937 4167 3938 - '@stylistic/eslint-plugin@5.10.0(eslint@10.2.0)': 4168 + '@stylistic/eslint-plugin@5.10.0(eslint@10.2.0(jiti@2.6.1))': 3939 4169 dependencies: 3940 - '@eslint-community/eslint-utils': 4.9.1(eslint@10.2.0) 4170 + '@eslint-community/eslint-utils': 4.9.1(eslint@10.2.0(jiti@2.6.1)) 3941 4171 '@typescript-eslint/types': 8.58.1 3942 - eslint: 10.2.0 4172 + eslint: 10.2.0(jiti@2.6.1) 3943 4173 eslint-visitor-keys: 4.2.1 3944 4174 espree: 10.4.0 3945 4175 estraverse: 5.3.0 ··· 4005 4235 dependencies: 4006 4236 '@swc/counter': 0.1.3 4007 4237 4238 + '@tailwindcss/node@4.2.2': 4239 + dependencies: 4240 + '@jridgewell/remapping': 2.3.5 4241 + enhanced-resolve: 5.20.1 4242 + jiti: 2.6.1 4243 + lightningcss: 1.32.0 4244 + magic-string: 0.30.21 4245 + source-map-js: 1.2.1 4246 + tailwindcss: 4.2.2 4247 + 4248 + '@tailwindcss/oxide-android-arm64@4.2.2': 4249 + optional: true 4250 + 4251 + '@tailwindcss/oxide-darwin-arm64@4.2.2': 4252 + optional: true 4253 + 4254 + '@tailwindcss/oxide-darwin-x64@4.2.2': 4255 + optional: true 4256 + 4257 + '@tailwindcss/oxide-freebsd-x64@4.2.2': 4258 + optional: true 4259 + 4260 + '@tailwindcss/oxide-linux-arm-gnueabihf@4.2.2': 4261 + optional: true 4262 + 4263 + '@tailwindcss/oxide-linux-arm64-gnu@4.2.2': 4264 + optional: true 4265 + 4266 + '@tailwindcss/oxide-linux-arm64-musl@4.2.2': 4267 + optional: true 4268 + 4269 + '@tailwindcss/oxide-linux-x64-gnu@4.2.2': 4270 + optional: true 4271 + 4272 + '@tailwindcss/oxide-linux-x64-musl@4.2.2': 4273 + optional: true 4274 + 4275 + '@tailwindcss/oxide-wasm32-wasi@4.2.2': 4276 + optional: true 4277 + 4278 + '@tailwindcss/oxide-win32-arm64-msvc@4.2.2': 4279 + optional: true 4280 + 4281 + '@tailwindcss/oxide-win32-x64-msvc@4.2.2': 4282 + optional: true 4283 + 4284 + '@tailwindcss/oxide@4.2.2': 4285 + optionalDependencies: 4286 + '@tailwindcss/oxide-android-arm64': 4.2.2 4287 + '@tailwindcss/oxide-darwin-arm64': 4.2.2 4288 + '@tailwindcss/oxide-darwin-x64': 4.2.2 4289 + '@tailwindcss/oxide-freebsd-x64': 4.2.2 4290 + '@tailwindcss/oxide-linux-arm-gnueabihf': 4.2.2 4291 + '@tailwindcss/oxide-linux-arm64-gnu': 4.2.2 4292 + '@tailwindcss/oxide-linux-arm64-musl': 4.2.2 4293 + '@tailwindcss/oxide-linux-x64-gnu': 4.2.2 4294 + '@tailwindcss/oxide-linux-x64-musl': 4.2.2 4295 + '@tailwindcss/oxide-wasm32-wasi': 4.2.2 4296 + '@tailwindcss/oxide-win32-arm64-msvc': 4.2.2 4297 + '@tailwindcss/oxide-win32-x64-msvc': 4.2.2 4298 + 4299 + '@tailwindcss/vite@4.2.2(vite@7.3.2(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.32.0))': 4300 + dependencies: 4301 + '@tailwindcss/node': 4.2.2 4302 + '@tailwindcss/oxide': 4.2.2 4303 + tailwindcss: 4.2.2 4304 + vite: 7.3.2(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.32.0) 4305 + 4008 4306 '@tokenizer/inflate@0.4.1': 4009 4307 dependencies: 4010 4308 debug: 4.4.3 ··· 4060 4358 4061 4359 '@types/validator@13.15.10': {} 4062 4360 4063 - '@typescript-eslint/eslint-plugin@8.58.1(@typescript-eslint/parser@8.58.1(eslint@10.2.0)(typescript@6.0.2))(eslint@10.2.0)(typescript@6.0.2)': 4361 + '@typescript-eslint/eslint-plugin@8.58.1(@typescript-eslint/parser@8.58.1(eslint@10.2.0(jiti@2.6.1))(typescript@6.0.2))(eslint@10.2.0(jiti@2.6.1))(typescript@6.0.2)': 4064 4362 dependencies: 4065 4363 '@eslint-community/regexpp': 4.12.2 4066 - '@typescript-eslint/parser': 8.58.1(eslint@10.2.0)(typescript@6.0.2) 4364 + '@typescript-eslint/parser': 8.58.1(eslint@10.2.0(jiti@2.6.1))(typescript@6.0.2) 4067 4365 '@typescript-eslint/scope-manager': 8.58.1 4068 - '@typescript-eslint/type-utils': 8.58.1(eslint@10.2.0)(typescript@6.0.2) 4069 - '@typescript-eslint/utils': 8.58.1(eslint@10.2.0)(typescript@6.0.2) 4366 + '@typescript-eslint/type-utils': 8.58.1(eslint@10.2.0(jiti@2.6.1))(typescript@6.0.2) 4367 + '@typescript-eslint/utils': 8.58.1(eslint@10.2.0(jiti@2.6.1))(typescript@6.0.2) 4070 4368 '@typescript-eslint/visitor-keys': 8.58.1 4071 - eslint: 10.2.0 4369 + eslint: 10.2.0(jiti@2.6.1) 4072 4370 ignore: 7.0.5 4073 4371 natural-compare: 1.4.0 4074 4372 ts-api-utils: 2.5.0(typescript@6.0.2) ··· 4076 4374 transitivePeerDependencies: 4077 4375 - supports-color 4078 4376 4079 - '@typescript-eslint/parser@8.58.1(eslint@10.2.0)(typescript@6.0.2)': 4377 + '@typescript-eslint/parser@8.58.1(eslint@10.2.0(jiti@2.6.1))(typescript@6.0.2)': 4080 4378 dependencies: 4081 4379 '@typescript-eslint/scope-manager': 8.58.1 4082 4380 '@typescript-eslint/types': 8.58.1 4083 4381 '@typescript-eslint/typescript-estree': 8.58.1(typescript@6.0.2) 4084 4382 '@typescript-eslint/visitor-keys': 8.58.1 4085 4383 debug: 4.4.3 4086 - eslint: 10.2.0 4384 + eslint: 10.2.0(jiti@2.6.1) 4087 4385 typescript: 6.0.2 4088 4386 transitivePeerDependencies: 4089 4387 - supports-color ··· 4106 4404 dependencies: 4107 4405 typescript: 6.0.2 4108 4406 4109 - '@typescript-eslint/type-utils@8.58.1(eslint@10.2.0)(typescript@6.0.2)': 4407 + '@typescript-eslint/type-utils@8.58.1(eslint@10.2.0(jiti@2.6.1))(typescript@6.0.2)': 4110 4408 dependencies: 4111 4409 '@typescript-eslint/types': 8.58.1 4112 4410 '@typescript-eslint/typescript-estree': 8.58.1(typescript@6.0.2) 4113 - '@typescript-eslint/utils': 8.58.1(eslint@10.2.0)(typescript@6.0.2) 4411 + '@typescript-eslint/utils': 8.58.1(eslint@10.2.0(jiti@2.6.1))(typescript@6.0.2) 4114 4412 debug: 4.4.3 4115 - eslint: 10.2.0 4413 + eslint: 10.2.0(jiti@2.6.1) 4116 4414 ts-api-utils: 2.5.0(typescript@6.0.2) 4117 4415 typescript: 6.0.2 4118 4416 transitivePeerDependencies: ··· 4135 4433 transitivePeerDependencies: 4136 4434 - supports-color 4137 4435 4138 - '@typescript-eslint/utils@8.58.1(eslint@10.2.0)(typescript@6.0.2)': 4436 + '@typescript-eslint/utils@8.58.1(eslint@10.2.0(jiti@2.6.1))(typescript@6.0.2)': 4139 4437 dependencies: 4140 - '@eslint-community/eslint-utils': 4.9.1(eslint@10.2.0) 4438 + '@eslint-community/eslint-utils': 4.9.1(eslint@10.2.0(jiti@2.6.1)) 4141 4439 '@typescript-eslint/scope-manager': 8.58.1 4142 4440 '@typescript-eslint/types': 8.58.1 4143 4441 '@typescript-eslint/typescript-estree': 8.58.1(typescript@6.0.2) 4144 - eslint: 10.2.0 4442 + eslint: 10.2.0(jiti@2.6.1) 4145 4443 typescript: 6.0.2 4146 4444 transitivePeerDependencies: 4147 4445 - supports-color ··· 4490 4788 dependencies: 4491 4789 once: 1.4.0 4492 4790 4791 + enhanced-resolve@5.20.1: 4792 + dependencies: 4793 + graceful-fs: 4.2.11 4794 + tapable: 2.3.2 4795 + 4493 4796 enquirer@2.4.1: 4494 4797 dependencies: 4495 4798 ansi-colors: 4.1.3 ··· 4557 4860 4558 4861 escape-string-regexp@5.0.0: {} 4559 4862 4560 - eslint-config-prettier@10.1.8(eslint@10.2.0): 4863 + eslint-config-prettier@10.1.8(eslint@10.2.0(jiti@2.6.1)): 4561 4864 dependencies: 4562 - eslint: 10.2.0 4865 + eslint: 10.2.0(jiti@2.6.1) 4563 4866 4564 - eslint-plugin-prettier@5.5.5(eslint-config-prettier@10.1.8(eslint@10.2.0))(eslint@10.2.0)(prettier@3.8.2): 4867 + eslint-plugin-prettier@5.5.5(eslint-config-prettier@10.1.8(eslint@10.2.0(jiti@2.6.1)))(eslint@10.2.0(jiti@2.6.1))(prettier@3.8.2): 4565 4868 dependencies: 4566 - eslint: 10.2.0 4869 + eslint: 10.2.0(jiti@2.6.1) 4567 4870 prettier: 3.8.2 4568 4871 prettier-linter-helpers: 1.0.1 4569 4872 synckit: 0.11.12 4570 4873 optionalDependencies: 4571 - eslint-config-prettier: 10.1.8(eslint@10.2.0) 4874 + eslint-config-prettier: 10.1.8(eslint@10.2.0(jiti@2.6.1)) 4572 4875 4573 - eslint-plugin-unicorn@63.0.0(eslint@10.2.0): 4876 + eslint-plugin-unicorn@63.0.0(eslint@10.2.0(jiti@2.6.1)): 4574 4877 dependencies: 4575 4878 '@babel/helper-validator-identifier': 7.28.5 4576 - '@eslint-community/eslint-utils': 4.9.1(eslint@10.2.0) 4879 + '@eslint-community/eslint-utils': 4.9.1(eslint@10.2.0(jiti@2.6.1)) 4577 4880 change-case: 5.4.4 4578 4881 ci-info: 4.4.0 4579 4882 clean-regexp: 1.0.0 4580 4883 core-js-compat: 3.49.0 4581 - eslint: 10.2.0 4884 + eslint: 10.2.0(jiti@2.6.1) 4582 4885 find-up-simple: 1.0.1 4583 4886 globals: 16.5.0 4584 4887 indent-string: 5.0.0 ··· 4603 4906 4604 4907 eslint-visitor-keys@5.0.1: {} 4605 4908 4606 - eslint@10.2.0: 4909 + eslint@10.2.0(jiti@2.6.1): 4607 4910 dependencies: 4608 - '@eslint-community/eslint-utils': 4.9.1(eslint@10.2.0) 4911 + '@eslint-community/eslint-utils': 4.9.1(eslint@10.2.0(jiti@2.6.1)) 4609 4912 '@eslint-community/regexpp': 4.12.2 4610 4913 '@eslint/config-array': 0.23.5 4611 4914 '@eslint/config-helpers': 0.5.5 ··· 4635 4938 minimatch: 10.2.5 4636 4939 natural-compare: 1.4.0 4637 4940 optionator: 0.9.4 4941 + optionalDependencies: 4942 + jiti: 2.6.1 4638 4943 transitivePeerDependencies: 4639 4944 - supports-color 4640 4945 ··· 4835 5140 globals@16.5.0: {} 4836 5141 4837 5142 gopd@1.2.0: {} 5143 + 5144 + graceful-fs@4.2.11: {} 4838 5145 4839 5146 has-flag@4.0.0: {} 4840 5147 ··· 4955 5262 chalk: 4.1.2 4956 5263 pretty-format: 30.3.0 4957 5264 5265 + jiti@2.6.1: {} 5266 + 4958 5267 joycon@3.1.1: {} 4959 5268 4960 5269 js-stringify@1.0.2: {} ··· 5041 5350 prelude-ls: 1.2.1 5042 5351 type-check: 0.4.0 5043 5352 5353 + lightningcss-android-arm64@1.32.0: 5354 + optional: true 5355 + 5356 + lightningcss-darwin-arm64@1.32.0: 5357 + optional: true 5358 + 5359 + lightningcss-darwin-x64@1.32.0: 5360 + optional: true 5361 + 5362 + lightningcss-freebsd-x64@1.32.0: 5363 + optional: true 5364 + 5365 + lightningcss-linux-arm-gnueabihf@1.32.0: 5366 + optional: true 5367 + 5368 + lightningcss-linux-arm64-gnu@1.32.0: 5369 + optional: true 5370 + 5371 + lightningcss-linux-arm64-musl@1.32.0: 5372 + optional: true 5373 + 5374 + lightningcss-linux-x64-gnu@1.32.0: 5375 + optional: true 5376 + 5377 + lightningcss-linux-x64-musl@1.32.0: 5378 + optional: true 5379 + 5380 + lightningcss-win32-arm64-msvc@1.32.0: 5381 + optional: true 5382 + 5383 + lightningcss-win32-x64-msvc@1.32.0: 5384 + optional: true 5385 + 5386 + lightningcss@1.32.0: 5387 + dependencies: 5388 + detect-libc: 2.1.2 5389 + optionalDependencies: 5390 + lightningcss-android-arm64: 1.32.0 5391 + lightningcss-darwin-arm64: 1.32.0 5392 + lightningcss-darwin-x64: 1.32.0 5393 + lightningcss-freebsd-x64: 1.32.0 5394 + lightningcss-linux-arm-gnueabihf: 1.32.0 5395 + lightningcss-linux-arm64-gnu: 1.32.0 5396 + lightningcss-linux-arm64-musl: 1.32.0 5397 + lightningcss-linux-x64-gnu: 1.32.0 5398 + lightningcss-linux-x64-musl: 1.32.0 5399 + lightningcss-win32-arm64-msvc: 1.32.0 5400 + lightningcss-win32-x64-msvc: 1.32.0 5401 + 5044 5402 locate-path@6.0.0: 5045 5403 dependencies: 5046 5404 p-locate: 5.0.0 ··· 5060 5418 lru-cache@11.3.3: {} 5061 5419 5062 5420 luxon@3.7.2: {} 5421 + 5422 + magic-string@0.30.21: 5423 + dependencies: 5424 + '@jridgewell/sourcemap-codec': 1.5.5 5063 5425 5064 5426 math-intrinsics@1.1.0: {} 5065 5427 ··· 5633 5995 5634 5996 tagged-tag@1.0.0: {} 5635 5997 5998 + tailwindcss@4.2.2: {} 5999 + 6000 + tapable@2.3.2: {} 6001 + 5636 6002 tar-fs@2.1.4: 5637 6003 dependencies: 5638 6004 chownr: 1.1.4 ··· 5718 6084 media-typer: 1.1.0 5719 6085 mime-types: 3.0.2 5720 6086 5721 - typescript-eslint@8.58.1(eslint@10.2.0)(typescript@6.0.2): 6087 + typescript-eslint@8.58.1(eslint@10.2.0(jiti@2.6.1))(typescript@6.0.2): 5722 6088 dependencies: 5723 - '@typescript-eslint/eslint-plugin': 8.58.1(@typescript-eslint/parser@8.58.1(eslint@10.2.0)(typescript@6.0.2))(eslint@10.2.0)(typescript@6.0.2) 5724 - '@typescript-eslint/parser': 8.58.1(eslint@10.2.0)(typescript@6.0.2) 6089 + '@typescript-eslint/eslint-plugin': 8.58.1(@typescript-eslint/parser@8.58.1(eslint@10.2.0(jiti@2.6.1))(typescript@6.0.2))(eslint@10.2.0(jiti@2.6.1))(typescript@6.0.2) 6090 + '@typescript-eslint/parser': 8.58.1(eslint@10.2.0(jiti@2.6.1))(typescript@6.0.2) 5725 6091 '@typescript-eslint/typescript-estree': 8.58.1(typescript@6.0.2) 5726 - '@typescript-eslint/utils': 8.58.1(eslint@10.2.0)(typescript@6.0.2) 5727 - eslint: 10.2.0 6092 + '@typescript-eslint/utils': 8.58.1(eslint@10.2.0(jiti@2.6.1))(typescript@6.0.2) 6093 + eslint: 10.2.0(jiti@2.6.1) 5728 6094 typescript: 6.0.2 5729 6095 transitivePeerDependencies: 5730 6096 - supports-color ··· 5774 6140 5775 6141 vary@1.1.2: {} 5776 6142 5777 - vite-plugin-restart@2.0.0(vite@7.3.2(@types/node@25.5.2)): 6143 + vite-plugin-restart@2.0.0(vite@7.3.2(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.32.0)): 5778 6144 dependencies: 5779 6145 micromatch: 4.0.8 5780 - vite: 7.3.2(@types/node@25.5.2) 6146 + vite: 7.3.2(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.32.0) 5781 6147 5782 - vite@7.3.2(@types/node@25.5.2): 6148 + vite@7.3.2(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.32.0): 5783 6149 dependencies: 5784 6150 esbuild: 0.27.7 5785 6151 fdir: 6.5.0(picomatch@4.0.4) ··· 5790 6156 optionalDependencies: 5791 6157 '@types/node': 25.5.2 5792 6158 fsevents: 2.3.3 6159 + jiti: 2.6.1 6160 + lightningcss: 1.32.0 5793 6161 5794 6162 which@2.0.2: 5795 6163 dependencies:
+10 -225
resources/css/app.css
··· 1 - :root { 2 - --gray-1: oklch(98.5% 0 0); 3 - --gray-2: oklch(97% 0 0); 4 - --gray-3: oklch(92.2% 0 0); 5 - --gray-4: oklch(87% 0 0); 6 - --gray-6: oklch(55.6% 0 0); 7 - --gray-7: oklch(43.9% 0 0); 8 - --gray-8: oklch(37.1% 0 0); 9 - --gray-10: oklch(26.9% 0 0); 10 - --gray-12: oklch(14.5% 0 0); 11 - } 12 - 13 - * { 14 - box-sizing: border-box; 15 - margin: 0; 16 - padding: 0; 17 - } 18 - 19 - html, 20 - body { 21 - height: 100%; 22 - font-family: system-ui, sans-serif; 23 - -webkit-font-smoothing: antialiased; 24 - background: var(--gray-2); 25 - color: var(--gray-10); 26 - font-size: 16px; 27 - line-height: 1.5; 28 - } 29 - 30 - a { 31 - color: inherit; 32 - text-decoration: none; 33 - } 34 - 35 - [x-cloak] { 36 - display: none; 37 - } 38 - 39 - h1, 40 - h2, 41 - h3, 42 - h4, 43 - h5, 44 - h6 { 45 - color: var(--gray-12); 46 - } 47 - 48 - /* Header */ 49 - header { 50 - max-width: 1440px; 51 - margin: auto; 52 - padding: 0 30px; 53 - } 54 - header > div { 55 - display: flex; 56 - justify-content: space-between; 57 - align-items: center; 58 - height: 64px; 59 - } 60 - header nav { 61 - display: flex; 62 - align-items: center; 63 - gap: 26px; 64 - } 65 - header nav a { 66 - font-weight: 500; 67 - color: var(--gray-8); 68 - } 69 - header nav a:hover, 70 - header nav a.current { 71 - color: var(--gray-12); 72 - } 1 + @import 'tailwindcss'; 2 + @source '../views'; 73 3 74 - /* Main */ 75 - main { 76 - max-width: 1440px; 77 - margin: 0 30px; 78 - display: flex; 79 - flex-direction: column; 80 - justify-content: space-between; 81 - min-height: calc(100vh - 65px); 82 - background: #fff; 83 - border: 1px solid var(--gray-3); 84 - } 85 - 86 - .hero { 87 - padding: 100px 50px; 88 - max-width: 880px; 89 - } 90 - .hero h1 { 91 - margin-bottom: 15px; 92 - font-size: 52px; 93 - font-weight: 600; 94 - letter-spacing: -1px; 95 - line-height: 1.05; 96 - } 97 - .hero p { 98 - font-size: 22px; 99 - color: var(--gray-7); 100 - } 101 - .hero .button { 102 - margin-top: 30px; 103 - display: inline-block; 104 - padding: 10px 16px; 105 - } 106 - 107 - .cards { 108 - display: grid; 109 - grid-template-columns: repeat(3, 1fr); 110 - padding: 0 50px; 111 - border-top: 1px solid var(--gray-3); 112 - } 113 - .cards a { 114 - padding: 30px 40px; 115 - border-right: 1px solid var(--gray-3); 116 - } 117 - .cards a:first-child { 118 - border-left: 1px solid var(--gray-3); 119 - } 120 - .cards a:hover { 121 - background: var(--gray-1); 122 - } 123 - .cards h3 { 124 - margin-bottom: 10px; 125 - font-size: 20px; 126 - font-weight: 600; 127 - letter-spacing: -0.4px; 128 - } 129 - .cards p { 130 - color: var(--gray-6); 131 - } 132 - 133 - /* Form */ 134 - .form-container { 135 - display: flex; 136 - flex-direction: column; 137 - justify-content: center; 138 - max-width: 400px; 139 - margin: auto; 140 - } 141 - .form-container h1 { 142 - font-size: 32px; 143 - letter-spacing: -0.5px; 144 - margin: 5px 0; 145 - } 146 - .form-container p { 147 - font-size: 18px; 148 - margin-bottom: 48px; 149 - color: var(--gray-6); 150 - } 151 - form { 152 - display: flex; 153 - flex-direction: column; 154 - gap: 24px; 155 - } 156 - label { 157 - margin-bottom: 4px; 158 - display: block; 159 - font-size: 14px; 160 - font-weight: 500; 161 - } 162 - input, 163 - textarea, 164 - button { 165 - width: 100%; 166 - border-radius: 4px; 167 - font: inherit; 168 - } 169 - input { 170 - height: 40px; 171 - border: 1px solid var(--gray-4); 172 - padding: 0 16px; 173 - } 174 - input[data-invalid='true'], 175 - textarea[data-invalid='true'] { 176 - border-color: #fb2c36; 177 - } 178 - input[data-invalid='true'] + div, 179 - textarea[data-invalid='true'] + div { 180 - color: #fb2c36; 181 - font-size: 14px; 182 - font-weight: 500; 183 - margin-top: 2px; 184 - } 185 - 186 - button { 187 - background: var(--gray-12); 188 - color: #fff; 189 - border: none; 190 - padding: 10px; 191 - font-weight: 500; 192 - } 193 - button:hover { 194 - background: var(--gray-10); 195 - } 196 - 197 - /* Alerts */ 198 - .alert { 199 - background: #fff; 200 - position: relative; 201 - padding: 12px 16px; 202 - font-size: 14px; 203 - min-width: 380px; 204 - font-weight: 500; 205 - border: 1px solid var(--gray-3); 206 - border-radius: 10px; 207 - animation: scale-up 0.2s cubic-bezier(0.39, 0.575, 0.565, 1) both; 208 - } 209 - .alert-destructive { 210 - color: #fb2c36; 211 - background: #fb2c361a; 212 - border-color: #fb2c36; 213 - } 214 - .alert-success { 215 - color: #00a63e; 216 - background: #00a63e1a; 217 - border-color: #00a63e; 218 - } 219 - .flash-container { 220 - position: fixed; 221 - top: 80px; 222 - left: 0; 223 - right: 0; 224 - display: flex; 225 - flex-direction: column; 226 - align-items: center; 4 + @theme { 5 + --animate-scale-up: scale-up 0.2s cubic-bezier(0.39, 0.575, 0.565, 1) both; 227 6 } 228 7 229 8 @keyframes scale-up { ··· 234 13 transform: scale(1); 235 14 } 236 15 } 16 + 17 + @layer base { 18 + [x-cloak] { 19 + display: none !important; 20 + } 21 + }
+6 -1
resources/views/components/alert/root.edge
··· 1 1 @let(variant = $props.get('variant') || 'default') 2 2 @inject({ variant, autoDismiss: $props.get('autoDismiss') }) 3 - @let(classes = ['alert', `alert-${variant}`]) 3 + @let(variantClasses = { 4 + default: 'bg-white border-gray-200', 5 + destructive: 'text-red-500 bg-red-500/10 border-red-500', 6 + success: 'text-green-600 bg-green-600/10 border-green-600', 7 + }) 8 + @let(classes = ['relative', 'py-3', 'px-4', 'text-sm', 'min-w-[380px]', 'font-medium', 'border', 'rounded-[10px]', 'animate-scale-up', variantClasses[variant] || variantClasses.default]) 4 9 5 10 <div {{ $props 6 11 .except(['variant', 'autoDismiss'])
+1 -1
resources/views/components/button.edge
··· 1 1 @let(buttonTextFromSlot = await $slots.main()) 2 2 @let(buttonText = buttonTextFromSlot.trim() ? buttonTextFromSlot : $props.get('text') ?? '') 3 - @let(classes = []) 3 + @let(classes = ['w-full', 'rounded', 'font-inherit', 'bg-gray-900', 'text-white', 'border-none', 'py-2.5', 'font-medium', 'hover:bg-gray-800', 'cursor-pointer']) 4 4 5 5 <button {{ 6 6 $props.except(['text']).merge({ class: classes }).toAttrs()
+1 -1
resources/views/components/field/error.edge
··· 1 - @let(classes = []) 1 + @let(classes = ['text-red-500', 'text-sm', 'font-medium', 'mt-0.5']) 2 2 3 3 @if($context.hasErrors) 4 4 <div {{ $props.merge({ id: `${$context.id}-error`, class: classes }).toAttrs() }}>
+1 -1
resources/views/components/field/label.edge
··· 1 1 @let(labelTextFromSlot = await $slots.main()) 2 2 @let(labelText = labelTextFromSlot.trim() ? labelTextFromSlot : $props.get('text')) 3 - @let(classes = []) 3 + @let(classes = ['mb-1', 'block', 'text-sm', 'font-medium']) 4 4 5 5 <label {{ $props 6 6 .except(['text'])
+1 -1
resources/views/components/input/control.edge
··· 3 3 ? $context.oldValue || $props.get('value') || '' 4 4 : $props.get('value') || '' 5 5 ) 6 - @let(classes = []) 6 + @let(classes = ['w-full', 'rounded', 'font-inherit', 'h-10', 'border', 'border-gray-300', 'px-4', 'data-[invalid=true]:border-red-500']) 7 7 8 8 <input {{ $props 9 9 .except(['value'])
+5 -29
resources/views/components/layout.edge
··· 17 17 @if(typeof canonicalUrl !== 'undefined' && canonicalUrl) 18 18 <link rel="canonical" href="{{ canonicalUrl }}" /> 19 19 @endif 20 - <style> 21 - [x-cloak] { display: none !important; } 22 - *, *::before, *::after { box-sizing: border-box; } 23 - body { 24 - font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif; 25 - font-size: 16px; 26 - line-height: 1.5; 27 - color: #1a1a1a; 28 - background: #f9f9f9; 29 - margin: 0; 30 - padding: 0; 31 - } 32 - a { color: #0066cc; text-decoration: none; } 33 - a:hover { text-decoration: underline; } 34 - .container { max-width: 680px; margin: 0 auto; padding: 0 16px; } 35 - .site-footer { 36 - margin-top: 48px; 37 - padding: 24px 0; 38 - border-top: 1px solid #eee; 39 - font-size: 13px; 40 - color: #888; 41 - text-align: center; 42 - } 43 - </style> 44 20 </head> 45 - <body> 46 - <div class="container"> 21 + <body class="font-sans text-base leading-normal text-gray-900 bg-gray-50"> 22 + <div class="max-w-[680px] mx-auto px-4"> 47 23 {{{ await $slots.main() }}} 48 - <footer class="site-footer"> 49 - <a href="/">skystar.social</a> &middot; 50 - <a href="/about">about</a> 24 + <footer class="mt-12 py-6 border-t border-gray-200 text-[13px] text-gray-400 text-center"> 25 + <a href="/" class="text-blue-600 hover:underline">skystar.social</a> &middot; 26 + <a href="/about" class="text-blue-600 hover:underline">about</a> 51 27 </footer> 52 28 </div> 53 29 </body>
+2 -2
resources/views/components/link.edge
··· 10 10 ) 11 11 : undefined 12 12 ) 13 - @let(activeClass = request.url() === linkHref ? 'current' : '') 14 - @let(classes = [activeClass]) 13 + @let(activeClass = request.url() === linkHref ? 'text-gray-900' : 'text-gray-700') 14 + @let(classes = ['font-medium', 'hover:text-gray-900', activeClass]) 15 15 16 16 <a {{ $props 17 17 .except(['href', 'text', 'route', 'routeParams', 'routeOptions'])
+1 -1
resources/views/components/textarea/control.edge
··· 1 - @let(classes = []) 1 + @let(classes = ['w-full', 'rounded', 'font-inherit', 'border', 'border-gray-300', 'px-4', 'py-2', 'data-[invalid=true]:border-red-500']) 2 2 3 3 <textarea {{ $props 4 4 .except(['value'])
+7 -7
resources/views/pages/about.edge
··· 4 4 @endslot 5 5 6 6 @slot('main') 7 - <div style="padding: 48px 0;"> 8 - <h1 style="font-size: 1.8rem; margin-bottom: 24px;">About skystar</h1> 7 + <div class="py-12 space-y-4"> 8 + <h1 class="text-3xl font-bold mb-6">About skystar</h1> 9 9 <p> 10 - skystar is a <a href="https://favstar.fm" target="_blank" rel="noopener">favstar.fm</a>-style 11 - site for <a href="https://bsky.app" target="_blank" rel="noopener">Bluesky</a>. 10 + skystar is a <a href="https://favstar.fm" target="_blank" rel="noopener" class="text-blue-600 hover:underline">favstar.fm</a>-style 11 + site for <a href="https://bsky.app" target="_blank" rel="noopener" class="text-blue-600 hover:underline">Bluesky</a>. 12 12 Type any handle and see that account's most-liked and most-reposted posts, powered by the 13 - <a href="https://atproto.com" target="_blank" rel="noopener">AT Protocol</a> firehose. 13 + <a href="https://atproto.com" target="_blank" rel="noopener" class="text-blue-600 hover:underline">AT Protocol</a> firehose. 14 14 </p> 15 15 <p> 16 16 Data is collected from the Bluesky Jetstream feed and updated in near real-time. ··· 22 22 </p> 23 23 <p> 24 24 {{-- TODO: add GitHub URL --}} 25 - Source code: <a href="https://github.com/TODO/skystar" target="_blank" rel="noopener">github.com/TODO/skystar</a> 25 + Source code: <a href="https://github.com/TODO/skystar" target="_blank" rel="noopener" class="text-blue-600 hover:underline">github.com/TODO/skystar</a> 26 26 </p> 27 - <p><a href="/">← Back to search</a></p> 27 + <p><a href="/" class="text-blue-600 hover:underline">← Back to search</a></p> 28 28 </div> 29 29 @endslot 30 30 @endcomponent
+3 -3
resources/views/pages/errors/not_found.edge
··· 4 4 @endslot 5 5 6 6 @slot('main') 7 - <div style="padding: 64px 0; text-align: center;"> 8 - <h1 style="font-size: 1.6rem; margin-bottom: 16px;"> 7 + <div class="py-16 text-center"> 8 + <h1 class="text-2xl mb-4"> 9 9 @if(handle) 10 10 We can't find {{ '@' + handle }} on Bluesky. Did you typo? 11 11 @else 12 12 Page not found. 13 13 @endif 14 14 </h1> 15 - <p><a href="/">← Try another handle</a></p> 15 + <p><a href="/" class="text-blue-600 hover:underline">← Try another handle</a></p> 16 16 </div> 17 17 @endslot 18 18 @endcomponent
+3 -3
resources/views/pages/errors/server_error.edge
··· 4 4 @endslot 5 5 6 6 @slot('main') 7 - <div style="padding: 64px 0; text-align: center;"> 8 - <h1 style="font-size: 1.6rem; margin-bottom: 16px;"> 7 + <div class="py-16 text-center"> 8 + <h1 class="text-2xl mb-4"> 9 9 {{ message ?? "We're having a moment, try again in a sec." }} 10 10 </h1> 11 - <p><a href="/">← Back to search</a></p> 11 + <p><a href="/" class="text-blue-600 hover:underline">← Back to search</a></p> 12 12 </div> 13 13 @endslot 14 14 @endcomponent
+1 -1
resources/views/pages/home.edge
··· 1 1 @component('components/layout') 2 2 @slot('main') 3 - <div style="padding: 64px 0; text-align: center;"> 3 + <div class="py-16 text-center"> 4 4 <p>Redirecting…</p> 5 5 </div> 6 6 @endslot
+11 -26
resources/views/pages/landing.edge
··· 1 1 @component('components/layout') 2 2 @slot('main') 3 - <div style="padding: 64px 0 48px;"> 4 - <h1 style="font-size: 2rem; font-weight: 700; margin: 0 0 8px;">skystar ✦</h1> 5 - <p style="font-size: 1.1rem; color: #555; margin: 0 0 40px;"> 3 + <div class="pt-16 pb-12"> 4 + <h1 class="text-3xl font-bold mb-2">skystar ✦</h1> 5 + <p class="text-lg text-gray-600 mb-10"> 6 6 See any Bluesky account's most-liked and most-reposted posts. 7 7 </p> 8 8 9 - <form action="/search" method="GET" style="display: flex; gap: 8px; margin-bottom: 16px;"> 9 + <form action="/search" method="GET" class="flex gap-2 mb-4"> 10 10 <input 11 11 type="text" 12 12 name="q" 13 13 placeholder="@handle or handle.bsky.social" 14 14 autofocus 15 - style=" 16 - flex: 1; 17 - padding: 10px 14px; 18 - font-size: 1rem; 19 - border: 1px solid #ccc; 20 - border-radius: 6px; 21 - outline: none; 22 - " 15 + class="flex-1 px-3.5 py-2.5 text-base border border-gray-300 rounded-md outline-none focus:border-blue-500" 23 16 /> 24 17 <button 25 18 type="submit" 26 - style=" 27 - padding: 10px 20px; 28 - font-size: 1rem; 29 - background: #0066cc; 30 - color: #fff; 31 - border: none; 32 - border-radius: 6px; 33 - cursor: pointer; 34 - " 19 + class="px-5 py-2.5 text-base bg-blue-600 text-white border-none rounded-md cursor-pointer hover:bg-blue-700" 35 20 > 36 21 Go 37 22 </button> 38 23 </form> 39 24 40 25 @if(error) 41 - <p style="color: #cc0000; margin: 0 0 16px; font-size: 0.95rem;">{{ error }}</p> 26 + <p class="text-red-700 mb-4 text-[0.95rem]">{{ error }}</p> 42 27 @endif 43 28 44 - <p style="font-size: 0.9rem; color: #888; margin: 0 0 32px;"> 29 + <p class="text-sm text-gray-400 mb-8"> 45 30 Try an example: 46 31 @each(handle in examples) 47 - <a href="/profile/{{ handle }}/likes" style="margin-right: 12px;">{{ handle }}</a> 32 + <a href="/profile/{{ handle }}/likes" class="mr-3 text-blue-600 hover:underline">{{ handle }}</a> 48 33 @endeach 49 34 </p> 50 35 51 - <p style="font-size: 0.9rem; color: #666; max-width: 520px;"> 36 + <p class="text-sm text-gray-500 max-w-[520px]"> 52 37 skystar indexes Bluesky posts and tracks engagement from the 53 - <a href="https://atproto.com" target="_blank" rel="noopener">AT Protocol</a> firehose. 38 + <a href="https://atproto.com" target="_blank" rel="noopener" class="text-blue-600 hover:underline">AT Protocol</a> firehose. 54 39 Type a handle to see that account's greatest hits. 55 40 No login required. 56 41 </p>
+4 -4
resources/views/pages/profile/gone.edge
··· 4 4 @endslot 5 5 6 6 @slot('main') 7 - <div style="padding: 64px 0; text-align: center;"> 8 - <h1 style="font-size: 1.6rem; margin-bottom: 16px;">{{ '@' + handle }} is no longer available.</h1> 9 - <p style="color: #666;"> 7 + <div class="py-16 text-center"> 8 + <h1 class="text-2xl mb-4">{{ '@' + handle }} is no longer available.</h1> 9 + <p class="text-gray-500"> 10 10 This account has been deleted or taken down from Bluesky. 11 11 </p> 12 - <p><a href="/">← Back to search</a></p> 12 + <p><a href="/" class="text-blue-600 hover:underline">← Back to search</a></p> 13 13 </div> 14 14 @endslot 15 15 @endcomponent
+7 -7
resources/views/pages/profile/loading.edge
··· 13 13 @slot('main') 14 14 <div 15 15 x-data="backfillProgress({ handle: '{{ handle }}', total: {{ totalPosts }} })" 16 - style="padding: 64px 0; text-align: center;" 16 + class="py-16 text-center" 17 17 > 18 18 <div x-show="state !== 'failed'"> 19 - <h1 id="backfill-title" style="font-size: 1.6rem; margin-bottom: 16px;"> 19 + <h1 id="backfill-title" class="text-2xl mb-4"> 20 20 Indexing {{ '@' + handle }}… 21 21 </h1> 22 - <p style="color: #666; max-width: 420px; margin: 0 auto 24px;"> 22 + <p class="text-gray-500 max-w-[420px] mx-auto mb-6"> 23 23 This is a one-time index. It may take a few minutes for very active accounts. 24 24 </p> 25 25 <progress 26 26 max="{{ totalPosts }}" 27 27 x-bind:value="fetched" 28 28 aria-labelledby="backfill-title" 29 - style="width: 320px; max-width: 80%; height: 14px;" 29 + class="w-80 max-w-[80%] h-3.5" 30 30 ></progress> 31 31 <p 32 32 aria-live="polite" 33 33 aria-atomic="true" 34 - style="color: #666; margin-top: 12px; font-variant-numeric: tabular-nums;" 34 + class="text-gray-500 mt-3 tabular-nums" 35 35 > 36 36 Indexed <span x-text="fetched">0</span> of {{ totalPosts }} posts 37 37 </p> ··· 40 40 x-show="state === 'failed'" 41 41 x-cloak 42 42 role="alert" 43 - style="max-width: 420px; margin: 0 auto; color: #a33;" 43 + class="max-w-[420px] mx-auto text-red-700" 44 44 > 45 - <h1 style="font-size: 1.4rem; margin-bottom: 12px;">Backfill failed</h1> 45 + <h1 class="text-xl mb-3">Backfill failed</h1> 46 46 <p> 47 47 <span x-text="error">Unknown error</span>. Try refreshing the page. 48 48 </p>
+50 -102
resources/views/pages/profile/show.edge
··· 4 4 @endslot 5 5 6 6 @slot('main') 7 - <div style="padding: 32px 0 16px;"> 7 + <div class="pt-8 pb-4"> 8 8 {{-- Profile header --}} 9 - <div style="display: flex; align-items: center; gap: 16px; margin-bottom: 24px;"> 10 - <div style=" 11 - width: 56px; height: 56px; 12 - border-radius: 50%; 13 - background: #ddd; 14 - flex-shrink: 0; 15 - display: flex; align-items: center; justify-content: center; 16 - font-size: 20px; color: #aaa; 17 - ">@</div> 9 + <div class="flex items-center gap-4 mb-6"> 10 + <div class="size-14 rounded-full bg-gray-300 shrink-0 flex items-center justify-center text-xl text-gray-400">@</div> 18 11 <div> 19 12 @if(user.displayName) 20 - <div style="font-size: 1.1rem; font-weight: 600;">{{ user.displayName }}</div> 13 + <div class="text-lg font-semibold">{{ user.displayName }}</div> 21 14 @endif 22 - <div style="color: #555;">{{ '@' + handle }}</div> 15 + <div class="text-gray-600">{{ '@' + handle }}</div> 23 16 </div> 24 17 </div> 25 18 26 19 {{-- Controls --}} 27 - <div style="display: flex; align-items: center; gap: 24px; margin-bottom: 24px; flex-wrap: wrap;"> 20 + <div class="flex items-center justify-between mb-6 flex-wrap gap-6"> 28 21 {{-- Kind toggle --}} 29 - <div style="display: flex; gap: 4px;"> 22 + <div class="flex gap-1"> 30 23 <a 31 24 href="/profile/{{ handle }}/likes{{ daysWindow ? '?days=' + daysWindow : '' }}" 32 - style=" 33 - padding: 6px 14px; 34 - border-radius: 20px; 35 - font-size: 0.9rem; 36 - background: {{ kind === 'likes' ? '#0066cc' : '#eee' }}; 37 - color: {{ kind === 'likes' ? '#fff' : '#333' }}; 38 - " 25 + class="px-3.5 py-1.5 rounded-full text-sm {{ kind === 'likes' ? 'bg-blue-600 text-white' : 'bg-gray-200 text-gray-700' }}" 39 26 >Most liked</a> 40 27 <a 41 28 href="/profile/{{ handle }}/reposts{{ daysWindow ? '?days=' + daysWindow : '' }}" 42 - style=" 43 - padding: 6px 14px; 44 - border-radius: 20px; 45 - font-size: 0.9rem; 46 - background: {{ kind === 'reposts' ? '#0066cc' : '#eee' }}; 47 - color: {{ kind === 'reposts' ? '#fff' : '#333' }}; 48 - " 29 + class="px-3.5 py-1.5 rounded-full text-sm {{ kind === 'reposts' ? 'bg-blue-600 text-white' : 'bg-gray-200 text-gray-700' }}" 49 30 >Most reposted</a> 50 31 </div> 51 32 52 33 {{-- Lens dropdown (simple links) --}} 53 - <div style="display: flex; gap: 4px;"> 34 + <div class="flex gap-1"> 54 35 <a 55 36 href="/profile/{{ handle }}/{{ kind }}" 56 - style=" 57 - padding: 6px 14px; 58 - border-radius: 20px; 59 - font-size: 0.9rem; 60 - background: {{ !daysWindow ? '#0066cc' : '#eee' }}; 61 - color: {{ !daysWindow ? '#fff' : '#333' }}; 62 - " 37 + class="px-3.5 py-1.5 rounded-full text-sm {{ !daysWindow ? 'bg-blue-600 text-white' : 'bg-gray-200 text-gray-700' }}" 63 38 >All time</a> 64 39 <a 65 40 href="/profile/{{ handle }}/{{ kind }}?days=30" 66 - style=" 67 - padding: 6px 14px; 68 - border-radius: 20px; 69 - font-size: 0.9rem; 70 - background: {{ daysWindow === 30 ? '#0066cc' : '#eee' }}; 71 - color: {{ daysWindow === 30 ? '#fff' : '#333' }}; 72 - " 41 + class="px-3.5 py-1.5 rounded-full text-sm {{ daysWindow === 30 ? 'bg-blue-600 text-white' : 'bg-gray-200 text-gray-700' }}" 73 42 >Last month</a> 74 43 </div> 75 44 </div> 76 45 77 46 {{-- Posts --}} 78 47 @if(posts.length === 0) 79 - <p style="color: #888;">{{ '@' + handle }} hasn't posted anything yet (or nothing in this window).</p> 48 + <p class="text-gray-400">{{ '@' + handle }} hasn't posted anything yet (or nothing in this window).</p> 80 49 @else 81 - <ol style="list-style: none; padding: 0; margin: 0;"> 50 + <ol class="list-none p-0 m-0"> 82 51 @each((post, index) in posts) 83 - <li style=" 84 - background: #fff; 85 - border: 1px solid #e5e5e5; 86 - border-radius: 8px; 87 - padding: 16px; 88 - margin-bottom: 12px; 89 - "> 90 - <div style="display: flex; justify-content: space-between; align-items: flex-start; gap: 12px;"> 91 - <div style="flex: 1;"> 92 - <p style="margin: 0 0 12px; white-space: pre-wrap; word-break: break-word;">{{{ post.postTextSafe }}}</p> 52 + <li class="bg-white border border-neutral-200 rounded-lg p-4 mb-3"> 53 + <div class="flex justify-between items-start gap-3"> 54 + <div class="flex-1 min-w-0"> 55 + <p class="mb-3 whitespace-pre-wrap break-words">{{{ post.postTextSafe }}}</p> 93 56 94 57 {{-- Embed block --}} 95 58 @if(post.embed) 96 59 @if(post.embed.type === 'images') 97 60 @if(post.embed.items.length === 1) 98 - <div style="margin-bottom: 12px;"> 99 - <a href="{{ post.embed.items[0].fullsize }}" target="_blank" rel="noopener" style="display: block;"> 61 + <div class="mb-3"> 62 + <a href="{{ post.embed.items[0].fullsize }}" target="_blank" rel="noopener" class="block"> 100 63 <img 101 64 src="{{ post.embed.items[0].thumb }}" 102 65 alt="{{ post.embed.items[0].alt }}" 103 66 loading="lazy" 104 - style="max-width: 100%; max-height: 400px; border-radius: 8px; object-fit: cover;{{ post.embed.items[0].aspectRatio ? ' aspect-ratio: ' + post.embed.items[0].aspectRatio.width + ' / ' + post.embed.items[0].aspectRatio.height + ';' : '' }}" 67 + class="max-w-full max-h-[400px] rounded-lg object-cover" 68 + style="{{ post.embed.items[0].aspectRatio ? 'aspect-ratio: ' + post.embed.items[0].aspectRatio.width + ' / ' + post.embed.items[0].aspectRatio.height : '' }}" 105 69 > 106 70 </a> 107 71 </div> 108 72 @elseif(post.embed.items.length === 2) 109 - <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 4px; margin-bottom: 12px;"> 73 + <div class="grid grid-cols-2 gap-1 mb-3"> 110 74 @each(img in post.embed.items) 111 - <a href="{{ img.fullsize }}" target="_blank" rel="noopener" style="display: block;"> 75 + <a href="{{ img.fullsize }}" target="_blank" rel="noopener" class="block"> 112 76 <img 113 77 src="{{ img.thumb }}" 114 78 alt="{{ img.alt }}" 115 79 loading="lazy" 116 - style="width: 100%; height: 200px; border-radius: 6px; object-fit: cover;" 80 + class="w-full h-[200px] rounded-md object-cover" 117 81 > 118 82 </a> 119 83 @endeach 120 84 </div> 121 85 @elseif(post.embed.items.length === 3) 122 - <div style="display: grid; grid-template-columns: 1fr 1fr; grid-template-rows: 1fr 1fr; gap: 4px; margin-bottom: 12px;"> 123 - <a href="{{ post.embed.items[0].fullsize }}" target="_blank" rel="noopener" style="display: block; grid-row: 1 / 3;"> 86 + <div class="grid grid-cols-2 grid-rows-2 gap-1 mb-3"> 87 + <a href="{{ post.embed.items[0].fullsize }}" target="_blank" rel="noopener" class="block row-span-2"> 124 88 <img 125 89 src="{{ post.embed.items[0].thumb }}" 126 90 alt="{{ post.embed.items[0].alt }}" 127 91 loading="lazy" 128 - style="width: 100%; height: 100%; border-radius: 6px; object-fit: cover;" 92 + class="w-full h-full rounded-md object-cover" 129 93 > 130 94 </a> 131 - <a href="{{ post.embed.items[1].fullsize }}" target="_blank" rel="noopener" style="display: block;"> 95 + <a href="{{ post.embed.items[1].fullsize }}" target="_blank" rel="noopener" class="block"> 132 96 <img 133 97 src="{{ post.embed.items[1].thumb }}" 134 98 alt="{{ post.embed.items[1].alt }}" 135 99 loading="lazy" 136 - style="width: 100%; height: 100%; border-radius: 6px; object-fit: cover;" 100 + class="w-full h-full rounded-md object-cover" 137 101 > 138 102 </a> 139 - <a href="{{ post.embed.items[2].fullsize }}" target="_blank" rel="noopener" style="display: block;"> 103 + <a href="{{ post.embed.items[2].fullsize }}" target="_blank" rel="noopener" class="block"> 140 104 <img 141 105 src="{{ post.embed.items[2].thumb }}" 142 106 alt="{{ post.embed.items[2].alt }}" 143 107 loading="lazy" 144 - style="width: 100%; height: 100%; border-radius: 6px; object-fit: cover;" 108 + class="w-full h-full rounded-md object-cover" 145 109 > 146 110 </a> 147 111 </div> 148 112 @elseif(post.embed.items.length >= 4) 149 - <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 4px; margin-bottom: 12px;"> 113 + <div class="grid grid-cols-2 gap-1 mb-3"> 150 114 @each(img in post.embed.items.slice(0, 4)) 151 - <a href="{{ img.fullsize }}" target="_blank" rel="noopener" style="display: block;"> 115 + <a href="{{ img.fullsize }}" target="_blank" rel="noopener" class="block"> 152 116 <img 153 117 src="{{ img.thumb }}" 154 118 alt="{{ img.alt }}" 155 119 loading="lazy" 156 - style="width: 100%; height: 160px; border-radius: 6px; object-fit: cover;" 120 + class="w-full h-40 rounded-md object-cover" 157 121 > 158 122 </a> 159 123 @endeach 160 124 </div> 161 125 @endif 162 126 @elseif(post.embed.type === 'video') 163 - <div style="margin-bottom: 12px;"> 164 - <a href="{{ post.bskyUrl }}" target="_blank" rel="noopener" style="display: block; position: relative; max-width: 100%;"> 127 + <div class="mb-3"> 128 + <a href="{{ post.bskyUrl }}" target="_blank" rel="noopener" class="block relative max-w-full"> 165 129 <img 166 130 src="{{ post.embed.thumbnail }}" 167 131 alt="{{ post.embed.alt }}" 168 132 loading="lazy" 169 - style="max-width: 100%; max-height: 400px; border-radius: 8px; object-fit: cover;{{ post.embed.aspectRatio ? ' aspect-ratio: ' + post.embed.aspectRatio.width + ' / ' + post.embed.aspectRatio.height + ';' : '' }}" 133 + class="max-w-full max-h-[400px] rounded-lg object-cover" 134 + style="{{ post.embed.aspectRatio ? 'aspect-ratio: ' + post.embed.aspectRatio.width + ' / ' + post.embed.aspectRatio.height : '' }}" 170 135 > 171 - <span style=" 172 - position: absolute; 173 - top: 50%; left: 50%; 174 - transform: translate(-50%, -50%); 175 - background: rgba(0, 0, 0, 0.6); 176 - color: #fff; 177 - width: 48px; height: 48px; 178 - border-radius: 50%; 179 - display: flex; align-items: center; justify-content: center; 180 - font-size: 20px; 181 - ">&#9654;</span> 136 + <span class="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 bg-black/60 text-white size-12 rounded-full flex items-center justify-center text-xl">&#9654;</span> 182 137 </a> 183 138 </div> 184 139 @elseif(post.embed.type === 'external') 185 - <div style="margin-bottom: 12px;"> 186 - <a href="{{ post.embed.uri }}" target="_blank" rel="noopener" style=" 187 - display: flex; 188 - border: 1px solid #e5e5e5; 189 - border-radius: 8px; 190 - overflow: hidden; 191 - text-decoration: none; 192 - color: inherit; 193 - "> 140 + <div class="mb-3"> 141 + <a href="{{ post.embed.uri }}" target="_blank" rel="noopener" class="flex border border-neutral-200 rounded-lg overflow-hidden no-underline text-inherit"> 194 142 @if(post.embed.thumb) 195 - <div style="flex-shrink: 0; width: 120px; min-height: 80px;"> 143 + <div class="shrink-0 w-[120px] min-h-[80px]"> 196 144 <img 197 145 src="{{ post.embed.thumb }}" 198 146 alt="" 199 147 loading="lazy" 200 - style="width: 100%; height: 100%; object-fit: cover;" 148 + class="w-full h-full object-cover" 201 149 > 202 150 </div> 203 151 @endif 204 - <div style="padding: 10px 12px; min-width: 0; flex: 1;"> 205 - <div style="font-weight: 600; font-size: 0.9rem; margin-bottom: 4px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;">{{ post.embed.title }}</div> 206 - <div style="font-size: 0.8rem; color: #888; overflow: hidden; text-overflow: ellipsis; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;">{{ post.embed.description }}</div> 152 + <div class="py-2.5 px-3 min-w-0 flex-1"> 153 + <div class="font-semibold text-sm mb-1 overflow-hidden text-ellipsis whitespace-nowrap">{{ post.embed.title }}</div> 154 + <div class="text-xs text-gray-400 line-clamp-2">{{ post.embed.description }}</div> 207 155 </div> 208 156 </a> 209 157 </div> 210 158 @endif 211 159 @endif 212 160 213 - <div style="font-size: 0.85rem; color: #888; display: flex; gap: 16px; flex-wrap: wrap;"> 161 + <div class="text-sm text-gray-400 flex gap-4 flex-wrap"> 214 162 <span>♥ {{ post.likes }} likes</span> 215 163 <span>♻ {{ post.reposts }} reposts</span> 216 - <a href="{{ post.bskyUrl }}" target="_blank" rel="noopener" style="color: #0066cc;">view on Bluesky ↗</a> 164 + <a href="{{ post.bskyUrl }}" target="_blank" rel="noopener" class="text-blue-600 hover:underline">view on Bluesky ↗</a> 217 165 </div> 218 166 </div> 219 - <div style="font-size: 1.2rem; font-weight: 700; color: #ccc; flex-shrink: 0;">{{ index + 1 }}</div> 167 + <div class="text-xl font-bold text-gray-300 shrink-0">{{ index + 1 }}</div> 220 168 </div> 221 169 </li> 222 170 @endeach
+1 -1
resources/views/partials/flash_alerts.edge
··· 1 - <div class="flash-container"> 1 + <div class="fixed top-20 left-0 right-0 flex flex-col items-center"> 2 2 @if(flashMessages.has('error')) 3 3 @alert.root({ variant: 'destructive', autoDismiss: true }) 4 4 @!alert.description({ text: flashMessages.get('error') })
+2 -2
resources/views/partials/header.edge
··· 1 - <header> 2 - <div> 1 + <header class="max-w-[1440px] mx-auto px-[30px]"> 2 + <div class="flex justify-between items-center h-16"> 3 3 <div> 4 4 @link({ route: 'home', text: 'Home' }) 5 5 <svg width="auto" height="18" viewBox="0 0 413 38" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M382.5 37.5v-30h7.5V0h15v7.5h7.5v30H405v-15h-15v15h-7.5ZM390 15h15V7.8h-15V15ZM360 37.5V0h7.5v37.5H360ZM315 37.5V0h22.5v7.5h7.5V30h-7.5v7.5H315Zm7.5-7.5h14.7V7.5h-14.7V30ZM277.5 37.5V0H300v7.5h-15V15h15v7.5h-15V30h15v7.5h-22.5ZM225 37.5V0h7.5v7.5h7.5V15h7.5v7.5H240V15h-7.5v22.5H225Zm30 0V15h-7.5V7.5h7.5V0h7.5v37.5H255ZM180 37.5V0h22.5v7.5h7.5V15h-7.5v15h7.5v7.5h-7.5V30H195v-7.5h-7.5v15H180Zm7.5-22.5h14.7V7.5h-14.7V15ZM142.5 37.5V0H165v7.5h-15V15h15v7.5h-15V30h15v7.5h-22.5ZM97.5 37.5V0H120v7.5h7.5V15H120v7.5h-15v15h-7.5ZM105 15h14.7V7.5H105V15ZM60 37.5V15h-7.5V7.5H45V0h7.5v7.5H60V15h7.5v22.5H60Zm15-30V0h7.5v7.5H75ZM67.5 15V7.5H75V15h-7.5ZM0 37.5V0h7.5v15h15V0H30v37.5h-7.5v-15h-15v15H0Z" fill="currentColor"/></svg>
+2
vite.config.ts
··· 1 1 import { defineConfig } from 'vite' 2 2 import adonisjs from '@adonisjs/vite/client' 3 + import tailwindcss from '@tailwindcss/vite' 3 4 4 5 export default defineConfig({ 5 6 plugins: [ 7 + tailwindcss(), 6 8 adonisjs({ 7 9 /** 8 10 * Entrypoints of your application. Each entrypoint will