Compare changes

Choose any two refs to compare.

-4
.vscode/extensions.json
···
-
{
-
"recommendations": ["astro-build.astro-vscode"],
-
"unwantedRecommendations": []
-
}
-11
.vscode/launch.json
···
-
{
-
"version": "0.2.0",
-
"configurations": [
-
{
-
"command": "./node_modules/.bin/astro dev",
-
"name": "Development server",
-
"request": "launch",
-
"type": "node-terminal"
-
}
-
]
-
}
-46
README.md
···
-
# Astro Starter Kit: Basics
-
-
```sh
-
bun create astro@latest -- --template basics
-
```
-
-
> ๐Ÿง‘โ€๐Ÿš€ **Seasoned astronaut?** Delete this file. Have fun!
-
-
## ๐Ÿš€ Project Structure
-
-
Inside of your Astro project, you'll see the following folders and files:
-
-
```text
-
/
-
โ”œโ”€โ”€ public/
-
โ”‚ โ””โ”€โ”€ favicon.svg
-
โ”œโ”€โ”€ src
-
โ”‚ย ย  โ”œโ”€โ”€ assets
-
โ”‚ย ย  โ”‚ย ย  โ””โ”€โ”€ astro.svg
-
โ”‚ย ย  โ”œโ”€โ”€ components
-
โ”‚ย ย  โ”‚ย ย  โ””โ”€โ”€ Welcome.astro
-
โ”‚ย ย  โ”œโ”€โ”€ layouts
-
โ”‚ย ย  โ”‚ย ย  โ””โ”€โ”€ Layout.astro
-
โ”‚ย ย  โ””โ”€โ”€ pages
-
โ”‚ย ย  โ””โ”€โ”€ index.astro
-
โ””โ”€โ”€ package.json
-
```
-
-
To learn more about the folder structure of an Astro project, refer to [our guide on project structure](https://docs.astro.build/en/basics/project-structure/).
-
-
## ๐Ÿงž Commands
-
-
All commands are run from the root of the project, from a terminal:
-
-
| Command | Action |
-
| :------------------------ | :----------------------------------------------- |
-
| `bun install` | Installs dependencies |
-
| `bun dev` | Starts local dev server at `localhost:4321` |
-
| `bun build` | Build your production site to `./dist/` |
-
| `bun preview` | Preview your build locally, before deploying |
-
| `bun astro ...` | Run CLI commands like `astro add`, `astro check` |
-
| `bun astro -- --help` | Get help using the Astro CLI |
-
-
## ๐Ÿ‘€ Want to learn more?
-
-
Feel free to check [our documentation](https://docs.astro.build) or jump into our [Discord server](https://astro.build/chat).
+11 -1
astro.config.mjs
···
// @ts-check
import { defineConfig } from 'astro/config';
+
import tailwindcss from '@tailwindcss/vite';
+
+
import react from '@astrojs/react';
+
// https://astro.build/config
-
export default defineConfig({});
+
export default defineConfig({
+
vite: {
+
plugins: [tailwindcss()]
+
},
+
+
integrations: [react()]
+
});
+199
bun.lock
···
"": {
"name": "mywebsite-2026",
"dependencies": {
+
"@astrojs/react": "^4.4.2",
+
"@lucide/astro": "^0.553.0",
+
"@lucide/lab": "^0.1.2",
+
"@tailwindcss/vite": "^4.1.17",
+
"@types/react": "^19.2.2",
+
"@types/react-dom": "^19.2.2",
"astro": "^5.15.4",
+
"react": "^19.2.0",
+
"react-dom": "^19.2.0",
+
"react-github-calendar": "^4.5.11",
+
"tailwindcss": "^4.1.17",
+
},
+
"devDependencies": {
+
"@catppuccin/tailwindcss": "^1.0.0",
},
},
},
···
"@astrojs/prism": ["@astrojs/prism@3.3.0", "", { "dependencies": { "prismjs": "^1.30.0" } }, "sha512-q8VwfU/fDZNoDOf+r7jUnMC2//H2l0TuQ6FkGJL8vD8nw/q5KiL3DS1KKBI3QhI9UQhpJ5dc7AtqfbXWuOgLCQ=="],
+
"@astrojs/react": ["@astrojs/react@4.4.2", "", { "dependencies": { "@vitejs/plugin-react": "^4.7.0", "ultrahtml": "^1.6.0", "vite": "^6.4.1" }, "peerDependencies": { "@types/react": "^17.0.50 || ^18.0.21 || ^19.0.0", "@types/react-dom": "^17.0.17 || ^18.0.6 || ^19.0.0", "react": "^17.0.2 || ^18.0.0 || ^19.0.0", "react-dom": "^17.0.2 || ^18.0.0 || ^19.0.0" } }, "sha512-1tl95bpGfuaDMDn8O3x/5Dxii1HPvzjvpL2YTuqOOrQehs60I2DKiDgh1jrKc7G8lv+LQT5H15V6QONQ+9waeQ=="],
+
"@astrojs/telemetry": ["@astrojs/telemetry@3.3.0", "", { "dependencies": { "ci-info": "^4.2.0", "debug": "^4.4.0", "dlv": "^1.1.3", "dset": "^3.1.4", "is-docker": "^3.0.0", "is-wsl": "^3.1.0", "which-pm-runs": "^1.1.0" } }, "sha512-UFBgfeldP06qu6khs/yY+q1cDAaArM2/7AEIqQ9Cuvf7B1hNLq0xDrZkct+QoIGyjq56y8IaE2I3CTvG99mlhQ=="],
+
"@babel/code-frame": ["@babel/code-frame@7.27.1", "", { "dependencies": { "@babel/helper-validator-identifier": "^7.27.1", "js-tokens": "^4.0.0", "picocolors": "^1.1.1" } }, "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg=="],
+
+
"@babel/compat-data": ["@babel/compat-data@7.28.5", "", {}, "sha512-6uFXyCayocRbqhZOB+6XcuZbkMNimwfVGFji8CTZnCzOHVGvDqzvitu1re2AU5LROliz7eQPhB8CpAMvnx9EjA=="],
+
+
"@babel/core": ["@babel/core@7.28.5", "", { "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/generator": "^7.28.5", "@babel/helper-compilation-targets": "^7.27.2", "@babel/helper-module-transforms": "^7.28.3", "@babel/helpers": "^7.28.4", "@babel/parser": "^7.28.5", "@babel/template": "^7.27.2", "@babel/traverse": "^7.28.5", "@babel/types": "^7.28.5", "@jridgewell/remapping": "^2.3.5", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", "json5": "^2.2.3", "semver": "^6.3.1" } }, "sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw=="],
+
+
"@babel/generator": ["@babel/generator@7.28.5", "", { "dependencies": { "@babel/parser": "^7.28.5", "@babel/types": "^7.28.5", "@jridgewell/gen-mapping": "^0.3.12", "@jridgewell/trace-mapping": "^0.3.28", "jsesc": "^3.0.2" } }, "sha512-3EwLFhZ38J4VyIP6WNtt2kUdW9dokXA9Cr4IVIFHuCpZ3H8/YFOl5JjZHisrn1fATPBmKKqXzDFvh9fUwHz6CQ=="],
+
+
"@babel/helper-compilation-targets": ["@babel/helper-compilation-targets@7.27.2", "", { "dependencies": { "@babel/compat-data": "^7.27.2", "@babel/helper-validator-option": "^7.27.1", "browserslist": "^4.24.0", "lru-cache": "^5.1.1", "semver": "^6.3.1" } }, "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ=="],
+
+
"@babel/helper-globals": ["@babel/helper-globals@7.28.0", "", {}, "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw=="],
+
+
"@babel/helper-module-imports": ["@babel/helper-module-imports@7.27.1", "", { "dependencies": { "@babel/traverse": "^7.27.1", "@babel/types": "^7.27.1" } }, "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w=="],
+
+
"@babel/helper-module-transforms": ["@babel/helper-module-transforms@7.28.3", "", { "dependencies": { "@babel/helper-module-imports": "^7.27.1", "@babel/helper-validator-identifier": "^7.27.1", "@babel/traverse": "^7.28.3" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw=="],
+
+
"@babel/helper-plugin-utils": ["@babel/helper-plugin-utils@7.27.1", "", {}, "sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw=="],
+
"@babel/helper-string-parser": ["@babel/helper-string-parser@7.27.1", "", {}, "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA=="],
"@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.28.5", "", {}, "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q=="],
+
"@babel/helper-validator-option": ["@babel/helper-validator-option@7.27.1", "", {}, "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg=="],
+
+
"@babel/helpers": ["@babel/helpers@7.28.4", "", { "dependencies": { "@babel/template": "^7.27.2", "@babel/types": "^7.28.4" } }, "sha512-HFN59MmQXGHVyYadKLVumYsA9dBFun/ldYxipEjzA4196jpLZd8UjEEBLkbEkvfYreDqJhZxYAWFPtrfhNpj4w=="],
+
"@babel/parser": ["@babel/parser@7.28.5", "", { "dependencies": { "@babel/types": "^7.28.5" }, "bin": "./bin/babel-parser.js" }, "sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ=="],
+
"@babel/plugin-transform-react-jsx-self": ["@babel/plugin-transform-react-jsx-self@7.27.1", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw=="],
+
+
"@babel/plugin-transform-react-jsx-source": ["@babel/plugin-transform-react-jsx-source@7.27.1", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw=="],
+
+
"@babel/template": ["@babel/template@7.27.2", "", { "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/parser": "^7.27.2", "@babel/types": "^7.27.1" } }, "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw=="],
+
+
"@babel/traverse": ["@babel/traverse@7.28.5", "", { "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/generator": "^7.28.5", "@babel/helper-globals": "^7.28.0", "@babel/parser": "^7.28.5", "@babel/template": "^7.27.2", "@babel/types": "^7.28.5", "debug": "^4.3.1" } }, "sha512-TCCj4t55U90khlYkVV/0TfkJkAkUg3jZFA3Neb7unZT8CPok7iiRfaX0F+WnqWqt7OxhOn0uBKXCw4lbL8W0aQ=="],
+
"@babel/types": ["@babel/types@7.28.5", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.28.5" } }, "sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA=="],
"@capsizecss/unpack": ["@capsizecss/unpack@3.0.0", "", { "dependencies": { "fontkit": "^2.0.2" } }, "sha512-+ntATQe1AlL7nTOYjwjj6w3299CgRot48wL761TUGYpYgAou3AaONZazp0PKZyCyWhudWsjhq1nvRHOvbMzhTA=="],
+
+
"@catppuccin/tailwindcss": ["@catppuccin/tailwindcss@1.0.0", "", {}, "sha512-l8pOlcYe2ncGd8a1gUmL5AHmKlxR2+CHuG5kt4Me6IZwzntW1DoLmj89BH+DcsPHBsdDGLrTSv35emlYyU3FeQ=="],
"@emnapi/runtime": ["@emnapi/runtime@1.7.0", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-oAYoQnCYaQZKVS53Fq23ceWMRxq5EhQsE0x0RdQ55jT7wagMu5k+fS39v1fiSLrtrLQlXwVINenqhLMtTrV/1Q=="],
···
"@img/sharp-win32-x64": ["@img/sharp-win32-x64@0.34.5", "", { "os": "win32", "cpu": "x64" }, "sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw=="],
+
"@jridgewell/gen-mapping": ["@jridgewell/gen-mapping@0.3.13", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA=="],
+
+
"@jridgewell/remapping": ["@jridgewell/remapping@2.3.5", "", { "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ=="],
+
+
"@jridgewell/resolve-uri": ["@jridgewell/resolve-uri@3.1.2", "", {}, "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw=="],
+
"@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.5", "", {}, "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og=="],
+
"@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.31", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw=="],
+
+
"@lucide/astro": ["@lucide/astro@0.553.0", "", { "peerDependencies": { "astro": "^4 || ^5" } }, "sha512-yiHpOKGBPOy+pmZfkQmZcFAETU8FvkqWdoLCboSZGuZ1zgwFHGxBmr/brmk5PxVFOUnImzsRFGzAX2O2A88hmQ=="],
+
+
"@lucide/lab": ["@lucide/lab@0.1.2", "", {}, "sha512-VprF2BJa7ZuTGOhUd5cf8tHJXyL63wdxcGieAiVVoR9hO0YmPsnZO0AGqDiX2/br+/MC6n8BoJcmPilltOXIJA=="],
+
"@oslojs/encoding": ["@oslojs/encoding@1.1.0", "", {}, "sha512-70wQhgYmndg4GCPxPPxPGevRKqTIJ2Nh4OkiMWmDAVYsTQ+Ta7Sq+rPevXyXGdzr30/qZBnyOalCszoMxlyldQ=="],
+
+
"@rolldown/pluginutils": ["@rolldown/pluginutils@1.0.0-beta.27", "", {}, "sha512-+d0F4MKMCbeVUJwG96uQ4SgAznZNSq93I3V+9NHA4OpvqG8mRCpGdKmK8l/dl02h2CCDHwW2FqilnTyDcAnqjA=="],
"@rollup/pluginutils": ["@rollup/pluginutils@5.3.0", "", { "dependencies": { "@types/estree": "^1.0.0", "estree-walker": "^2.0.2", "picomatch": "^4.0.2" }, "peerDependencies": { "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" }, "optionalPeers": ["rollup"] }, "sha512-5EdhGZtnu3V88ces7s53hhfK5KSASnJZv8Lulpc04cWO3REESroJXg73DFsOmgbU2BhwV0E20bu2IDZb3VKW4Q=="],
···
"@swc/helpers": ["@swc/helpers@0.5.17", "", { "dependencies": { "tslib": "^2.8.0" } }, "sha512-5IKx/Y13RsYd+sauPb2x+U/xZikHjolzfuDgTAl/Tdf3Q8rslRvC19NKDLgAJQ6wsqADk10ntlv08nPFw/gO/A=="],
+
"@tailwindcss/node": ["@tailwindcss/node@4.1.17", "", { "dependencies": { "@jridgewell/remapping": "^2.3.4", "enhanced-resolve": "^5.18.3", "jiti": "^2.6.1", "lightningcss": "1.30.2", "magic-string": "^0.30.21", "source-map-js": "^1.2.1", "tailwindcss": "4.1.17" } }, "sha512-csIkHIgLb3JisEFQ0vxr2Y57GUNYh447C8xzwj89U/8fdW8LhProdxvnVH6U8M2Y73QKiTIH+LWbK3V2BBZsAg=="],
+
+
"@tailwindcss/oxide": ["@tailwindcss/oxide@4.1.17", "", { "optionalDependencies": { "@tailwindcss/oxide-android-arm64": "4.1.17", "@tailwindcss/oxide-darwin-arm64": "4.1.17", "@tailwindcss/oxide-darwin-x64": "4.1.17", "@tailwindcss/oxide-freebsd-x64": "4.1.17", "@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.17", "@tailwindcss/oxide-linux-arm64-gnu": "4.1.17", "@tailwindcss/oxide-linux-arm64-musl": "4.1.17", "@tailwindcss/oxide-linux-x64-gnu": "4.1.17", "@tailwindcss/oxide-linux-x64-musl": "4.1.17", "@tailwindcss/oxide-wasm32-wasi": "4.1.17", "@tailwindcss/oxide-win32-arm64-msvc": "4.1.17", "@tailwindcss/oxide-win32-x64-msvc": "4.1.17" } }, "sha512-F0F7d01fmkQhsTjXezGBLdrl1KresJTcI3DB8EkScCldyKp3Msz4hub4uyYaVnk88BAS1g5DQjjF6F5qczheLA=="],
+
+
"@tailwindcss/oxide-android-arm64": ["@tailwindcss/oxide-android-arm64@4.1.17", "", { "os": "android", "cpu": "arm64" }, "sha512-BMqpkJHgOZ5z78qqiGE6ZIRExyaHyuxjgrJ6eBO5+hfrfGkuya0lYfw8fRHG77gdTjWkNWEEm+qeG2cDMxArLQ=="],
+
+
"@tailwindcss/oxide-darwin-arm64": ["@tailwindcss/oxide-darwin-arm64@4.1.17", "", { "os": "darwin", "cpu": "arm64" }, "sha512-EquyumkQweUBNk1zGEU/wfZo2qkp/nQKRZM8bUYO0J+Lums5+wl2CcG1f9BgAjn/u9pJzdYddHWBiFXJTcxmOg=="],
+
+
"@tailwindcss/oxide-darwin-x64": ["@tailwindcss/oxide-darwin-x64@4.1.17", "", { "os": "darwin", "cpu": "x64" }, "sha512-gdhEPLzke2Pog8s12oADwYu0IAw04Y2tlmgVzIN0+046ytcgx8uZmCzEg4VcQh+AHKiS7xaL8kGo/QTiNEGRog=="],
+
+
"@tailwindcss/oxide-freebsd-x64": ["@tailwindcss/oxide-freebsd-x64@4.1.17", "", { "os": "freebsd", "cpu": "x64" }, "sha512-hxGS81KskMxML9DXsaXT1H0DyA+ZBIbyG/sSAjWNe2EDl7TkPOBI42GBV3u38itzGUOmFfCzk1iAjDXds8Oh0g=="],
+
+
"@tailwindcss/oxide-linux-arm-gnueabihf": ["@tailwindcss/oxide-linux-arm-gnueabihf@4.1.17", "", { "os": "linux", "cpu": "arm" }, "sha512-k7jWk5E3ldAdw0cNglhjSgv501u7yrMf8oeZ0cElhxU6Y2o7f8yqelOp3fhf7evjIS6ujTI3U8pKUXV2I4iXHQ=="],
+
+
"@tailwindcss/oxide-linux-arm64-gnu": ["@tailwindcss/oxide-linux-arm64-gnu@4.1.17", "", { "os": "linux", "cpu": "arm64" }, "sha512-HVDOm/mxK6+TbARwdW17WrgDYEGzmoYayrCgmLEw7FxTPLcp/glBisuyWkFz/jb7ZfiAXAXUACfyItn+nTgsdQ=="],
+
+
"@tailwindcss/oxide-linux-arm64-musl": ["@tailwindcss/oxide-linux-arm64-musl@4.1.17", "", { "os": "linux", "cpu": "arm64" }, "sha512-HvZLfGr42i5anKtIeQzxdkw/wPqIbpeZqe7vd3V9vI3RQxe3xU1fLjss0TjyhxWcBaipk7NYwSrwTwK1hJARMg=="],
+
+
"@tailwindcss/oxide-linux-x64-gnu": ["@tailwindcss/oxide-linux-x64-gnu@4.1.17", "", { "os": "linux", "cpu": "x64" }, "sha512-M3XZuORCGB7VPOEDH+nzpJ21XPvK5PyjlkSFkFziNHGLc5d6g3di2McAAblmaSUNl8IOmzYwLx9NsE7bplNkwQ=="],
+
+
"@tailwindcss/oxide-linux-x64-musl": ["@tailwindcss/oxide-linux-x64-musl@4.1.17", "", { "os": "linux", "cpu": "x64" }, "sha512-k7f+pf9eXLEey4pBlw+8dgfJHY4PZ5qOUFDyNf7SI6lHjQ9Zt7+NcscjpwdCEbYi6FI5c2KDTDWyf2iHcCSyyQ=="],
+
+
"@tailwindcss/oxide-wasm32-wasi": ["@tailwindcss/oxide-wasm32-wasi@4.1.17", "", { "dependencies": { "@emnapi/core": "^1.6.0", "@emnapi/runtime": "^1.6.0", "@emnapi/wasi-threads": "^1.1.0", "@napi-rs/wasm-runtime": "^1.0.7", "@tybys/wasm-util": "^0.10.1", "tslib": "^2.4.0" }, "cpu": "none" }, "sha512-cEytGqSSoy7zK4JRWiTCx43FsKP/zGr0CsuMawhH67ONlH+T79VteQeJQRO/X7L0juEUA8ZyuYikcRBf0vsxhg=="],
+
+
"@tailwindcss/oxide-win32-arm64-msvc": ["@tailwindcss/oxide-win32-arm64-msvc@4.1.17", "", { "os": "win32", "cpu": "arm64" }, "sha512-JU5AHr7gKbZlOGvMdb4722/0aYbU+tN6lv1kONx0JK2cGsh7g148zVWLM0IKR3NeKLv+L90chBVYcJ8uJWbC9A=="],
+
+
"@tailwindcss/oxide-win32-x64-msvc": ["@tailwindcss/oxide-win32-x64-msvc@4.1.17", "", { "os": "win32", "cpu": "x64" }, "sha512-SKWM4waLuqx0IH+FMDUw6R66Hu4OuTALFgnleKbqhgGU30DY20NORZMZUKgLRjQXNN2TLzKvh48QXTig4h4bGw=="],
+
+
"@tailwindcss/vite": ["@tailwindcss/vite@4.1.17", "", { "dependencies": { "@tailwindcss/node": "4.1.17", "@tailwindcss/oxide": "4.1.17", "tailwindcss": "4.1.17" }, "peerDependencies": { "vite": "^5.2.0 || ^6 || ^7" } }, "sha512-4+9w8ZHOiGnpcGI6z1TVVfWaX/koK7fKeSYF3qlYg2xpBtbteP2ddBxiarL+HVgfSJGeK5RIxRQmKm4rTJJAwA=="],
+
+
"@types/babel__core": ["@types/babel__core@7.20.5", "", { "dependencies": { "@babel/parser": "^7.20.7", "@babel/types": "^7.20.7", "@types/babel__generator": "*", "@types/babel__template": "*", "@types/babel__traverse": "*" } }, "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA=="],
+
+
"@types/babel__generator": ["@types/babel__generator@7.27.0", "", { "dependencies": { "@babel/types": "^7.0.0" } }, "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg=="],
+
+
"@types/babel__template": ["@types/babel__template@7.4.4", "", { "dependencies": { "@babel/parser": "^7.1.0", "@babel/types": "^7.0.0" } }, "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A=="],
+
+
"@types/babel__traverse": ["@types/babel__traverse@7.28.0", "", { "dependencies": { "@babel/types": "^7.28.2" } }, "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q=="],
+
"@types/debug": ["@types/debug@4.1.12", "", { "dependencies": { "@types/ms": "*" } }, "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ=="],
"@types/estree": ["@types/estree@1.0.8", "", {}, "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w=="],
···
"@types/node": ["@types/node@24.10.0", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-qzQZRBqkFsYyaSWXuEHc2WR9c0a0CXwiE5FWUvn7ZM+vdy1uZLfCunD38UzhuB7YN/J11ndbDBcTmOdxJo9Q7A=="],
+
"@types/react": ["@types/react@19.2.2", "", { "dependencies": { "csstype": "^3.0.2" } }, "sha512-6mDvHUFSjyT2B2yeNx2nUgMxh9LtOWvkhIU3uePn2I2oyNymUAX1NIsdgviM4CH+JSrp2D2hsMvJOkxY+0wNRA=="],
+
+
"@types/react-dom": ["@types/react-dom@19.2.2", "", { "peerDependencies": { "@types/react": "^19.2.0" } }, "sha512-9KQPoO6mZCi7jcIStSnlOWn2nEF3mNmyr3rIAsGnAbQKYbRLyqmeSc39EVgtxXVia+LMT8j3knZLAZAh+xLmrw=="],
+
"@types/unist": ["@types/unist@3.0.3", "", {}, "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q=="],
"@ungap/structured-clone": ["@ungap/structured-clone@1.3.0", "", {}, "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g=="],
+
+
"@vitejs/plugin-react": ["@vitejs/plugin-react@4.7.0", "", { "dependencies": { "@babel/core": "^7.28.0", "@babel/plugin-transform-react-jsx-self": "^7.27.1", "@babel/plugin-transform-react-jsx-source": "^7.27.1", "@rolldown/pluginutils": "1.0.0-beta.27", "@types/babel__core": "^7.20.5", "react-refresh": "^0.17.0" }, "peerDependencies": { "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0" } }, "sha512-gUu9hwfWvvEDBBmgtAowQCojwZmJ5mcLn3aufeCsitijs3+f2NsrPtlAWIR6OPiqljl96GVCUbLe0HyqIpVaoA=="],
"acorn": ["acorn@8.15.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg=="],
···
"base-64": ["base-64@1.0.0", "", {}, "sha512-kwDPIFCGx0NZHog36dj+tHiwP4QMzsZ3AgMViUBKI0+V5n4U0ufTCUMhnQ04diaRI8EX/QcPfql7zlhZ7j4zgg=="],
"base64-js": ["base64-js@1.5.1", "", {}, "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="],
+
+
"baseline-browser-mapping": ["baseline-browser-mapping@2.8.25", "", { "bin": { "baseline-browser-mapping": "dist/cli.js" } }, "sha512-2NovHVesVF5TXefsGX1yzx1xgr7+m9JQenvz6FQY3qd+YXkKkYiv+vTCc7OriP9mcDZpTC5mAOYN4ocd29+erA=="],
"boxen": ["boxen@8.0.1", "", { "dependencies": { "ansi-align": "^3.0.1", "camelcase": "^8.0.0", "chalk": "^5.3.0", "cli-boxes": "^3.0.0", "string-width": "^7.2.0", "type-fest": "^4.21.0", "widest-line": "^5.0.0", "wrap-ansi": "^9.0.0" } }, "sha512-F3PH5k5juxom4xktynS7MoFY+NUWH5LC4CnH11YB8NPew+HLpmBLCybSAEyb2F+4pRXhuhWqFesoQd6DAyc2hw=="],
"brotli": ["brotli@1.3.3", "", { "dependencies": { "base64-js": "^1.1.2" } }, "sha512-oTKjJdShmDuGW94SyyaoQvAjf30dZaHnjJ8uAF+u2/vGJkJbJPJAT1gDiOJP5v1Zb6f9KEyW/1HpuaWIXtGHPg=="],
+
"browserslist": ["browserslist@4.27.0", "", { "dependencies": { "baseline-browser-mapping": "^2.8.19", "caniuse-lite": "^1.0.30001751", "electron-to-chromium": "^1.5.238", "node-releases": "^2.0.26", "update-browserslist-db": "^1.1.4" }, "bin": { "browserslist": "cli.js" } }, "sha512-AXVQwdhot1eqLihwasPElhX2tAZiBjWdJ9i/Zcj2S6QYIjkx62OKSfnobkriB81C3l4w0rVy3Nt4jaTBltYEpw=="],
+
"camelcase": ["camelcase@8.0.0", "", {}, "sha512-8WB3Jcas3swSvjIeA2yvCJ+Miyz5l1ZmB6HFb9R1317dt9LCQoswg/BGrmAmkWVEszSrrg4RwmO46qIm2OEnSA=="],
+
+
"caniuse-lite": ["caniuse-lite@1.0.30001754", "", {}, "sha512-x6OeBXueoAceOmotzx3PO4Zpt4rzpeIFsSr6AAePTZxSkXiYDUmpypEl7e2+8NCd9bD7bXjqyef8CJYPC1jfxg=="],
"ccount": ["ccount@2.0.1", "", {}, "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg=="],
···
"comma-separated-tokens": ["comma-separated-tokens@2.0.3", "", {}, "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg=="],
"common-ancestor-path": ["common-ancestor-path@1.0.1", "", {}, "sha512-L3sHRo1pXXEqX8VU28kfgUY+YGsk09hPqZiZmLacNib6XNTCM8ubYeT7ryXQw8asB1sKgcU5lkB7ONug08aB8w=="],
+
+
"convert-source-map": ["convert-source-map@2.0.0", "", {}, "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg=="],
"cookie": ["cookie@1.0.2", "", {}, "sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA=="],
···
"cssesc": ["cssesc@3.0.0", "", { "bin": { "cssesc": "bin/cssesc" } }, "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg=="],
+
"csstype": ["csstype@3.1.3", "", {}, "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="],
+
+
"date-fns": ["date-fns@4.1.0", "", {}, "sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg=="],
+
"debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="],
"decode-named-character-reference": ["decode-named-character-reference@1.2.0", "", { "dependencies": { "character-entities": "^2.0.0" } }, "sha512-c6fcElNV6ShtZXmsgNgFFV5tVX2PaV4g+MOAkb8eXHvn6sryJBrZa9r0zV6+dtTyoCKxtDy5tyQ5ZwQuidtd+Q=="],
···
"dlv": ["dlv@1.1.3", "", {}, "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA=="],
"dset": ["dset@3.1.4", "", {}, "sha512-2QF/g9/zTaPDc3BjNcVTGoBbXBgYfMTTceLaYcFJ/W9kggFUkhxD/hMEeuLKbugyef9SqAx8cpgwlIP/jinUTA=="],
+
+
"electron-to-chromium": ["electron-to-chromium@1.5.249", "", {}, "sha512-5vcfL3BBe++qZ5kuFhD/p8WOM1N9m3nwvJPULJx+4xf2usSlZFJ0qoNYO2fOX4hi3ocuDcmDobtA+5SFr4OmBg=="],
"emoji-regex": ["emoji-regex@10.6.0", "", {}, "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A=="],
+
"enhanced-resolve": ["enhanced-resolve@5.18.3", "", { "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.2.0" } }, "sha512-d4lC8xfavMeBjzGr2vECC3fsGXziXZQyJxD868h2M/mBI3PwAuODxAkLkq5HYuvrPYcUtiLzsTo8U3PgX3Ocww=="],
+
"entities": ["entities@6.0.1", "", {}, "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g=="],
"es-module-lexer": ["es-module-lexer@1.7.0", "", {}, "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA=="],
"esbuild": ["esbuild@0.25.12", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.25.12", "@esbuild/android-arm": "0.25.12", "@esbuild/android-arm64": "0.25.12", "@esbuild/android-x64": "0.25.12", "@esbuild/darwin-arm64": "0.25.12", "@esbuild/darwin-x64": "0.25.12", "@esbuild/freebsd-arm64": "0.25.12", "@esbuild/freebsd-x64": "0.25.12", "@esbuild/linux-arm": "0.25.12", "@esbuild/linux-arm64": "0.25.12", "@esbuild/linux-ia32": "0.25.12", "@esbuild/linux-loong64": "0.25.12", "@esbuild/linux-mips64el": "0.25.12", "@esbuild/linux-ppc64": "0.25.12", "@esbuild/linux-riscv64": "0.25.12", "@esbuild/linux-s390x": "0.25.12", "@esbuild/linux-x64": "0.25.12", "@esbuild/netbsd-arm64": "0.25.12", "@esbuild/netbsd-x64": "0.25.12", "@esbuild/openbsd-arm64": "0.25.12", "@esbuild/openbsd-x64": "0.25.12", "@esbuild/openharmony-arm64": "0.25.12", "@esbuild/sunos-x64": "0.25.12", "@esbuild/win32-arm64": "0.25.12", "@esbuild/win32-ia32": "0.25.12", "@esbuild/win32-x64": "0.25.12" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg=="],
+
+
"escalade": ["escalade@3.2.0", "", {}, "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA=="],
"escape-string-regexp": ["escape-string-regexp@5.0.0", "", {}, "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw=="],
···
"fontkit": ["fontkit@2.0.4", "", { "dependencies": { "@swc/helpers": "^0.5.12", "brotli": "^1.3.2", "clone": "^2.1.2", "dfa": "^1.2.0", "fast-deep-equal": "^3.1.3", "restructure": "^3.0.0", "tiny-inflate": "^1.0.3", "unicode-properties": "^1.4.0", "unicode-trie": "^2.0.0" } }, "sha512-syetQadaUEDNdxdugga9CpEYVaQIxOwk7GlwZWWZ19//qW4zE5bknOKeMBDYAASwnpaSHKJITRLMF9m1fp3s6g=="],
"fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="],
+
+
"gensync": ["gensync@1.0.0-beta.2", "", {}, "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg=="],
"get-east-asian-width": ["get-east-asian-width@1.4.0", "", {}, "sha512-QZjmEOC+IT1uk6Rx0sX22V6uHWVwbdbxf1faPqJ1QhLdGgsRGCZoyaQBm/piRdJy/D2um6hM1UP7ZEeQ4EkP+Q=="],
"github-slugger": ["github-slugger@2.0.0", "", {}, "sha512-IaOQ9puYtjrkq7Y0Ygl9KDZnrf/aiUJYUpVf89y8kyaxbRG7Y1SrX/jaumrv81vc61+kiMempujsM3Yw7w5qcw=="],
+
"graceful-fs": ["graceful-fs@4.2.11", "", {}, "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="],
+
"h3": ["h3@1.15.4", "", { "dependencies": { "cookie-es": "^1.2.2", "crossws": "^0.3.5", "defu": "^6.1.4", "destr": "^2.0.5", "iron-webcrypto": "^1.2.1", "node-mock-http": "^1.0.2", "radix3": "^1.1.2", "ufo": "^1.6.1", "uncrypto": "^0.1.3" } }, "sha512-z5cFQWDffyOe4vQ9xIqNfCZdV4p//vy6fBnr8Q1AWnVZ0teurKMG66rLj++TKwKPUP3u7iMUvrvKaEUiQw2QWQ=="],
"hast-util-from-html": ["hast-util-from-html@2.0.3", "", { "dependencies": { "@types/hast": "^3.0.0", "devlop": "^1.1.0", "hast-util-from-parse5": "^8.0.0", "parse5": "^7.0.0", "vfile": "^6.0.0", "vfile-message": "^4.0.0" } }, "sha512-CUSRHXyKjzHov8yKsQjGOElXy/3EKpyX56ELnkHH34vDVw1N1XSQ1ZcAvTyAPtGqLTuKP/uxM+aLkSPqF/EtMw=="],
···
"is-wsl": ["is-wsl@3.1.0", "", { "dependencies": { "is-inside-container": "^1.0.0" } }, "sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw=="],
+
"jiti": ["jiti@2.6.1", "", { "bin": { "jiti": "lib/jiti-cli.mjs" } }, "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ=="],
+
+
"js-tokens": ["js-tokens@4.0.0", "", {}, "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="],
+
"js-yaml": ["js-yaml@4.1.0", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA=="],
+
"jsesc": ["jsesc@3.1.0", "", { "bin": { "jsesc": "bin/jsesc" } }, "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA=="],
+
+
"json5": ["json5@2.2.3", "", { "bin": { "json5": "lib/cli.js" } }, "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg=="],
+
"kleur": ["kleur@3.0.3", "", {}, "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w=="],
+
"lightningcss": ["lightningcss@1.30.2", "", { "dependencies": { "detect-libc": "^2.0.3" }, "optionalDependencies": { "lightningcss-android-arm64": "1.30.2", "lightningcss-darwin-arm64": "1.30.2", "lightningcss-darwin-x64": "1.30.2", "lightningcss-freebsd-x64": "1.30.2", "lightningcss-linux-arm-gnueabihf": "1.30.2", "lightningcss-linux-arm64-gnu": "1.30.2", "lightningcss-linux-arm64-musl": "1.30.2", "lightningcss-linux-x64-gnu": "1.30.2", "lightningcss-linux-x64-musl": "1.30.2", "lightningcss-win32-arm64-msvc": "1.30.2", "lightningcss-win32-x64-msvc": "1.30.2" } }, "sha512-utfs7Pr5uJyyvDETitgsaqSyjCb2qNRAtuqUeWIAKztsOYdcACf2KtARYXg2pSvhkt+9NfoaNY7fxjl6nuMjIQ=="],
+
+
"lightningcss-android-arm64": ["lightningcss-android-arm64@1.30.2", "", { "os": "android", "cpu": "arm64" }, "sha512-BH9sEdOCahSgmkVhBLeU7Hc9DWeZ1Eb6wNS6Da8igvUwAe0sqROHddIlvU06q3WyXVEOYDZ6ykBZQnjTbmo4+A=="],
+
+
"lightningcss-darwin-arm64": ["lightningcss-darwin-arm64@1.30.2", "", { "os": "darwin", "cpu": "arm64" }, "sha512-ylTcDJBN3Hp21TdhRT5zBOIi73P6/W0qwvlFEk22fkdXchtNTOU4Qc37SkzV+EKYxLouZ6M4LG9NfZ1qkhhBWA=="],
+
+
"lightningcss-darwin-x64": ["lightningcss-darwin-x64@1.30.2", "", { "os": "darwin", "cpu": "x64" }, "sha512-oBZgKchomuDYxr7ilwLcyms6BCyLn0z8J0+ZZmfpjwg9fRVZIR5/GMXd7r9RH94iDhld3UmSjBM6nXWM2TfZTQ=="],
+
+
"lightningcss-freebsd-x64": ["lightningcss-freebsd-x64@1.30.2", "", { "os": "freebsd", "cpu": "x64" }, "sha512-c2bH6xTrf4BDpK8MoGG4Bd6zAMZDAXS569UxCAGcA7IKbHNMlhGQ89eRmvpIUGfKWNVdbhSbkQaWhEoMGmGslA=="],
+
+
"lightningcss-linux-arm-gnueabihf": ["lightningcss-linux-arm-gnueabihf@1.30.2", "", { "os": "linux", "cpu": "arm" }, "sha512-eVdpxh4wYcm0PofJIZVuYuLiqBIakQ9uFZmipf6LF/HRj5Bgm0eb3qL/mr1smyXIS1twwOxNWndd8z0E374hiA=="],
+
+
"lightningcss-linux-arm64-gnu": ["lightningcss-linux-arm64-gnu@1.30.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-UK65WJAbwIJbiBFXpxrbTNArtfuznvxAJw4Q2ZGlU8kPeDIWEX1dg3rn2veBVUylA2Ezg89ktszWbaQnxD/e3A=="],
+
+
"lightningcss-linux-arm64-musl": ["lightningcss-linux-arm64-musl@1.30.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-5Vh9dGeblpTxWHpOx8iauV02popZDsCYMPIgiuw97OJ5uaDsL86cnqSFs5LZkG3ghHoX5isLgWzMs+eD1YzrnA=="],
+
+
"lightningcss-linux-x64-gnu": ["lightningcss-linux-x64-gnu@1.30.2", "", { "os": "linux", "cpu": "x64" }, "sha512-Cfd46gdmj1vQ+lR6VRTTadNHu6ALuw2pKR9lYq4FnhvgBc4zWY1EtZcAc6EffShbb1MFrIPfLDXD6Xprbnni4w=="],
+
+
"lightningcss-linux-x64-musl": ["lightningcss-linux-x64-musl@1.30.2", "", { "os": "linux", "cpu": "x64" }, "sha512-XJaLUUFXb6/QG2lGIW6aIk6jKdtjtcffUT0NKvIqhSBY3hh9Ch+1LCeH80dR9q9LBjG3ewbDjnumefsLsP6aiA=="],
+
+
"lightningcss-win32-arm64-msvc": ["lightningcss-win32-arm64-msvc@1.30.2", "", { "os": "win32", "cpu": "arm64" }, "sha512-FZn+vaj7zLv//D/192WFFVA0RgHawIcHqLX9xuWiQt7P0PtdFEVaxgF9rjM/IRYHQXNnk61/H/gb2Ei+kUQ4xQ=="],
+
+
"lightningcss-win32-x64-msvc": ["lightningcss-win32-x64-msvc@1.30.2", "", { "os": "win32", "cpu": "x64" }, "sha512-5g1yc73p+iAkid5phb4oVFMB45417DkRevRbt/El/gKXJk4jid+vPFF/AXbxn05Aky8PapwzZrdJShv5C0avjw=="],
+
"longest-streak": ["longest-streak@3.1.0", "", {}, "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g=="],
"lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="],
···
"node-mock-http": ["node-mock-http@1.0.3", "", {}, "sha512-jN8dK25fsfnMrVsEhluUTPkBFY+6ybu7jSB1n+ri/vOGjJxU8J9CZhpSGkHXSkFjtUhbmoncG/YG9ta5Ludqog=="],
+
"node-releases": ["node-releases@2.0.27", "", {}, "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA=="],
+
"normalize-path": ["normalize-path@3.0.0", "", {}, "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA=="],
"ofetch": ["ofetch@1.5.1", "", { "dependencies": { "destr": "^2.0.5", "node-fetch-native": "^1.6.7", "ufo": "^1.6.1" } }, "sha512-2W4oUZlVaqAPAil6FUg/difl6YhqhUR7x2eZY4bQCko22UXg3hptq9KLQdqFClV+Wu85UX7hNtdGTngi/1BxcA=="],
···
"radix3": ["radix3@1.1.2", "", {}, "sha512-b484I/7b8rDEdSDKckSSBA8knMpcdsXudlE/LNL639wFoHKwLbEkQFZHWEYwDC0wa0FKUcCY+GAF73Z7wxNVFA=="],
+
"react": ["react@19.2.0", "", {}, "sha512-tmbWg6W31tQLeB5cdIBOicJDJRR2KzXsV7uSK9iNfLWQ5bIZfxuPEHp7M8wiHyHnn0DD1i7w3Zmin0FtkrwoCQ=="],
+
+
"react-activity-calendar": ["react-activity-calendar@2.7.15", "", { "dependencies": { "date-fns": "^4.1.0" }, "peerDependencies": { "react": "^18.0.0 || ^19.0.0" } }, "sha512-sPO4tDJp+sRbV8F/LhUZ/woHmi4dg0Phd+Kt1Jw0orSfGfEqGCm7fFXiTIAvuuAwpwxqPEYEnfNzOLEfUrdg1A=="],
+
+
"react-dom": ["react-dom@19.2.0", "", { "dependencies": { "scheduler": "^0.27.0" }, "peerDependencies": { "react": "^19.2.0" } }, "sha512-UlbRu4cAiGaIewkPyiRGJk0imDN2T3JjieT6spoL2UeSf5od4n5LB/mQ4ejmxhCFT1tYe8IvaFulzynWovsEFQ=="],
+
+
"react-github-calendar": ["react-github-calendar@4.5.11", "", { "dependencies": { "react-activity-calendar": "^2.7.15" }, "peerDependencies": { "react": "^18.0.0 || ^19.0.0" } }, "sha512-tDUjAIYILYtPmPUrA/KKuCcGY9A0PcRQEjnOGcAoqV2qeaibh3IQ+YznQOYr78PsBfLIVtq4nZYYM3QadjGu+Q=="],
+
+
"react-refresh": ["react-refresh@0.17.0", "", {}, "sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ=="],
+
"readdirp": ["readdirp@4.1.2", "", {}, "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg=="],
"regex": ["regex@6.0.1", "", { "dependencies": { "regex-utilities": "^2.3.0" } }, "sha512-uorlqlzAKjKQZ5P+kTJr3eeJGSVroLKoHmquUj4zHWuR+hEyNqlXsSKlYYF5F4NI6nl7tWCs0apKJ0lmfsXAPA=="],
···
"rollup": ["rollup@4.52.5", "", { "dependencies": { "@types/estree": "1.0.8" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.52.5", "@rollup/rollup-android-arm64": "4.52.5", "@rollup/rollup-darwin-arm64": "4.52.5", "@rollup/rollup-darwin-x64": "4.52.5", "@rollup/rollup-freebsd-arm64": "4.52.5", "@rollup/rollup-freebsd-x64": "4.52.5", "@rollup/rollup-linux-arm-gnueabihf": "4.52.5", "@rollup/rollup-linux-arm-musleabihf": "4.52.5", "@rollup/rollup-linux-arm64-gnu": "4.52.5", "@rollup/rollup-linux-arm64-musl": "4.52.5", "@rollup/rollup-linux-loong64-gnu": "4.52.5", "@rollup/rollup-linux-ppc64-gnu": "4.52.5", "@rollup/rollup-linux-riscv64-gnu": "4.52.5", "@rollup/rollup-linux-riscv64-musl": "4.52.5", "@rollup/rollup-linux-s390x-gnu": "4.52.5", "@rollup/rollup-linux-x64-gnu": "4.52.5", "@rollup/rollup-linux-x64-musl": "4.52.5", "@rollup/rollup-openharmony-arm64": "4.52.5", "@rollup/rollup-win32-arm64-msvc": "4.52.5", "@rollup/rollup-win32-ia32-msvc": "4.52.5", "@rollup/rollup-win32-x64-gnu": "4.52.5", "@rollup/rollup-win32-x64-msvc": "4.52.5", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-3GuObel8h7Kqdjt0gxkEzaifHTqLVW56Y/bjN7PSQtkKr0w3V/QYSdt6QWYtd7A1xUtYQigtdUfgj1RvWVtorw=="],
+
"scheduler": ["scheduler@0.27.0", "", {}, "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q=="],
+
"semver": ["semver@7.7.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q=="],
"sharp": ["sharp@0.34.5", "", { "dependencies": { "@img/colour": "^1.0.0", "detect-libc": "^2.1.2", "semver": "^7.7.3" }, "optionalDependencies": { "@img/sharp-darwin-arm64": "0.34.5", "@img/sharp-darwin-x64": "0.34.5", "@img/sharp-libvips-darwin-arm64": "1.2.4", "@img/sharp-libvips-darwin-x64": "1.2.4", "@img/sharp-libvips-linux-arm": "1.2.4", "@img/sharp-libvips-linux-arm64": "1.2.4", "@img/sharp-libvips-linux-ppc64": "1.2.4", "@img/sharp-libvips-linux-riscv64": "1.2.4", "@img/sharp-libvips-linux-s390x": "1.2.4", "@img/sharp-libvips-linux-x64": "1.2.4", "@img/sharp-libvips-linuxmusl-arm64": "1.2.4", "@img/sharp-libvips-linuxmusl-x64": "1.2.4", "@img/sharp-linux-arm": "0.34.5", "@img/sharp-linux-arm64": "0.34.5", "@img/sharp-linux-ppc64": "0.34.5", "@img/sharp-linux-riscv64": "0.34.5", "@img/sharp-linux-s390x": "0.34.5", "@img/sharp-linux-x64": "0.34.5", "@img/sharp-linuxmusl-arm64": "0.34.5", "@img/sharp-linuxmusl-x64": "0.34.5", "@img/sharp-wasm32": "0.34.5", "@img/sharp-win32-arm64": "0.34.5", "@img/sharp-win32-ia32": "0.34.5", "@img/sharp-win32-x64": "0.34.5" } }, "sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg=="],
···
"strip-ansi": ["strip-ansi@7.1.2", "", { "dependencies": { "ansi-regex": "^6.0.1" } }, "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA=="],
+
"tailwindcss": ["tailwindcss@4.1.17", "", {}, "sha512-j9Ee2YjuQqYT9bbRTfTZht9W/ytp5H+jJpZKiYdP/bpnXARAuELt9ofP0lPnmHjbga7SNQIxdTAXCmtKVYjN+Q=="],
+
+
"tapable": ["tapable@2.3.0", "", {}, "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg=="],
+
"tiny-inflate": ["tiny-inflate@1.0.3", "", {}, "sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw=="],
"tinyexec": ["tinyexec@1.0.2", "", {}, "sha512-W/KYk+NFhkmsYpuHq5JykngiOCnxeVL8v8dFnqxSD8qEEdRfXk1SDM6JzNqcERbcGYj9tMrDQBYV9cjgnunFIg=="],
···
"unstorage": ["unstorage@1.17.2", "", { "dependencies": { "anymatch": "^3.1.3", "chokidar": "^4.0.3", "destr": "^2.0.5", "h3": "^1.15.4", "lru-cache": "^10.4.3", "node-fetch-native": "^1.6.7", "ofetch": "^1.5.0", "ufo": "^1.6.1" }, "peerDependencies": { "@azure/app-configuration": "^1.8.0", "@azure/cosmos": "^4.2.0", "@azure/data-tables": "^13.3.0", "@azure/identity": "^4.6.0", "@azure/keyvault-secrets": "^4.9.0", "@azure/storage-blob": "^12.26.0", "@capacitor/preferences": "^6.0.3 || ^7.0.0", "@deno/kv": ">=0.9.0", "@netlify/blobs": "^6.5.0 || ^7.0.0 || ^8.1.0 || ^9.0.0 || ^10.0.0", "@planetscale/database": "^1.19.0", "@upstash/redis": "^1.34.3", "@vercel/blob": ">=0.27.1", "@vercel/functions": "^2.2.12 || ^3.0.0", "@vercel/kv": "^1.0.1", "aws4fetch": "^1.0.20", "db0": ">=0.2.1", "idb-keyval": "^6.2.1", "ioredis": "^5.4.2", "uploadthing": "^7.4.4" }, "optionalPeers": ["@azure/app-configuration", "@azure/cosmos", "@azure/data-tables", "@azure/identity", "@azure/keyvault-secrets", "@azure/storage-blob", "@capacitor/preferences", "@deno/kv", "@netlify/blobs", "@planetscale/database", "@upstash/redis", "@vercel/blob", "@vercel/functions", "@vercel/kv", "aws4fetch", "db0", "idb-keyval", "ioredis", "uploadthing"] }, "sha512-cKEsD6iBWJgOMJ6vW1ID/SYuqNf8oN4yqRk8OYqaVQ3nnkJXOT1PSpaMh2QfzLs78UN5kSNRD2c/mgjT8tX7+w=="],
+
"update-browserslist-db": ["update-browserslist-db@1.1.4", "", { "dependencies": { "escalade": "^3.2.0", "picocolors": "^1.1.1" }, "peerDependencies": { "browserslist": ">= 4.21.0" }, "bin": { "update-browserslist-db": "cli.js" } }, "sha512-q0SPT4xyU84saUX+tomz1WLkxUbuaJnR1xWt17M7fJtEJigJeWUNGUqrauFXsHnqev9y9JTRGwk13tFBuKby4A=="],
+
"vfile": ["vfile@6.0.3", "", { "dependencies": { "@types/unist": "^3.0.0", "vfile-message": "^4.0.0" } }, "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q=="],
"vfile-location": ["vfile-location@5.0.3", "", { "dependencies": { "@types/unist": "^3.0.0", "vfile": "^6.0.0" } }, "sha512-5yXvWDEgqeiYiBe1lbxYF7UMAIm/IcopxMHrMQDq3nvKcjPKIhZklUKL+AE7J7uApI4kwe2snsK+eI6UTj9EHg=="],
···
"xxhash-wasm": ["xxhash-wasm@1.1.0", "", {}, "sha512-147y/6YNh+tlp6nd/2pWq38i9h6mz/EuQ6njIrmW8D1BS5nCqs0P6DG+m6zTGnNz5I+uhZ0SHxBs9BsPrwcKDA=="],
+
"yallist": ["yallist@3.1.1", "", {}, "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="],
+
"yargs-parser": ["yargs-parser@21.1.1", "", {}, "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw=="],
"yocto-queue": ["yocto-queue@1.2.1", "", {}, "sha512-AyeEbWOu/TAXdxlV9wmGcR0+yh2j3vYPGOECcIj2S7MkrLyC7ne+oye2BKTItt0ii2PHk4cDy+95+LshzbXnGg=="],
···
"zod-to-ts": ["zod-to-ts@1.2.0", "", { "peerDependencies": { "typescript": "^4.9.4 || ^5.0.2", "zod": "^3" } }, "sha512-x30XE43V+InwGpvTySRNz9kB7qFU8DlyEy7BsSTCHPH1R0QasMmHWZDCzYm6bVXtj/9NNJAZF3jW8rzFvH5OFA=="],
"zwitch": ["zwitch@2.0.4", "", {}, "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A=="],
+
+
"@babel/core/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="],
+
+
"@babel/helper-compilation-targets/lru-cache": ["lru-cache@5.1.1", "", { "dependencies": { "yallist": "^3.0.2" } }, "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w=="],
+
+
"@babel/helper-compilation-targets/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="],
"@rollup/pluginutils/estree-walker": ["estree-walker@2.0.2", "", {}, "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="],
+
+
"@tailwindcss/oxide-wasm32-wasi/@emnapi/core": ["@emnapi/core@1.7.0", "", { "dependencies": { "@emnapi/wasi-threads": "1.1.0", "tslib": "^2.4.0" }, "bundled": true }, "sha512-pJdKGq/1iquWYtv1RRSljZklxHCOCAJFJrImO5ZLKPJVJlVUcs8yFwNQlqS0Lo8xT1VAXXTCZocF9n26FWEKsw=="],
+
+
"@tailwindcss/oxide-wasm32-wasi/@emnapi/runtime": ["@emnapi/runtime@1.7.0", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-oAYoQnCYaQZKVS53Fq23ceWMRxq5EhQsE0x0RdQ55jT7wagMu5k+fS39v1fiSLrtrLQlXwVINenqhLMtTrV/1Q=="],
+
+
"@tailwindcss/oxide-wasm32-wasi/@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.1.0", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ=="],
+
+
"@tailwindcss/oxide-wasm32-wasi/@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@1.0.7", "", { "dependencies": { "@emnapi/core": "^1.5.0", "@emnapi/runtime": "^1.5.0", "@tybys/wasm-util": "^0.10.1" }, "bundled": true }, "sha512-SeDnOO0Tk7Okiq6DbXmmBODgOAb9dp9gjlphokTUxmt8U3liIP1ZsozBahH69j/RJv+Rfs6IwUKHTgQYJ/HBAw=="],
+
+
"@tailwindcss/oxide-wasm32-wasi/@tybys/wasm-util": ["@tybys/wasm-util@0.10.1", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg=="],
+
+
"@tailwindcss/oxide-wasm32-wasi/tslib": ["tslib@2.8.1", "", { "bundled": true }, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
"ansi-align/string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="],
+14 -1
package.json
···
"astro": "astro"
},
"dependencies": {
-
"astro": "^5.15.4"
+
"@astrojs/react": "^4.4.2",
+
"@lucide/astro": "^0.553.0",
+
"@lucide/lab": "^0.1.2",
+
"@tailwindcss/vite": "^4.1.17",
+
"@types/react": "^19.2.2",
+
"@types/react-dom": "^19.2.2",
+
"astro": "^5.15.4",
+
"react": "^19.2.0",
+
"react-dom": "^19.2.0",
+
"react-github-calendar": "^4.5.11",
+
"tailwindcss": "^4.1.17"
+
},
+
"devDependencies": {
+
"@catppuccin/tailwindcss": "^1.0.0"
}
}
public/banner.png

This is a binary file and will not be displayed.

public/celeste_exhale.mp3

This is a binary file and will not be displayed.

public/doodlecat.png

This is a binary file and will not be displayed.

public/favicon.ico

This is a binary file and will not be displayed.

-9
public/favicon.svg
···
-
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 128 128">
-
<path d="M50.4 78.5a75.1 75.1 0 0 0-28.5 6.9l24.2-65.7c.7-2 1.9-3.2 3.4-3.2h29c1.5 0 2.7 1.2 3.4 3.2l24.2 65.7s-11.6-7-28.5-7L67 45.5c-.4-1.7-1.6-2.8-2.9-2.8-1.3 0-2.5 1.1-2.9 2.7L50.4 78.5Zm-1.1 28.2Zm-4.2-20.2c-2 6.6-.6 15.8 4.2 20.2a17.5 17.5 0 0 1 .2-.7 5.5 5.5 0 0 1 5.7-4.5c2.8.1 4.3 1.5 4.7 4.7.2 1.1.2 2.3.2 3.5v.4c0 2.7.7 5.2 2.2 7.4a13 13 0 0 0 5.7 4.9v-.3l-.2-.3c-1.8-5.6-.5-9.5 4.4-12.8l1.5-1a73 73 0 0 0 3.2-2.2 16 16 0 0 0 6.8-11.4c.3-2 .1-4-.6-6l-.8.6-1.6 1a37 37 0 0 1-22.4 2.7c-5-.7-9.7-2-13.2-6.2Z" />
-
<style>
-
path { fill: #000; }
-
@media (prefers-color-scheme: dark) {
-
path { fill: #FFF; }
-
}
-
</style>
-
</svg>
+1
public/pause.svg
···
+
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="#bac2de" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-pause"><rect x="6" y="4" width="4" height="16"></rect><rect x="14" y="4" width="4" height="16"></rect></svg>
+1
public/play.svg
···
+
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="#bac2de" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-play"><polygon points="5 3 19 12 5 21 5 3"></polygon></svg>
-1
src/assets/astro.svg
···
-
<svg xmlns="http://www.w3.org/2000/svg" fill="none" width="115" height="48"><path fill="#17191E" d="M7.77 36.35C6.4 35.11 6 32.51 6.57 30.62c.99 1.2 2.35 1.57 3.75 1.78 2.18.33 4.31.2 6.33-.78.23-.12.44-.27.7-.42.18.55.23 1.1.17 1.67a4.56 4.56 0 0 1-1.94 3.23c-.43.32-.9.61-1.34.91-1.38.94-1.76 2.03-1.24 3.62l.05.17a3.63 3.63 0 0 1-1.6-1.38 3.87 3.87 0 0 1-.63-2.1c0-.37 0-.74-.05-1.1-.13-.9-.55-1.3-1.33-1.32a1.56 1.56 0 0 0-1.63 1.26c0 .06-.03.12-.05.2Z"/><path fill="url(#a)" d="M7.77 36.35C6.4 35.11 6 32.51 6.57 30.62c.99 1.2 2.35 1.57 3.75 1.78 2.18.33 4.31.2 6.33-.78.23-.12.44-.27.7-.42.18.55.23 1.1.17 1.67a4.56 4.56 0 0 1-1.94 3.23c-.43.32-.9.61-1.34.91-1.38.94-1.76 2.03-1.24 3.62l.05.17a3.63 3.63 0 0 1-1.6-1.38 3.87 3.87 0 0 1-.63-2.1c0-.37 0-.74-.05-1.1-.13-.9-.55-1.3-1.33-1.32a1.56 1.56 0 0 0-1.63 1.26c0 .06-.03.12-.05.2Z"/><path fill="#17191E" d="M.02 30.31s4.02-1.95 8.05-1.95l3.04-9.4c.11-.45.44-.76.82-.76.37 0 .7.31.82.76l3.04 9.4c4.77 0 8.05 1.95 8.05 1.95L17 11.71c-.2-.56-.53-.91-.98-.91H7.83c-.44 0-.76.35-.97.9L.02 30.31Zm42.37-5.97c0 1.64-2.05 2.62-4.88 2.62-1.85 0-2.5-.45-2.5-1.41 0-1 .8-1.49 2.65-1.49 1.67 0 3.09.03 4.73.23v.05Zm.03-2.04a21.37 21.37 0 0 0-4.37-.36c-5.32 0-7.82 1.25-7.82 4.18 0 3.04 1.71 4.2 5.68 4.2 3.35 0 5.63-.84 6.46-2.92h.14c-.03.5-.05 1-.05 1.4 0 1.07.18 1.16 1.06 1.16h4.15a16.9 16.9 0 0 1-.36-4c0-1.67.06-2.93.06-4.62 0-3.45-2.07-5.64-8.56-5.64-2.8 0-5.9.48-8.26 1.19.22.93.54 2.83.7 4.06 2.04-.96 4.95-1.37 7.2-1.37 3.11 0 3.97.71 3.97 2.15v.57Zm11.37 3c-.56.07-1.33.07-2.12.07-.83 0-1.6-.03-2.12-.1l-.02.58c0 2.85 1.87 4.52 8.45 4.52 6.2 0 8.2-1.64 8.2-4.55 0-2.74-1.33-4.09-7.2-4.39-4.58-.2-4.99-.7-4.99-1.28 0-.66.59-1 3.65-1 3.18 0 4.03.43 4.03 1.35v.2a46.13 46.13 0 0 1 4.24.03l.02-.55c0-3.36-2.8-4.46-8.2-4.46-6.08 0-8.13 1.49-8.13 4.39 0 2.6 1.64 4.23 7.48 4.48 4.3.14 4.77.62 4.77 1.28 0 .7-.7 1.03-3.71 1.03-3.47 0-4.35-.48-4.35-1.47v-.13Zm19.82-12.05a17.5 17.5 0 0 1-6.24 3.48c.03.84.03 2.4.03 3.24l1.5.02c-.02 1.63-.04 3.6-.04 4.9 0 3.04 1.6 5.32 6.58 5.32 2.1 0 3.5-.23 5.23-.6a43.77 43.77 0 0 1-.46-4.13c-1.03.34-2.34.53-3.78.53-2 0-2.82-.55-2.82-2.13 0-1.37 0-2.65.03-3.84 2.57.02 5.13.07 6.64.11-.02-1.18.03-2.9.1-4.04-2.2.04-4.65.07-6.68.07l.07-2.93h-.16Zm13.46 6.04a767.33 767.33 0 0 1 .07-3.18H82.6c.07 1.96.07 3.98.07 6.92 0 2.95-.03 4.99-.07 6.93h5.18c-.09-1.37-.11-3.68-.11-5.65 0-3.1 1.26-4 4.12-4 1.33 0 2.28.16 3.1.46.03-1.16.26-3.43.4-4.43-.86-.25-1.81-.41-2.96-.41-2.46-.03-4.26.98-5.1 3.38l-.17-.02Zm22.55 3.65c0 2.5-1.8 3.66-4.64 3.66-2.81 0-4.61-1.1-4.61-3.66s1.82-3.52 4.61-3.52c2.82 0 4.64 1.03 4.64 3.52Zm4.71-.11c0-4.96-3.87-7.18-9.35-7.18-5.5 0-9.23 2.22-9.23 7.18 0 4.94 3.49 7.59 9.21 7.59 5.77 0 9.37-2.65 9.37-7.6Z"/><defs><linearGradient id="a" x1="6.33" x2="19.43" y1="40.8" y2="34.6" gradientUnits="userSpaceOnUse"><stop stop-color="#D83333"/><stop offset="1" stop-color="#F041FF"/></linearGradient></defs></svg>
-1
src/assets/background.svg
···
-
<svg xmlns="http://www.w3.org/2000/svg" width="1440" height="1024" fill="none"><path fill="url(#a)" fill-rule="evenodd" d="M-217.58 475.75c91.82-72.02 225.52-29.38 341.2-44.74C240 415.56 372.33 315.14 466.77 384.9c102.9 76.02 44.74 246.76 90.31 366.31 29.83 78.24 90.48 136.14 129.48 210.23 57.92 109.99 169.67 208.23 155.9 331.77-13.52 121.26-103.42 264.33-224.23 281.37-141.96 20.03-232.72-220.96-374.06-196.99-151.7 25.73-172.68 330.24-325.85 315.72-128.6-12.2-110.9-230.73-128.15-358.76-12.16-90.14 65.87-176.25 44.1-264.57-26.42-107.2-167.12-163.46-176.72-273.45-10.15-116.29 33.01-248.75 124.87-320.79Z" clip-rule="evenodd" style="opacity:.154"/><path fill="url(#b)" fill-rule="evenodd" d="M1103.43 115.43c146.42-19.45 275.33-155.84 413.5-103.59 188.09 71.13 409 212.64 407.06 413.88-1.94 201.25-259.28 278.6-414.96 405.96-130 106.35-240.24 294.39-405.6 265.3-163.7-28.8-161.93-274.12-284.34-386.66-134.95-124.06-436-101.46-445.82-284.6-9.68-180.38 247.41-246.3 413.54-316.9 101.01-42.93 207.83 21.06 316.62 6.61Z" clip-rule="evenodd" style="opacity:.154"/><defs><linearGradient id="b" x1="373" x2="1995.44" y1="1100" y2="118.03" gradientUnits="userSpaceOnUse"><stop stop-color="#D83333"/><stop offset="1" stop-color="#F041FF"/></linearGradient><linearGradient id="a" x1="107.37" x2="1130.66" y1="1993.35" y2="1026.31" gradientUnits="userSpaceOnUse"><stop stop-color="#3245FF"/><stop offset="1" stop-color="#BC52EE"/></linearGradient></defs></svg>
+1
src/assets/butterfly.svg
···
+
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-butterfly-icon lucide-butterfly"><path d="M15.8 2C12 3.8 12 9 12 9s0-5.2-3.8-7"/><path d="M12 9v11"/><path d="M20 5c-3.5 0-6.5 3.9-8 6.3C10.5 8.9 7.5 5 4 5a2 2 0 0 0-2 2c0 2.3.6 4.4 1.5 5.6C4 13.5 4.9 14 6 14h2c-.9.4-2.1.9-2.6 1.5-1.6 1.6-.9 3.4.7 4.9 1.6 1.6 3.4 2.3 4.9.7.3-.3 1-1.1 1-1.1s.6.8 1 1.1c1.6 1.6 3.4.9 4.9-.7 1.6-1.6 2.3-3.4.7-4.9-.5-.5-1.7-1.1-2.6-1.5h2c1.1 0 2-.5 2.5-1.4.9-1.2 1.5-3.3 1.5-5.6a2 2 0 0 0-2-2"/></svg>
+34
src/components/Badgebar.astro
···
+
---
+
import LucideIcon from "./LucideIcon.astro";
+
+
interface Badge {
+
icon: string | any,
+
href: string
+
color: string
+
svg?: boolean
+
}
+
+
interface Props {
+
badges: Badge[]
+
size: string
+
}
+
+
const { badges, size } = Astro.props
+
+
---
+
<span class="flex gap-2 bg-ctp-crust p-2 pl-3 pr-3 rounded-full h-min">
+
{badges.map(badge =>
+
<a href=`${badge.href}` target="_blank" rel="noopener noreferrer">
+
{ badge.svg && badge.icon && (
+
<badge.icon width={size} height={size} style={`stroke:${badge.color}`}
+
class="hover:rotate-15 hover:scale-110 ease-in hover:ease-out transition-transform active:scale-80"
+
/>
+
)}
+
{ !badge.svg && (
+
<LucideIcon name=`${badge.icon}` width=`${size}` height=`${size}` style={`stroke:${badge.color}`}
+
class="hover:rotate-15 hover:scale-110 ease-in hover:ease-out transition-transform active:scale-80"
+
/>
+
)}
+
</a>
+
)}
+
</span>
+21
src/components/Footer.astro
···
+
---
+
import { Heart, Rocket, Copyright, Code } from "@lucide/astro"
+
---
+
<div class="flex justify-between bg-ctp-base p-6 pl-12 pr-12">
+
<span class="inline-flex gap-2 items-center">
+
Copyright
+
<Copyright size="20" class="stroke-ctp-text"/>
+
2026 Banana
+
</span>
+
<span class="inline-flex gap-2 items-center">
+
<a href="https://tangled.org/@banana.tngl.sh/mywebsite-2026"
+
class="text-xs text-ctp-overlay0 flex gap-1 hover:underline"><Code size="16" />src</a>
+
+
</span>
+
<span class="inline-flex gap-2 items-center">
+
Made with
+
<Heart size="20" class="stroke-ctp-red"/>
+
using Astro
+
<Rocket size="20" class="stroke-ctp-lavender"/>
+
</span>
+
</div>
+28
src/components/GithubCalendar.jsx
···
+
import React from 'react';
+
+
export default function GitHubWrapper({ username, ...props }) {
+
const [GitHubCalendar, setGitHubCalendar] = React.useState(null);
+
+
const theme = {
+
dark: [
+
'var(--catppuccin-color-crust)',
+
'var(--catppuccin-color-green-900)',
+
'var(--catppuccin-color-green-500)',
+
'var(--catppuccin-color-green-200)',
+
'var(--catppuccin-color-green-50)',
+
],
+
};
+
React.useEffect(() => {
+
import('react-github-calendar').then((module) => {
+
setGitHubCalendar(() => module.default);
+
});
+
}, []);
+
+
if (!GitHubCalendar) {
+
return <div>Loading GitHub calendar...</div>;
+
}
+
+
return <GitHubCalendar username={username} theme={theme}
+
blockMargin={3} blockRadius={1} blockSize={10}
+
{...props} />;
+
}
+12
src/components/Label.astro
···
+
---
+
interface Props {
+
name: string;
+
}
+
+
const { name } = Astro.props;
+
---
+
+
<span
+
class=`absolute top-[-0.5rem] left-3 text-xs text-ctp-overlay1 bg-ctp-mantle pl-2 pr-2`
+
>{name}</span
+
>
+12
src/components/LucideIcon.astro
···
+
---
+
import { icons, type IconProps } from '@lucide/astro';
+
+
interface Props extends IconProps {
+
name: keyof typeof icons;
+
}
+
+
const { name, ...restProps } = Astro.props;
+
const Icon = icons[name];
+
---
+
+
<Icon {...restProps} />
+79
src/components/PortfolioItem.astro
···
+
---
+
interface Badge {
+
icon: string,
+
href: string
+
color: string
+
}
+
+
interface Props {
+
type: string
+
icon?: string,
+
title: string,
+
subtitle: string,
+
tag?: string,
+
tagcolor?: string,
+
href: string
+
badges?: Badge[]
+
}
+
+
const { type, icon = "Box", title, subtitle, tag, tagcolor, href, badges } = Astro.props
+
+
var color = "--catppuccin-color-yellow"
+
if (type=="project") {
+
color = "--catppuccin-color-red"
+
} else if (type=="repo") {
+
color = "--catppuccin-color-peach"
+
} else if (type=="team") {
+
color = "--catppuccin-color-mauve"
+
} else if (type=="misc") {
+
color = "--catppuccin-color-maroon"
+
} else if (type=="freelance") {
+
color = "--catppuccin-color-sky"
+
}
+
const colorCss = "var(" + color + ")"
+
+
var iconName = icon
+
if (iconName == "Box") {
+
if (type=="project") {
+
iconName = "Archive"
+
} else if (type=="repo") {
+
iconName = "BookMarked"
+
} else if (type=="team") {
+
iconName = "Users"
+
} else if (type=="misc") {
+
iconName = "Box"
+
} else if (type=="freelance") {
+
iconName = "ReceiptText"
+
}
+
}
+
+
import LucideIcon from "./LucideIcon.astro"
+
import Badgebar from "./Badgebar.astro"
+
import Tag from "./Tag.astro"
+
---
+
<div class="p-4 border border-ctp-surface0 flex flex-col -mt-px w-full">
+
<div class="flex flex-wrap sm:flex-nowrap justify-between gap-2 sm:gap-4">
+
<a href=`${href}` class="flex flex-col gap-1 group">
+
<span class="text-xl flex gap-2 items-center">
+
<LucideIcon name=`${iconName}` width="20" height="20" style={`stroke:${colorCss}`} />
+
<span class="group-hover:underline font-bold">{title} </span>
+
<span class="hidden md:flex items-center">
+
{tag && tagcolor && (
+
<Tag text={tag} color={tagcolor}/>
+
)}
+
</span>
+
</span>
+
<span class="text-sm">
+
<span class="flex gap-1">{subtitle}</span>
+
</span>
+
</a>
+
<span>
+
{ badges && (
+
<Badgebar badges={badges} size="20"/>
+
)}
+
</span>
+
</div>
+
<div>
+
<slot/>
+
</div>
+
</div>
+13
src/components/Tag.astro
···
+
---
+
interface Props {
+
text: string
+
color: string
+
}
+
+
const { text, color } = Astro.props
+
const colorCss = "var(" + color + "-700)"
+
---
+
<span class="p-1 pl-2 pr-2 text-xs rounded-full font-bold bg-ctp-base border border-ctp-surface0"
+
style={`color:${colorCss};`}>
+
{text}
+
</span>
-210
src/components/Welcome.astro
···
-
---
-
import astroLogo from '../assets/astro.svg';
-
import background from '../assets/background.svg';
-
---
-
-
<div id="container">
-
<img id="background" src={background.src} alt="" fetchpriority="high" />
-
<main>
-
<section id="hero">
-
<a href="https://astro.build"
-
><img src={astroLogo.src} width="115" height="48" alt="Astro Homepage" /></a
-
>
-
<h1>
-
To get started, open the <code><pre>src/pages</pre></code> directory in your project.
-
</h1>
-
<section id="links">
-
<a class="button" href="https://docs.astro.build">Read our docs</a>
-
<a href="https://astro.build/chat"
-
>Join our Discord <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 127.14 96.36"
-
><path
-
fill="currentColor"
-
d="M107.7 8.07A105.15 105.15 0 0 0 81.47 0a72.06 72.06 0 0 0-3.36 6.83 97.68 97.68 0 0 0-29.11 0A72.37 72.37 0 0 0 45.64 0a105.89 105.89 0 0 0-26.25 8.09C2.79 32.65-1.71 56.6.54 80.21a105.73 105.73 0 0 0 32.17 16.15 77.7 77.7 0 0 0 6.89-11.11 68.42 68.42 0 0 1-10.85-5.18c.91-.66 1.8-1.34 2.66-2a75.57 75.57 0 0 0 64.32 0c.87.71 1.76 1.39 2.66 2a68.68 68.68 0 0 1-10.87 5.19 77 77 0 0 0 6.89 11.1 105.25 105.25 0 0 0 32.19-16.14c2.64-27.38-4.51-51.11-18.9-72.15ZM42.45 65.69C36.18 65.69 31 60 31 53s5-12.74 11.43-12.74S54 46 53.89 53s-5.05 12.69-11.44 12.69Zm42.24 0C78.41 65.69 73.25 60 73.25 53s5-12.74 11.44-12.74S96.23 46 96.12 53s-5.04 12.69-11.43 12.69Z"
-
></path></svg
-
>
-
</a>
-
</section>
-
</section>
-
</main>
-
-
<a href="https://astro.build/blog/astro-5/" id="news" class="box">
-
<svg width="32" height="32" fill="none" xmlns="http://www.w3.org/2000/svg"
-
><path
-
d="M24.667 12c1.333 1.414 2 3.192 2 5.334 0 4.62-4.934 5.7-7.334 12C18.444 28.567 18 27.456 18 26c0-4.642 6.667-7.053 6.667-14Zm-5.334-5.333c1.6 1.65 2.4 3.43 2.4 5.333 0 6.602-8.06 7.59-6.4 17.334C13.111 27.787 12 25.564 12 22.666c0-4.434 7.333-8 7.333-16Zm-6-5.333C15.111 3.555 16 5.556 16 7.333c0 8.333-11.333 10.962-5.333 22-3.488-.774-6-4-6-8 0-8.667 8.666-10 8.666-20Z"
-
fill="#111827"></path></svg
-
>
-
<h2>What's New in Astro 5.0?</h2>
-
<p>
-
From content layers to server islands, click to learn more about the new features and
-
improvements in Astro 5.0
-
</p>
-
</a>
-
</div>
-
-
<style>
-
#background {
-
position: fixed;
-
top: 0;
-
left: 0;
-
width: 100%;
-
height: 100%;
-
z-index: -1;
-
filter: blur(100px);
-
}
-
-
#container {
-
font-family: Inter, Roboto, 'Helvetica Neue', 'Arial Nova', 'Nimbus Sans', Arial, sans-serif;
-
height: 100%;
-
}
-
-
main {
-
height: 100%;
-
display: flex;
-
justify-content: center;
-
}
-
-
#hero {
-
display: flex;
-
align-items: start;
-
flex-direction: column;
-
justify-content: center;
-
padding: 16px;
-
}
-
-
h1 {
-
font-size: 22px;
-
margin-top: 0.25em;
-
}
-
-
#links {
-
display: flex;
-
gap: 16px;
-
}
-
-
#links a {
-
display: flex;
-
align-items: center;
-
padding: 10px 12px;
-
color: #111827;
-
text-decoration: none;
-
transition: color 0.2s;
-
}
-
-
#links a:hover {
-
color: rgb(78, 80, 86);
-
}
-
-
#links a svg {
-
height: 1em;
-
margin-left: 8px;
-
}
-
-
#links a.button {
-
color: white;
-
background: linear-gradient(83.21deg, #3245ff 0%, #bc52ee 100%);
-
box-shadow:
-
inset 0 0 0 1px rgba(255, 255, 255, 0.12),
-
inset 0 -2px 0 rgba(0, 0, 0, 0.24);
-
border-radius: 10px;
-
}
-
-
#links a.button:hover {
-
color: rgb(230, 230, 230);
-
box-shadow: none;
-
}
-
-
pre {
-
font-family:
-
ui-monospace, 'Cascadia Code', 'Source Code Pro', Menlo, Consolas, 'DejaVu Sans Mono',
-
monospace;
-
font-weight: normal;
-
background: linear-gradient(14deg, #d83333 0%, #f041ff 100%);
-
-webkit-background-clip: text;
-
-webkit-text-fill-color: transparent;
-
background-clip: text;
-
margin: 0;
-
}
-
-
h2 {
-
margin: 0 0 1em;
-
font-weight: normal;
-
color: #111827;
-
font-size: 20px;
-
}
-
-
p {
-
color: #4b5563;
-
font-size: 16px;
-
line-height: 24px;
-
letter-spacing: -0.006em;
-
margin: 0;
-
}
-
-
code {
-
display: inline-block;
-
background:
-
linear-gradient(66.77deg, #f3cddd 0%, #f5cee7 100%) padding-box,
-
linear-gradient(155deg, #d83333 0%, #f041ff 18%, #f5cee7 45%) border-box;
-
border-radius: 8px;
-
border: 1px solid transparent;
-
padding: 6px 8px;
-
}
-
-
.box {
-
padding: 16px;
-
background: rgba(255, 255, 255, 1);
-
border-radius: 16px;
-
border: 1px solid white;
-
}
-
-
#news {
-
position: absolute;
-
bottom: 16px;
-
right: 16px;
-
max-width: 300px;
-
text-decoration: none;
-
transition: background 0.2s;
-
backdrop-filter: blur(50px);
-
}
-
-
#news:hover {
-
background: rgba(255, 255, 255, 0.55);
-
}
-
-
@media screen and (max-height: 368px) {
-
#news {
-
display: none;
-
}
-
}
-
-
@media screen and (max-width: 768px) {
-
#container {
-
display: flex;
-
flex-direction: column;
-
}
-
-
#hero {
-
display: block;
-
padding-top: 10%;
-
}
-
-
#links {
-
flex-wrap: wrap;
-
}
-
-
#links a.button {
-
padding: 14px 18px;
-
}
-
-
#news {
-
right: 16px;
-
left: 16px;
-
bottom: 2.5rem;
-
max-width: 100%;
-
}
-
-
h1 {
-
line-height: 1.5;
-
}
-
}
-
</style>
+27
src/components/navbar/Navbar.astro
···
+
---
+
import Btn from "./NavbarLink.astro"
+
+
let href = Astro.url.toString()
+
href = href.replace(Astro.url.host.toString(), "")
+
href = href.replace("https://", "")
+
href = href.replace("http://", "")
+
---
+
<div class="fixed z-40 bg-ctp-base
+
left-[2%] right-[2%] md:left-[4%] md:right-[4%] xl:left-[8%] xl:right-[8%]
+
pl-8 pr-8 pt-4 pb-4 flex justify-between rounded-bl-2xl rounded-br-2xl squircle">
+
<div class="flex gap-4 items-center">
+
<span class="flex flex-col">
+
<span>~/banana{href}</span>
+
</span>
+
</div>
+
<div class="flex gap-6 items-center">
+
<Btn page="home"/>
+
<Btn page="projects"/>
+
</div>
+
</div>
+
<style>
+
@reference "../../styles/global.css"
+
a {
+
@apply ;
+
}
+
</style>
+21
src/components/navbar/NavbarLink.astro
···
+
---
+
interface Props {
+
page: String;
+
}
+
const {page} = Astro.props
+
var href = page
+
if (href == "home") {
+
href = ""
+
}
+
---
+
<a
+
href=`/${href}`
+
class="font-bold
+
text-ctp-yellow hover:text-ctp-blue
+
hover:underline
+
ease-in hover:ease-out transition-all
+
">{page}</a>
+
+
+
+
+34
src/components/projects/BiomeBattle.astro
···
+
---
+
import Item from "../PortfolioItem.astro"
+
---
+
<Item
+
type="freelance"
+
title="BiomeBattle"
+
subtitle="A modern Minecraft creator event. As a developer, I helped with minor improvements to the cosmetics system."
+
icon="Earth"
+
href="https://biomebattle.xyz/"
+
tag="Java"
+
tagcolor="--catppuccin-color-teal"
+
badges={[
+
{
+
icon: "Bird",
+
href: "https://x.com/biomebattle",
+
color: "var(--catppuccin-color-sapphire)"
+
},
+
{
+
icon: "Github",
+
href: "https://github.com/biomebattle",
+
color: "var(--catppuccin-color-green)"
+
},
+
{
+
icon: "MessageCircle",
+
href: "https://biomebattle.xyz/discord",
+
color: "var(--catppuccin-color-blue)"
+
},
+
{
+
icon: "Youtube",
+
href: "https://youtube.com/@BiomeBattle",
+
color: "var(--catppuccin-color-red)"
+
},
+
]}
+
/>
+24
src/components/projects/Dotfiles.astro
···
+
---
+
import Item from "../PortfolioItem.astro"
+
export const priority = 1;
+
---
+
<Item
+
type="repo"
+
title="dotfiles"
+
subtitle="My personal configuration dotfiles for endeavouros linux."
+
href="https://tangled.org/@banana.tngl.sh/dotfiles"
+
badges={[
+
{
+
icon: "Github",
+
href: "https://github.com/imabanana80/dotfiles",
+
color: "var(--catppuccin-color-green)"
+
},
+
+
{
+
icon: "Book",
+
href: "https://wiki.archlinux.org/title/Dotfiles",
+
color: "var(--catppuccin-color-sapphire)"
+
},
+
]}
+
/>
+
+28
src/components/projects/IsleStats.astro
···
+
---
+
import Item from "../PortfolioItem.astro"
+
---
+
<Item
+
type="project"
+
title="IsleStats"
+
subtitle="An MCC Island Discord statistics bot that renders beautiful stat cards to show off your stats."
+
href="https://islestats.net"
+
tag="Python"
+
tagcolor="--catppuccin-color-blue"
+
badges={[
+
{
+
icon: "Github",
+
href: "https://github.com/islestats",
+
color: "var(--catppuccin-color-green)"
+
},
+
{
+
icon: "MessageCircle",
+
href: "https://discord.gg//islestats",
+
color: "var(--catppuccin-color-blue)"
+
},
+
{
+
icon: "Mail",
+
href: "mailto:contact@islestats.net",
+
color: "var(--catppuccin-color-maroon)"
+
}
+
]}
+
/>
+24
src/components/projects/MyWebsite2026.astro
···
+
---
+
import Item from "../PortfolioItem.astro"
+
---
+
<Item
+
type="repo"
+
title="my-website-2026"
+
subtitle="My portfolio website for the year 2026 built with Astro. This is the current website you're on."
+
href="https://beta.imabanana80.com/"
+
tag="Astro"
+
tagcolor="--catppuccin-color-pink"
+
badges={[
+
{
+
icon: "Spool",
+
href: "https://tangled.org/@banana.tngl.sh/mywebsite-2026",
+
color: "var(--catppuccin-color-lavender)"
+
},
+
{
+
icon: "Github",
+
href: "https://github.com/imabanana80/mywebsite-2026",
+
color: "var(--catppuccin-color-green)"
+
},
+
]}
+
/>
+
+18
src/components/projects/PassgenAstro.astro
···
+
---
+
import Item from "../PortfolioItem.astro"
+
---
+
<Item
+
type="repo"
+
title="passgen-astro"
+
subtitle="Static client-based password phrase generator built with astro."
+
href="https://pass.imabanana80.com"
+
tag="Astro"
+
tagcolor="--catppuccin-color-pink"
+
badges={[
+
{
+
icon: "Github",
+
href: "https://github.com/imabanana80/passgen-astro",
+
color: "var(--catppuccin-color-green)"
+
},
+
]}
+
/>
+29
src/components/projects/PotassiumSh.astro
···
+
---
+
import Item from "../PortfolioItem.astro"
+
export const priority = 2;
+
---
+
<Item
+
type="team"
+
title="potassium.sh"
+
subtitle="An indie software development studio for the creative and insane, founded by me, with some friends!"
+
href="https://potassium.sh"
+
tag="Founder"
+
tagcolor="--catppuccin-color-rosewater"
+
badges={[
+
{
+
icon: "Mail",
+
href: "mailto:team@potassium.sh",
+
color: "var(--catppuccin-color-maroon)"
+
},
+
{
+
icon: "Spool",
+
href: "https://tangled.org/@potassium.sh",
+
color: "var(--catppuccin-color-lavender)"
+
},
+
{
+
icon: "Bird",
+
href: "https://bsky.app/profile/potassium.sh",
+
color: "var(--catppuccin-color-sapphire)"
+
},
+
]}
+
/>
+18
src/components/projects/SMPSales.astro
···
+
---
+
import Item from "../PortfolioItem.astro"
+
---
+
<Item
+
type="team"
+
title="SMP Sales"
+
subtitle="A Minecraft SMP freelancing hub, from developers to artists, all you'll need to start an SMP of your own."
+
href="https://discord.gg/DUa3asXpvs"
+
tag="Developer"
+
tagcolor="--catppuccin-color-rosewater"
+
badges={[
+
{
+
icon: "Github",
+
href: "https://github.com/smpsales",
+
color: "var(--catppuccin-color-green)"
+
},
+
]}
+
/>
+11
src/components/projects/StatusPage.astro
···
+
---
+
import Item from "../PortfolioItem.astro"
+
---
+
<Item
+
type="project"
+
title="Status Page"
+
subtitle="A custom status page design that could automatically fetch data from a custom api to display live information."
+
href="https://status.imabanana80.com"
+
tag="Astro"
+
tagcolor="--catppuccin-color-pink"
+
/>
+9
src/components/section/Contributions.astro
···
+
---
+
import Label from "../Label.astro"
+
import GitHubCalendar from "../GithubCalendar"
+
---
+
+
<div class="flex flex-col p-8 border-ctp-surface0 border w-full h-min relative">
+
<Label name="Contributions"/>
+
<GitHubCalendar client:load username="imabanana80"/>
+
</div>
+62
src/components/section/MusicPlayer.astro
···
+
---
+
import Label from "../Label.astro"
+
import { Disc } from "@lucide/astro"
+
---
+
<div class="border border-ctp-surface0 p-8 pt-6 pb-6 relative">
+
<Label name="Music Player" />
+
<div id="music">
+
<audio
+
id="audio"
+
controls
+
src="/celeste_exhale.mp3"
+
class="hidden"
+
></audio>
+
<div class="mb-1">
+
<span class="text-base flex gap-2 items-center w-fit">
+
<Disc size="20" class="stroke-ctp-pink"/>
+
Celeste - Exhale
+
<span class="text-sm text-ctp-overlay0">by Lena Raine</span>
+
</span>
+
</div>
+
<div id="controls" class="flex gap-1">
+
<button id="control-button" class=""><img id="control-img" src="/play.svg"></button>
+
<div id="progress-bar" class="self-center border border-ctp-surface1 w-full h-1">
+
<div id="progress" class="bg-ctp-subtext0 h-[0.25rem] w-0"></div>
+
</div>
+
</div>
+
</div>
+
</div>
+
<script>
+
const controlButton = document.getElementById("control-button") as HTMLElement
+
const controlImg = document.getElementById("control-img") as HTMLImageElement
+
const audio = document.getElementById("audio") as HTMLAudioElement
+
const progressBar = document.getElementById("progress-bar") as HTMLElement
+
const progress = document.getElementById("progress") as HTMLElement
+
+
controlButton.addEventListener("click", () => {
+
if (audio.paused) {
+
audio.play();
+
controlImg.src = "/pause.svg"
+
} else {
+
audio.pause();
+
controlImg.src = "/play.svg"
+
}
+
});
+
+
audio.addEventListener("timeupdate", () => {
+
progress.style.width = `${(audio.currentTime / audio.duration) * 100}%`;
+
});
+
+
audio.addEventListener("ended", () => {
+
audio.currentTime = 0;
+
progress.style.width = "0%";
+
audio.play();
+
});
+
+
progressBar.addEventListener("click", (e) => {
+
const clickPosition =
+
(e.offsetX / progressBar.clientWidth) * audio.duration;
+
audio.currentTime = clickPosition;
+
});
+
</script>
+
+15
src/components/section/Pinned.astro
···
+
---
+
import Label from "../Label.astro"
+
import Dotfiles from "../projects/Dotfiles.astro"
+
import IsleStats from "../projects/IsleStats.astro"
+
import Potassium from "../projects/PotassiumSh.astro"
+
---
+
+
<div class="flex flex-col p-8 border-ctp-surface0 border w-full h-min relative">
+
<Label name="Pinned"/>
+
<div class="flex flex-wrap">
+
<IsleStats/>
+
<Potassium />
+
<Dotfiles />
+
</div>
+
</div>
+102
src/components/section/Profile.astro
···
+
---
+
import Label from '../Label.astro';
+
import Quote from './Quote.astro'
+
import BadgeBar from "../Badgebar.astro"
+
import Butterfly from "../../assets/butterfly.svg"
+
+
let home = "hidden lg:flex"
+
if (Astro.url.pathname == "/") {
+
home = "flex"
+
}
+
---
+
<div class=`${home} flex-col md:col-span-2 border border-ctp-surface0 gap-[-1px] w-full h-min`>
+
<span class="p-4 pb-0 border-b border-ctp-surface0 relative">
+
<img src="/banner.png" class="w-full"/>
+
</span>
+
<div class="p-8 pt-12 flex-col flex flex-wrap relative">
+
<img src="/doodlecat.png" width="96px" height="96px"
+
class="rounded-full absolute -top-12 left-8 border-6 border-ctp-mantle" />
+
<span class="text-base flex justify-between w-full flex-wrap gap-2">
+
<span class="flex flex-col">
+
<span class="text-2xl font-bold">Banana</span>
+
<a href="mailto:banana@potassium.sh" class="hover:underline ease-in hover:ease-out transition-all">
+
banana@potassium.sh</a>
+
</span>
+
<BadgeBar
+
badges={[
+
{
+
icon: "Github",
+
color: "var(--catppuccin-color-green)",
+
href: "https://github.com/imabanana80"
+
},
+
{
+
icon: "Spool",
+
color: "var(--catppuccin-color-lavender)",
+
href: "https://tangled.org/@banana.tngl.sh"
+
},
+
{
+
icon: Butterfly,
+
color: "var(--catppuccin-color-sapphire)",
+
href: "https://bsky.app/profile/imabanana80.com",
+
svg: true
+
}
+
]}
+
size='20'
+
/>
+
</span>
+
<span class="relative p-3 mt-4 border border-ctp-surface0 text-sm">
+
<Label name="Currently"/>
+
Switching to endeavoros | Open for Hire
+
</span>
+
<span class="relative p-3 mt-4 border border-ctp-surface0 text-sm">
+
<Label name="About"/>
+
Hi, I'm Banana, a computer science student and software developer that specialises in
+
Web Development as well as developing and hosting Minecraft Events.
+
</span>
+
<span class="relative p-3 mt-4 border border-ctp-surface0 text-ctp-subtext0 text-sm">
+
<Label name="Time"/>
+
<span id="clock" class="text-ctp-text"></span> (SGT/UTC+8)
+
</span>
+
<span class="relative p-3 mt-4 border border-ctp-surface0 text-sm">
+
<Label name="Languages"/>
+
<span>Java, Python, Golang, HTML/CSS/TS</span>
+
</span>
+
<span class="relative p-3 -mt-px border border-ctp-surface0 text-sm">
+
<Label name="Frameworks"/>
+
<span>PaperMC, Astro, Tailwindcss</span>
+
</span>
+
<span class="relative p-3 -mt-px border border-ctp-surface0 text-sm">
+
<Label name="Tools"/>
+
<span>Neovim, IntellIJ, Figma, VSC*de</span>
+
</span>
+
<div class="mt-4 flex">
+
<Quote />
+
</div>
+
</div >
+
</div>
+
+
+
<script>
+
const clockElement: HTMLElement | null = document.getElementById("clock");
+
+
if (!clockElement) {
+
console.error(`Error: Clock element with ID "clock" not found.`);
+
}
+
+
const displayTime = (): void => {
+
const now: Date = new Date();
+
+
const options: Intl.DateTimeFormatOptions = {
+
hour: '2-digit',
+
minute: '2-digit',
+
second: '2-digit',
+
hour12: false,
+
timeZone: "Asia/Singapore"
+
};
+
+
const timeString: string = now.toLocaleTimeString('en-US', options);
+
clockElement.textContent = timeString;
+
};
+
displayTime();
+
setInterval(displayTime, 1000);
+
</script>
+19
src/components/section/Projects.astro
···
+
---
+
import Label from "../Label.astro"
+
let projects = Object.values(import.meta.glob('../projects/*.astro', { eager: true }));
+
+
projects = projects.sort((a, b) => {
+
const projectA = a.priority ?? Infinity;
+
const projectB = b.priority ?? Infinity;
+
+
return projectA - projectB
+
})
+
---
+
<div class="flex flex-col p-8 border-ctp-surface0 border w-full h-min relative">
+
<Label name="Projects"/>
+
<div class="flex flex-wrap gap-4">
+
{projects.map(Project => (
+
<Project.default />
+
))}
+
</div>
+
</div>
+35
src/components/section/Quote.astro
···
+
---
+
import Label from "../Label.astro"
+
---
+
<script>
+
interface Quote {
+
quote: string,
+
quotee: string,
+
}
+
const quoteElement = document.getElementById("quote") as HTMLElement
+
const quoteeElement = document.getElementById("quotee") as HTMLElement
+
+
const quotes: Quote[] = [
+
{ quote: "America is a nation that can be defined in a single word: asufutimaehaehfutbw", quotee: "Joseph Robinette Biden Jr."},
+
{ quote: "What if they- what if anything- what if a bomb drops on your head right now?", quotee: "Donald John Trump"},
+
{ quote: "This is a tough hurricane. One of the wettest we've ever seen from the standpoint of water.", quotee: "Donald John Trump"},
+
{ quote: "Heh heh heh, oh it's focused. I say it's err- I think it's- I- I- I haven't-- look.", quotee: "Joseph Robinette Biden Jr."},
+
{ quote: "the color orange is named after the fruit", quotee: "Elon Reeve Musk" },
+
{ quote: "I'm excited about electric school busses, I love electric school busses, I just love them..", quotee: "Kamala Devi Harris"},
+
{ quote: "How dare we speak marry christmas! How dare we!", quotee: "Kamala Devi Harris"},
+
{ quote: "One thing that really encourages me is AI. I love AI. I love ChatGPT. I love it. ChatGPT is frankly fantastic.", quotee: "Alexander Boris de Pfeffel Johnson" },
+
{ quote: "I am a fighter and not a quitter!", quotee: "Elizabeth Mary Truss" },
+
{ quote: "I call again for an immediate ceasefire in Gaza, the return of the sausages- the hostages..", quotee: "Keir Rodney Starmer" },
+
]
+
const quote: Quote = quotes[Math.floor(Math.random()*quotes.length)]
+
+
quoteElement.textContent = '"' + quote.quote + '"'
+
quoteeElement.textContent = "- " + quote.quotee
+
</script>
+
<span class="relative p-3 -mt-px border border-ctp-surface0 text-sm w-full">
+
<Label name="Quote"/>
+
<div class="flex flex-col text-sm gap-1">
+
<span id="quote" class="italic"></span>
+
<span id="quotee" class="w-full text-right"></span>
+
</div>
+
</span>
+18 -5
src/layouts/Layout.astro
···
+
---
+
import "../styles/global.css"
+
import Navbar from "../components/navbar/Navbar.astro"
+
import Footer from "../components/Footer.astro"
+
---
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width" />
-
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
+
<link rel="icon" type="image/svg+xml" href="/favicon.ico" />
<meta name="generator" content={Astro.generator} />
-
<title>Astro Basics</title>
+
<title>banana's page</title>
</head>
-
<body>
-
<slot />
+
<body class="bg-ctp-crust pl-[2%] pr-[2%]
+
md:pl-[4%] md:pr-[4%] xl:pl-[8%] xl:pr-[8%]
+
text-ctp-text">
+
<main class="w-full min-h-full max-h-max bg-ctp-mantle relative">
+
<Navbar/>
+
<slot />
+
</main>
+
<Footer />
</body>
</html>
-
+
<script>
+
+
</script>
<style>
html,
body {
+14
src/layouts/Page.astro
···
+
---
+
import Layout from './Layout.astro';
+
import Profile from "../components/section/Profile.astro";
+
---
+
<Layout>
+
<section class="h-[50%]
+
flex flex-col lg:grid-cols-5 lg:grid
+
p-10 pt-15 md:p-12 md:pt-18 xl:p-24 xl:pt-36 gap-4 md:gap-8 xl:gap-16">
+
<Profile/>
+
<div class="md:col-span-3 gap-4 md:gap-8 xl:gap-12 flex flex-col">
+
<slot/>
+
</div>
+
</section>
+
</Layout>
+25
src/pages/404.astro
···
+
---
+
import Layout from "../layouts/Layout.astro"
+
+
const urlPathname = Astro.url.pathname
+
const urlOrigin = Astro.url.origin
+
const astroGenerator = Astro.generator
+
const currentISODate = new Date().toISOString();
+
---
+
+
<Layout>
+
<section class="h-svh items-center flex pl-32 pr-32 ">
+
<div class="flex justify-between gap-8 w-full items-end">
+
<span class="text-9xl w-min">404 Not Found</span>
+
<div class="text-ctp-overlay0 flex flex-col items-end text-base p-4">
+
<span>HTTP/1.1 404 Not Found</span>
+
<span>Server: {astroGenerator}</span>
+
<span>Connection: keep-alive</span>
+
<span>Date: {currentISODate}</span>
+
<span>Content-Type: text/html; charset=utf-8</span>
+
<span>X-Request-Path: {urlPathname}</span>
+
<span>X-Request-Origin: {urlOrigin}</span>
+
</div>
+
</div>
+
</section>
+
</Layout>
+9 -8
src/pages/index.astro
···
---
-
import Welcome from '../components/Welcome.astro';
-
import Layout from '../layouts/Layout.astro';
+
import Page from '../layouts/Page.astro';
-
// Welcome to Astro! Wondering what to do next? Check out the Astro documentation at https://docs.astro.build
-
// Don't want to use any of this? Delete everything in this file, the `assets`, `components`, and `layouts` directories, and start fresh.
+
import Contributions from "../components/section/Contributions.astro"
+
import Pinned from "../components/section/Pinned.astro"
+
import MusicPlayer from "../components/section/MusicPlayer.astro"
---
-
-
<Layout>
-
<Welcome />
-
</Layout>
+
<Page>
+
<Contributions/>
+
<Pinned/>
+
<MusicPlayer/>
+
</Page>
+7
src/pages/projects.astro
···
+
---
+
import Page from '../layouts/Page.astro';
+
import ProjectsC from "../components/section/Projects.astro"
+
---
+
<Page>
+
<ProjectsC/>
+
</Page>
+14
src/styles/global.css
···
+
@import url('https://fonts.googleapis.com/css2?family=JetBrains+Mono:ital,wght@0,100..800;1,100..800&display=swap');
+
@import "tailwindcss";
+
@import "@catppuccin/tailwindcss/mocha.css";
+
+
@theme {
+
--color-transparent: "transparent";
+
--ease-in: cubic-bezier(0,0.69,0.31,1.63);
+
--ease-out: cubic-bezier(0,0.69,0.44,0.99);
+
--default-font-family: "JetBrains Mono", monospaced;
+
}
+
+
.squircle {
+
corner-shape: squircle
+
}
+12 -3
tsconfig.json
···
{
"extends": "astro/tsconfigs/strict",
-
"include": [".astro/types.d.ts", "**/*"],
-
"exclude": ["dist"]
-
}
+
"include": [
+
".astro/types.d.ts",
+
"**/*"
+
],
+
"exclude": [
+
"dist"
+
],
+
"compilerOptions": {
+
"jsx": "react-jsx",
+
"jsxImportSource": "react"
+
}
+
}