diff --git a/index.html b/index.html index cbc1f5a..8b677ad 100644 --- a/index.html +++ b/index.html @@ -2,10 +2,10 @@ - + - Vite + Preact + Alejandro Laguna
diff --git a/package-lock.json b/package-lock.json index 1893625..df1d1ce 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5,8 +5,10 @@ "packages": { "": { "dependencies": { + "@tailwindcss/vite": "^4.1.3", "preact": "^10.25.3", - "preact-iso": "^2.9.1" + "preact-iso": "^2.9.1", + "tailwindcss": "^4.1.3" }, "devDependencies": { "@preact/preset-vite": "^2.9.3", @@ -341,7 +343,6 @@ "cpu": [ "ppc64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -358,7 +359,6 @@ "cpu": [ "arm" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -375,7 +375,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -392,7 +391,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -409,7 +407,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -426,7 +423,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -443,7 +439,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -460,7 +455,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -477,7 +471,6 @@ "cpu": [ "arm" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -494,7 +487,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -511,7 +503,6 @@ "cpu": [ "ia32" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -528,7 +519,6 @@ "cpu": [ "loong64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -545,7 +535,6 @@ "cpu": [ "mips64el" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -562,7 +551,6 @@ "cpu": [ "ppc64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -579,7 +567,6 @@ "cpu": [ "riscv64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -596,7 +583,6 @@ "cpu": [ "s390x" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -613,7 +599,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -630,7 +615,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -647,7 +631,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -664,7 +647,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -681,7 +663,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -698,7 +679,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -715,7 +695,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -732,7 +711,6 @@ "cpu": [ "ia32" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -749,7 +727,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -934,7 +911,6 @@ "cpu": [ "arm" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -948,7 +924,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -962,7 +937,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -976,7 +950,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -990,7 +963,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1004,7 +976,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1018,7 +989,6 @@ "cpu": [ "arm" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1032,7 +1002,6 @@ "cpu": [ "arm" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1046,7 +1015,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1060,7 +1028,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1074,7 +1041,6 @@ "cpu": [ "loong64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1088,7 +1054,6 @@ "cpu": [ "ppc64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1102,7 +1067,6 @@ "cpu": [ "riscv64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1116,7 +1080,6 @@ "cpu": [ "riscv64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1130,7 +1093,6 @@ "cpu": [ "s390x" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1144,7 +1106,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1158,7 +1119,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1172,7 +1132,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1186,7 +1145,6 @@ "cpu": [ "ia32" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1200,18 +1158,240 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ "win32" ] }, + "node_modules/@tailwindcss/node": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.1.3.tgz", + "integrity": "sha512-H/6r6IPFJkCfBJZ2dKZiPJ7Ueb2wbL592+9bQEl2r73qbX6yGnmQVIfiUvDRB2YI0a3PWDrzUwkvQx1XW1bNkA==", + "license": "MIT", + "dependencies": { + "enhanced-resolve": "^5.18.1", + "jiti": "^2.4.2", + "lightningcss": "1.29.2", + "tailwindcss": "4.1.3" + } + }, + "node_modules/@tailwindcss/oxide": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.1.3.tgz", + "integrity": "sha512-t16lpHCU7LBxDe/8dCj9ntyNpXaSTAgxWm1u2XQP5NiIu4KGSyrDJJRlK9hJ4U9yJxx0UKCVI67MJWFNll5mOQ==", + "license": "MIT", + "engines": { + "node": ">= 10" + }, + "optionalDependencies": { + "@tailwindcss/oxide-android-arm64": "4.1.3", + "@tailwindcss/oxide-darwin-arm64": "4.1.3", + "@tailwindcss/oxide-darwin-x64": "4.1.3", + "@tailwindcss/oxide-freebsd-x64": "4.1.3", + "@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.3", + "@tailwindcss/oxide-linux-arm64-gnu": "4.1.3", + "@tailwindcss/oxide-linux-arm64-musl": "4.1.3", + "@tailwindcss/oxide-linux-x64-gnu": "4.1.3", + "@tailwindcss/oxide-linux-x64-musl": "4.1.3", + "@tailwindcss/oxide-win32-arm64-msvc": "4.1.3", + "@tailwindcss/oxide-win32-x64-msvc": "4.1.3" + } + }, + "node_modules/@tailwindcss/oxide-android-arm64": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.1.3.tgz", + "integrity": "sha512-cxklKjtNLwFl3mDYw4XpEfBY+G8ssSg9ADL4Wm6//5woi3XGqlxFsnV5Zb6v07dxw1NvEX2uoqsxO/zWQsgR+g==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-darwin-arm64": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.1.3.tgz", + "integrity": "sha512-mqkf2tLR5VCrjBvuRDwzKNShRu99gCAVMkVsaEOFvv6cCjlEKXRecPu9DEnxp6STk5z+Vlbh1M5zY3nQCXMXhw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-darwin-x64": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.1.3.tgz", + "integrity": "sha512-7sGraGaWzXvCLyxrc7d+CCpUN3fYnkkcso3rCzwUmo/LteAl2ZGCDlGvDD8Y/1D3ngxT8KgDj1DSwOnNewKhmg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-freebsd-x64": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.1.3.tgz", + "integrity": "sha512-E2+PbcbzIReaAYZe997wb9rId246yDkCwAakllAWSGqe6VTg9hHle67hfH6ExjpV2LSK/siRzBUs5wVff3RW9w==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.1.3.tgz", + "integrity": "sha512-GvfbJ8wjSSjbLFFE3UYz4Eh8i4L6GiEYqCtA8j2Zd2oXriPuom/Ah/64pg/szWycQpzRnbDiJozoxFU2oJZyfg==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm64-gnu": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.1.3.tgz", + "integrity": "sha512-35UkuCWQTeG9BHcBQXndDOrpsnt3Pj9NVIB4CgNiKmpG8GnCNXeMczkUpOoqcOhO6Cc/mM2W7kaQ/MTEENDDXg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm64-musl": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.1.3.tgz", + "integrity": "sha512-dm18aQiML5QCj9DQo7wMbt1Z2tl3Giht54uVR87a84X8qRtuXxUqnKQkRDK5B4bCOmcZ580lF9YcoMkbDYTXHQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-linux-x64-gnu": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.1.3.tgz", + "integrity": "sha512-LMdTmGe/NPtGOaOfV2HuO7w07jI3cflPrVq5CXl+2O93DCewADK0uW1ORNAcfu2YxDUS035eY2W38TxrsqngxA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-linux-x64-musl": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.1.3.tgz", + "integrity": "sha512-aalNWwIi54bbFEizwl1/XpmdDrOaCjRFQRgtbv9slWjmNPuJJTIKPHf5/XXDARc9CneW9FkSTqTbyvNecYAEGw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-win32-arm64-msvc": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.1.3.tgz", + "integrity": "sha512-PEj7XR4OGTGoboTIAdXicKuWl4EQIjKHKuR+bFy9oYN7CFZo0eu74+70O4XuERX4yjqVZGAkCdglBODlgqcCXg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-win32-x64-msvc": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.1.3.tgz", + "integrity": "sha512-T8gfxECWDBENotpw3HR9SmNiHC9AOJdxs+woasRZ8Q/J4VHN0OMs7F+4yVNZ9EVN26Wv6mZbK0jv7eHYuLJLwA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/vite": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/vite/-/vite-4.1.3.tgz", + "integrity": "sha512-lUI/QaDxLtlV52Lho6pu07CG9pSnRYLOPmKGIQjyHdTBagemc6HmgZxyjGAQ/5HMPrNeWBfTVIpQl0/jLXvWHQ==", + "license": "MIT", + "dependencies": { + "@tailwindcss/node": "4.1.3", + "@tailwindcss/oxide": "4.1.3", + "tailwindcss": "4.1.3" + }, + "peerDependencies": { + "vite": "^5.2.0 || ^6" + } + }, "node_modules/@types/estree": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.7.tgz", "integrity": "sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==", - "dev": true, "license": "MIT" }, "node_modules/array-union": { @@ -1387,6 +1567,15 @@ } } }, + "node_modules/detect-libc": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz", + "integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==", + "license": "Apache-2.0", + "engines": { + "node": ">=8" + } + }, "node_modules/dir-glob": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", @@ -1473,6 +1662,19 @@ "dev": true, "license": "MIT" }, + "node_modules/enhanced-resolve": { + "version": "5.18.1", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.1.tgz", + "integrity": "sha512-ZSW3ma5GkcQBIpwZTSRAI8N71Uuwgs93IezB7mf7R60tC8ZbJideoDNKjHn2O9KIlx6rkGTTEk1xUCK2E1Y2Yg==", + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + }, + "engines": { + "node": ">=10.13.0" + } + }, "node_modules/entities": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", @@ -1490,7 +1692,6 @@ "version": "0.25.2", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.2.tgz", "integrity": "sha512-16854zccKPnC+toMywC+uKNeYSv+/eXkevRAfwRD/G9Cleq66m8XFIrigkbvauLLlCfDL45Q2cWegSg53gGBnQ==", - "dev": true, "hasInstallScript": true, "license": "MIT", "bin": { @@ -1673,7 +1874,6 @@ "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, "hasInstallScript": true, "license": "MIT", "optional": true, @@ -1765,7 +1965,6 @@ "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true, "license": "ISC" }, "node_modules/he": { @@ -1821,6 +2020,15 @@ "node": ">=0.12.0" } }, + "node_modules/jiti": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.4.2.tgz", + "integrity": "sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A==", + "license": "MIT", + "bin": { + "jiti": "lib/jiti-cli.mjs" + } + }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -1874,6 +2082,234 @@ "dev": true, "license": "MIT" }, + "node_modules/lightningcss": { + "version": "1.29.2", + "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.29.2.tgz", + "integrity": "sha512-6b6gd/RUXKaw5keVdSEtqFVdzWnU5jMxTUjA2bVcMNPLwSQ08Sv/UodBVtETLCn7k4S1Ibxwh7k68IwLZPgKaA==", + "license": "MPL-2.0", + "dependencies": { + "detect-libc": "^2.0.3" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "optionalDependencies": { + "lightningcss-darwin-arm64": "1.29.2", + "lightningcss-darwin-x64": "1.29.2", + "lightningcss-freebsd-x64": "1.29.2", + "lightningcss-linux-arm-gnueabihf": "1.29.2", + "lightningcss-linux-arm64-gnu": "1.29.2", + "lightningcss-linux-arm64-musl": "1.29.2", + "lightningcss-linux-x64-gnu": "1.29.2", + "lightningcss-linux-x64-musl": "1.29.2", + "lightningcss-win32-arm64-msvc": "1.29.2", + "lightningcss-win32-x64-msvc": "1.29.2" + } + }, + "node_modules/lightningcss-darwin-arm64": { + "version": "1.29.2", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.29.2.tgz", + "integrity": "sha512-cK/eMabSViKn/PG8U/a7aCorpeKLMlK0bQeNHmdb7qUnBkNPnL+oV5DjJUo0kqWsJUapZsM4jCfYItbqBDvlcA==", + "cpu": [ + "arm64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-darwin-x64": { + "version": "1.29.2", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.29.2.tgz", + "integrity": "sha512-j5qYxamyQw4kDXX5hnnCKMf3mLlHvG44f24Qyi2965/Ycz829MYqjrVg2H8BidybHBp9kom4D7DR5VqCKDXS0w==", + "cpu": [ + "x64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-freebsd-x64": { + "version": "1.29.2", + "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.29.2.tgz", + "integrity": "sha512-wDk7M2tM78Ii8ek9YjnY8MjV5f5JN2qNVO+/0BAGZRvXKtQrBC4/cn4ssQIpKIPP44YXw6gFdpUF+Ps+RGsCwg==", + "cpu": [ + "x64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm-gnueabihf": { + "version": "1.29.2", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.29.2.tgz", + "integrity": "sha512-IRUrOrAF2Z+KExdExe3Rz7NSTuuJ2HvCGlMKoquK5pjvo2JY4Rybr+NrKnq0U0hZnx5AnGsuFHjGnNT14w26sg==", + "cpu": [ + "arm" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-gnu": { + "version": "1.29.2", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.29.2.tgz", + "integrity": "sha512-KKCpOlmhdjvUTX/mBuaKemp0oeDIBBLFiU5Fnqxh1/DZ4JPZi4evEH7TKoSBFOSOV3J7iEmmBaw/8dpiUvRKlQ==", + "cpu": [ + "arm64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-musl": { + "version": "1.29.2", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.29.2.tgz", + "integrity": "sha512-Q64eM1bPlOOUgxFmoPUefqzY1yV3ctFPE6d/Vt7WzLW4rKTv7MyYNky+FWxRpLkNASTnKQUaiMJ87zNODIrrKQ==", + "cpu": [ + "arm64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-gnu": { + "version": "1.29.2", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.29.2.tgz", + "integrity": "sha512-0v6idDCPG6epLXtBH/RPkHvYx74CVziHo6TMYga8O2EiQApnUPZsbR9nFNrg2cgBzk1AYqEd95TlrsL7nYABQg==", + "cpu": [ + "x64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-musl": { + "version": "1.29.2", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.29.2.tgz", + "integrity": "sha512-rMpz2yawkgGT8RULc5S4WiZopVMOFWjiItBT7aSfDX4NQav6M44rhn5hjtkKzB+wMTRlLLqxkeYEtQ3dd9696w==", + "cpu": [ + "x64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-win32-arm64-msvc": { + "version": "1.29.2", + "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.29.2.tgz", + "integrity": "sha512-nL7zRW6evGQqYVu/bKGK+zShyz8OVzsCotFgc7judbt6wnB2KbiKKJwBE4SGoDBQ1O94RjW4asrCjQL4i8Fhbw==", + "cpu": [ + "arm64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-win32-x64-msvc": { + "version": "1.29.2", + "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.29.2.tgz", + "integrity": "sha512-EdIUW3B2vLuHmv7urfzMI/h2fmlnOQBk1xlsDxkN1tCWKjNFjfLhGxYk8C8mzpSfr+A6jFFIi8fU6LbQGsRWjA==", + "cpu": [ + "x64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, "node_modules/locate-path": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", @@ -1958,7 +2394,6 @@ "version": "3.3.11", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", - "dev": true, "funding": [ { "type": "github", @@ -2067,7 +2502,6 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "dev": true, "license": "ISC" }, "node_modules/picomatch": { @@ -2100,7 +2534,6 @@ "version": "8.5.3", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.3.tgz", "integrity": "sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==", - "dev": true, "funding": [ { "type": "opencollective", @@ -2191,7 +2624,6 @@ "version": "4.38.0", "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.38.0.tgz", "integrity": "sha512-5SsIRtJy9bf1ErAOiFMFzl64Ex9X5V7bnJ+WlFMb+zmP459OSWCEG7b0ERZ+PEU7xPt4OG3RHbrp1LJlXxYTrw==", - "dev": true, "license": "MIT", "dependencies": { "@types/estree": "1.0.7" @@ -2295,7 +2727,6 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", - "dev": true, "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" @@ -2324,6 +2755,21 @@ "node": ">=0.10.0" } }, + "node_modules/tailwindcss": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.3.tgz", + "integrity": "sha512-2Q+rw9vy1WFXu5cIxlvsabCwhU2qUwodGq03ODhLJ0jW4ek5BUtoCsnLB0qG+m8AHgEsSJcJGDSDe06FXlP74g==", + "license": "MIT" + }, + "node_modules/tapable": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -2409,7 +2855,6 @@ "version": "6.2.4", "resolved": "https://registry.npmjs.org/vite/-/vite-6.2.4.tgz", "integrity": "sha512-veHMSew8CcRzhL5o8ONjy8gkfmFJAd5Ac16oxBUjlwgX3Gq2Wqr+qNC3TjPIpy7TPV/KporLga5GT9HqdrCizw==", - "dev": true, "license": "MIT", "dependencies": { "esbuild": "^0.25.0", diff --git a/package.json b/package.json index 6cb61b2..550858a 100644 --- a/package.json +++ b/package.json @@ -10,8 +10,10 @@ "deploy": "gh-pages -d dist" }, "dependencies": { + "@tailwindcss/vite": "^4.1.3", "preact": "^10.25.3", - "preact-iso": "^2.9.1" + "preact-iso": "^2.9.1", + "tailwindcss": "^4.1.3" }, "devDependencies": { "@preact/preset-vite": "^2.9.3", diff --git a/public/favicon-32x32.png b/public/favicon-32x32.png new file mode 100644 index 0000000..19ee6be Binary files /dev/null and b/public/favicon-32x32.png differ diff --git a/public/resume_eng.pdf b/public/resume_eng.pdf new file mode 100644 index 0000000..493363d Binary files /dev/null and b/public/resume_eng.pdf differ diff --git a/public/vite.svg b/public/vite.svg index ffcb6bc..86b21fe 100644 Binary files a/public/vite.svg and b/public/vite.svg differ diff --git a/src/assets/sketch.png b/src/assets/sketch.png new file mode 100644 index 0000000..6e25f38 Binary files /dev/null and b/src/assets/sketch.png differ diff --git a/src/components/About.tsx b/src/components/About.tsx new file mode 100644 index 0000000..7ef4a11 --- /dev/null +++ b/src/components/About.tsx @@ -0,0 +1,48 @@ +import { useEffect, useState } from 'react'; +import image from '../assets/sketch.png'; + +const taglines = [ + "Amateur Writer", + "Bookworm", + "Star Gazer", + "Physics Enthusiast", + "Lifelong Learner", + "Tea Enthusiast", + "Cosmic Explorer", + "Knowledge Seeker", +]; + +export default function About({ theme }) { + const [tagline, setTagline] = useState(''); + + useEffect(() => { + const randomTagline = taglines[Math.floor(Math.random() * taglines.length)]; + setTagline(randomTagline); + }, []); + + return ( +
+
+
+

Alejandro Laguna

+

Software Engineer & {tagline}

+

+ Crafting digital projects that inspire me, while exploring everything from books and tea to space and science. First-year computer science student. +

+ +
+
+ Alex Clark's Sketch +
+
+
+ ); +} + diff --git a/src/components/Education.tsx b/src/components/Education.tsx new file mode 100644 index 0000000..26d3e41 --- /dev/null +++ b/src/components/Education.tsx @@ -0,0 +1,36 @@ +import EducationCard from './EducationCard'; + +const education = [ + { + institution: "European Institute of Technology (EPITECH)", + degree: "Degree + Master in Computer Science", + duration: "2024 - 2029", + highlights: [ + "ONGOING", + "Multiple courses passed with Honors", + "Completed over 30 projects from different fields" + ] + }, + { + institution: "INS Cendrassos", + degree: "Microcomputer systems & networks", + duration: "2022 - 2024", + highlights: [ + "First of the class", + "ERASMUS+ Scholarship", + ] + } +]; + +export default function Education({ theme }) { + return ( +
+

Education

+
+ {education.map((edu, i) => ( + + ))} +
+
+ ); +} diff --git a/src/components/EducationCard.tsx b/src/components/EducationCard.tsx new file mode 100644 index 0000000..bed70e7 --- /dev/null +++ b/src/components/EducationCard.tsx @@ -0,0 +1,18 @@ +export default function EducationCard({ education, theme }) { + return ( +
+
+
+

{education.degree}

+

{education.institution}

+
+ {education.duration} +
+ +
+ ); +} diff --git a/src/components/Experience.tsx b/src/components/Experience.tsx new file mode 100644 index 0000000..ba87d47 --- /dev/null +++ b/src/components/Experience.tsx @@ -0,0 +1,39 @@ +import ExperienceCard from './ExperienceCard'; + +const experience = [ + { + company: "Avantiam Inc - Figueres, Spain", + role: "Full-Stack Developer", + duration: "Sep 2023 - Sep 2024", + technologies: ["Laravel", "Livewire", "AlpineJS", "TailwindCSS", "MariaDB/MySQL"], + highlights: [ + "Developed and maintained a comprehensive business management service used by over 100 companies", + "Managed all aspects of the project lifecycle, including server administration, performance tuning, and user experience improvements.", + "Recommendation letter available upon request." + ] + }, + { + company: "Niblu Group - Maribor, Slovenia", + role: "Backend Developer Intern", + duration: "Summer 2023", + technologies: ["NextJS", "TailwindCSS", "TypeScript", "FastAPI", "AWS S3 Bucket"], + highlights: [ + "Developed a secure authentication system and features for managing courses across different user roles.", + "Integrated AWS S3 for seamless storage and retrieval of course materials.", + "Gained valuable personal and professional growth through the ERASMUS experience, adapting to new challenges abroad alone." + ] + } +]; +export default function Experience({ theme }) { + return ( +
+

Work Experience

+
+ {experience.map((exp, i) => ( + + ))} +
+
+ ); +} + diff --git a/src/components/ExperienceCard.tsx b/src/components/ExperienceCard.tsx new file mode 100644 index 0000000..86056fb --- /dev/null +++ b/src/components/ExperienceCard.tsx @@ -0,0 +1,36 @@ +export default function ExperienceCard({ experience, theme }) { + return ( +
+
+
+

{experience.company}

+

{experience.role}

+
+ {experience.duration} +
+ + {experience.technologies && ( +
+

Technologies Used:

+ {experience.technologies.map((tech, i) => ( + {tech} + ))} +
+ )} + {experience.link && ( + + View More + + + )} +
+ ); +} + diff --git a/src/components/Footer.tsx b/src/components/Footer.tsx new file mode 100644 index 0000000..f1b8f41 --- /dev/null +++ b/src/components/Footer.tsx @@ -0,0 +1,26 @@ +export default function Footer({ theme }) { + const handleDownload = () => { + const link = document.createElement('a'); + link.href = '/public/resume_eng.pdf'; + link.download = 'alejandrolaguna_resume_eng.pdf'; + link.click(); + }; + + return ( + + ); +} diff --git a/src/components/Header.tsx b/src/components/Header.tsx index 4f83289..f2a3432 100644 --- a/src/components/Header.tsx +++ b/src/components/Header.tsx @@ -1,18 +1,22 @@ -import { useLocation } from 'preact-iso'; - -export function Header() { - const { url } = useLocation(); +export function Header({ theme }) { return ( -
- +
+
+

alejandrolaguna.dev

+ +
); } + + diff --git a/src/components/Layout.tsx b/src/components/Layout.tsx new file mode 100644 index 0000000..4f9ba23 --- /dev/null +++ b/src/components/Layout.tsx @@ -0,0 +1,10 @@ +export default function Layout({ children, theme }) { + return ( +
+
+ {children} +
+
+ ); +} + diff --git a/src/components/ProjectCard.tsx b/src/components/ProjectCard.tsx new file mode 100644 index 0000000..093aa5b --- /dev/null +++ b/src/components/ProjectCard.tsx @@ -0,0 +1,26 @@ +export default function ProjectCard({ project, theme }) { + return ( +
+
+

{project.title}

+ {project.year} +
+

{project.description}

+
+ {project.tech.map((tech, j) => ( + {tech} + ))} +
+ {project.link && ( + + View Details + + + )} +
+ ); +} + diff --git a/src/components/Projects.tsx b/src/components/Projects.tsx new file mode 100644 index 0000000..9b4c138 --- /dev/null +++ b/src/components/Projects.tsx @@ -0,0 +1,46 @@ +import ProjectCard from './ProjectCard'; + +const projects = [ + { + title: "Codertype", + description: "A monkeytype-like application designed specifically for developers", + tech: ["Laravel", "Livewire", "AlpineJS", "TailwindCSS", "PostgreSQL"], + year: "2025", + link: "https://github.com/alejandrolaguna20/codertype" + }, + { + title: "Nook.nvim", + description: "A tiny Neovim plugin created to manage tasks in a way that perfectly fits my personal workflow ", + tech: ["Lua"], + year: "2025", + link: "https://github.com/alejandrolaguna20/nook.nvim" + }, + { + title: "Portfolio", + description: "The website you are currently browsing, my little corner on the web.", + tech: ["Typescript", "PreactJS", "TailwindCSS", "Vite"], + year: "2025", + link: "https://github.com/alejandrolaguna20/portfolio" + }, + { + title: "Epitech Projects", + description: "A variety of projects I am building in my first year @ Epitech that range from algorithm implementation, graphical and mathematical simulations, and developing from scratch different Linux commands and programs, including a shell.", + tech: ["C", "Bash", "Python"], + year: "2025", + link: "https://www.epitech.eu/programme-grande-ecole-informatique/" + } +]; + +export default function Projects({ theme }) { + return ( +
+

Projects

+
+ {projects.map((project, i) => ( + + ))} +
+
+ ); +} + diff --git a/src/index.tsx b/src/index.tsx index 9cdf9c1..20ee853 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -1,19 +1,40 @@ import { render } from 'preact'; import { LocationProvider, Router, Route } from 'preact-iso'; - -import { Header } from './components/Header.jsx'; import { Home } from './pages/Home/index.jsx'; import { NotFound } from './pages/_404.jsx'; import './style.css'; +import { Header } from './components/Header.js'; export function App() { + const theme = { + bg: 'bg-[#1c2529]', + text: 'text-[#f0e4c8]', + accent: 'text-[#c7dd9a]', + accent2: 'text-[#f0b090]', + border: 'border-[#344146]', + card: 'bg-[#263136]', + hover: 'hover:text-[#fff4d8]', + button: 'bg-[#344146] hover:bg-[#49555a] text-[#f0e4c8]', + bg_hl: 'bg-[#344146]', + gradient: 'from-[#1c2529] via-[#263136] to-[#1c2529]' + } + return ( -
+
- - + ( + + )} + /> + ()} />
diff --git a/src/pages/Home/index.tsx b/src/pages/Home/index.tsx index 923de37..06436b7 100644 --- a/src/pages/Home/index.tsx +++ b/src/pages/Home/index.tsx @@ -1,39 +1,28 @@ -import preactLogo from '../../assets/preact.svg'; -import './style.css'; +import { useState, useEffect } from 'preact/hooks'; +import Layout from '../../components/Layout'; +import About from '../../components/About'; +import Projects from '../../components/Projects'; +import Experience from '../../components/Experience'; +import Footer from '../../components/Footer'; +import Education from '../../components/Education'; + +export function Home({ theme }) { + const [scrollPosition, setScrollPosition] = useState(0); + + useEffect(() => { + const handleScroll = () => setScrollPosition(window.scrollY); + window.addEventListener('scroll', handleScroll); + return () => window.removeEventListener('scroll', handleScroll); + }, []); -export function Home() { return ( -
- - Preact logo - -

Get Started building Vite-powered Preact Apps

-
- - - -
-
+ + + + + +