From d6e75ae2ea38a74e24c4a74a8817db99e7983151 Mon Sep 17 00:00:00 2001 From: Corwin Perren Date: Thu, 6 Nov 2025 01:21:27 -0800 Subject: [PATCH] Made a baseline working carousel, timeline, and started flushing out content for primary spacex experience --- package-lock.json | 99 +++++++++- package.json | 8 +- src/components/Carousel.astro | 8 - src/components/CustomCarousel.astro | 173 ++++++++++++++++++ src/components/Navbar.astro | 2 +- src/components/NestedNavbarEntries.astro | 4 +- src/components/Timeline.astro | 78 ++++++++ src/data/site-layout.ts | 144 +++++++++------ src/env.d.ts | 9 +- src/interfaces/experience-metadata.ts | 13 ++ src/interfaces/image-carousel.ts | 5 + src/interfaces/site-layout.ts | 2 +- src/interfaces/timeline.ts | 6 + src/layouts/BaseLayout.astro | 14 +- src/layouts/ExperienceLayout.astro | 2 +- ...avionics-test-engineering-internship.astro | 59 +++++- .../spacex/hardware-test-engineer-i-ii.astro | 88 ++++++++- ...luster.astro => .kubernetes-cluster.astro} | 0 ...nt.astro => .chubby-buttons-2-mount.astro} | 0 ...-10-norway.astro => .2024-10-norway.astro} | 0 ...-08-alaska.astro => .2025-08-alaska.astro} | 0 .../projects/.ossm-overkill-edition.astro | 0 src/pages/hobby/projects/.shed-solar.astro | 0 src/pages/index.astro | 17 +- src/styles/global.css | 4 + tsconfig.json | 3 +- 26 files changed, 638 insertions(+), 100 deletions(-) delete mode 100644 src/components/Carousel.astro create mode 100644 src/components/CustomCarousel.astro create mode 100644 src/components/Timeline.astro create mode 100644 src/interfaces/experience-metadata.ts create mode 100644 src/interfaces/image-carousel.ts create mode 100644 src/interfaces/timeline.ts rename src/pages/hobby/homelab/{kubernetes-cluster.astro => .kubernetes-cluster.astro} (100%) rename src/pages/hobby/motorcycling/custom-accessories/{chubby-buttons-2-mount.astro => .chubby-buttons-2-mount.astro} (100%) rename src/pages/hobby/motorcycling/trips/{2024-10-norway.astro => .2024-10-norway.astro} (100%) rename src/pages/hobby/motorcycling/trips/{2025-08-alaska.astro => .2025-08-alaska.astro} (100%) create mode 100644 src/pages/hobby/projects/.ossm-overkill-edition.astro create mode 100644 src/pages/hobby/projects/.shed-solar.astro diff --git a/package-lock.json b/package-lock.json index 2a0cf66..3e0dc84 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,21 +8,26 @@ "name": "caperren-com", "version": "0.0.1", "dependencies": { - "@tailwindcss/vite": "^4.1.11", "astro": "^5.15.3", "flowbite": "^3.1.2", + "leader-line-new": "^1.1.9", + "luxon": "^3.7.2", "tailwindcss": "^4.1.11", - "vitest": "^4.0.7" + "uuid": "^13.0.0" }, "devDependencies": { "@playwright/test": "^1.56.1", - "@types/node": "^24.10.0" + "@tailwindcss/vite": "^4.1.11", + "@types/luxon": "^3.7.1", + "@types/node": "^24.10.0", + "vitest": "^4.0.7" } }, "node_modules/@ampproject/remapping": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", + "dev": true, "license": "Apache-2.0", "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", @@ -1003,6 +1008,7 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz", "integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==", + "dev": true, "license": "ISC", "dependencies": { "minipass": "^7.0.4" @@ -1015,6 +1021,7 @@ "version": "0.3.12", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.12.tgz", "integrity": "sha512-OuLGC46TjB5BbN1dH8JULVVZY4WTdkF7tV9Ys6wLL1rubZnCMstOhNHueU5bLCrnRuDhKPDM4g6sw4Bel5Gzqg==", + "dev": true, "license": "MIT", "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0", @@ -1025,6 +1032,7 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, "license": "MIT", "engines": { "node": ">=6.0.0" @@ -1040,6 +1048,7 @@ "version": "0.3.29", "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.29.tgz", "integrity": "sha512-uw6guiW/gcAGPDhLmd77/6lW8QLeiV5RUTsAX46Db6oLhGaVj4lhnPwb184s1bkc8kdVg/+h988dro8GRDpmYQ==", + "dev": true, "license": "MIT", "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", @@ -1448,6 +1457,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.0.0.tgz", "integrity": "sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA==", + "dev": true, "license": "MIT" }, "node_modules/@swc/helpers": { @@ -1463,6 +1473,7 @@ "version": "4.1.11", "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.1.11.tgz", "integrity": "sha512-yzhzuGRmv5QyU9qLNg4GTlYI6STedBWRE7NjxP45CsFYYq9taI0zJXZBMqIC/c8fViNLhmrbpSFS57EoxUmD6Q==", + "dev": true, "license": "MIT", "dependencies": { "@ampproject/remapping": "^2.3.0", @@ -1478,6 +1489,7 @@ "version": "4.1.11", "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.1.11.tgz", "integrity": "sha512-Q69XzrtAhuyfHo+5/HMgr1lAiPP/G40OMFAnws7xcFEYqcypZmdW8eGXaOUIeOl1dzPJBPENXgbjsOyhg2nkrg==", + "dev": true, "hasInstallScript": true, "license": "MIT", "dependencies": { @@ -1509,6 +1521,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1525,6 +1538,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1541,6 +1555,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1557,6 +1572,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1573,6 +1589,7 @@ "cpu": [ "arm" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1589,6 +1606,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1605,6 +1623,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1621,6 +1640,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1637,6 +1657,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1661,6 +1682,7 @@ "cpu": [ "wasm32" ], + "dev": true, "license": "MIT", "optional": true, "dependencies": { @@ -1682,6 +1704,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1698,6 +1721,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1711,6 +1735,7 @@ "version": "4.1.11", "resolved": "https://registry.npmjs.org/@tailwindcss/vite/-/vite-4.1.11.tgz", "integrity": "sha512-RHYhrR3hku0MJFRV+fN2gNbDNEh3dwKvY8XJvTxCSXeMOsCRSr+uKvDWQcbizrHgjML6ZmTE5OwMrl5wKcujCw==", + "dev": true, "license": "MIT", "dependencies": { "@tailwindcss/node": "4.1.11", @@ -1725,6 +1750,7 @@ "version": "5.2.3", "resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.2.3.tgz", "integrity": "sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==", + "dev": true, "license": "MIT", "dependencies": { "@types/deep-eql": "*", @@ -1744,6 +1770,7 @@ "version": "4.0.2", "resolved": "https://registry.npmjs.org/@types/deep-eql/-/deep-eql-4.0.2.tgz", "integrity": "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==", + "dev": true, "license": "MIT" }, "node_modules/@types/estree": { @@ -1770,6 +1797,13 @@ "@types/unist": "*" } }, + "node_modules/@types/luxon": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/@types/luxon/-/luxon-3.7.1.tgz", + "integrity": "sha512-H3iskjFIAn5SlJU7OuxUmTEpebK6TKB8rxZShDslBMZJ5u9S//KM1sbdAisiSrqwLQncVjnpi2OK2J51h+4lsg==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/mdast": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz", @@ -1825,6 +1859,7 @@ "version": "4.0.7", "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.0.7.tgz", "integrity": "sha512-jGRG6HghnJDjljdjYIoVzX17S6uCVCBRFnsgdLGJ6CaxfPh8kzUKe/2n533y4O/aeZ/sIr7q7GbuEbeGDsWv4Q==", + "dev": true, "license": "MIT", "dependencies": { "@standard-schema/spec": "^1.0.0", @@ -1842,6 +1877,7 @@ "version": "4.0.7", "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-4.0.7.tgz", "integrity": "sha512-OsDwLS7WnpuNslOV6bJkXVYVV/6RSc4eeVxV7h9wxQPNxnjRvTTrIikfwCbMyl8XJmW6oOccBj2Q07YwZtQcCw==", + "dev": true, "license": "MIT", "dependencies": { "@vitest/spy": "4.0.7", @@ -1868,6 +1904,7 @@ "version": "4.0.7", "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.0.7.tgz", "integrity": "sha512-YY//yxqTmk29+/pK+Wi1UB4DUH3lSVgIm+M10rAJ74pOSMgT7rydMSc+vFuq9LjZLhFvVEXir8EcqMke3SVM6Q==", + "dev": true, "license": "MIT", "dependencies": { "tinyrainbow": "^3.0.3" @@ -1880,6 +1917,7 @@ "version": "4.0.7", "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-4.0.7.tgz", "integrity": "sha512-orU1lsu4PxLEcDWfjVCNGIedOSF/YtZ+XMrd1PZb90E68khWCNzD8y1dtxtgd0hyBIQk8XggteKN/38VQLvzuw==", + "dev": true, "license": "MIT", "dependencies": { "@vitest/utils": "4.0.7", @@ -1893,6 +1931,7 @@ "version": "4.0.7", "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-4.0.7.tgz", "integrity": "sha512-xJL+Nkw0OjaUXXQf13B8iKK5pI9QVtN9uOtzNHYuG/o/B7fIEg0DQ+xOe0/RcqwDEI15rud1k7y5xznBKGUXAA==", + "dev": true, "license": "MIT", "dependencies": { "@vitest/pretty-format": "4.0.7", @@ -1907,6 +1946,7 @@ "version": "4.0.7", "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-4.0.7.tgz", "integrity": "sha512-FW4X8hzIEn4z+HublB4hBF/FhCVaXfIHm8sUfvlznrcy1MQG7VooBgZPMtVCGZtHi0yl3KESaXTqsKh16d8cFg==", + "dev": true, "license": "MIT", "funding": { "url": "https://opencollective.com/vitest" @@ -1916,6 +1956,7 @@ "version": "4.0.7", "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.0.7.tgz", "integrity": "sha512-HNrg9CM/Z4ZWB6RuExhuC6FPmLipiShKVMnT9JlQvfhwR47JatWLChA6mtZqVHqypE6p/z6ofcjbyWpM7YLxPQ==", + "dev": true, "license": "MIT", "dependencies": { "@vitest/pretty-format": "4.0.7", @@ -2065,6 +2106,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", + "dev": true, "license": "MIT", "engines": { "node": ">=12" @@ -2257,6 +2299,7 @@ "version": "6.2.0", "resolved": "https://registry.npmjs.org/chai/-/chai-6.2.0.tgz", "integrity": "sha512-aUTnJc/JipRzJrNADXVvpVqi6CO0dn3nx4EVPxijri+fj3LUUDyZQOgVeW54Ob3Y1Xh9Iz8f+CgaCl8v0mn9bA==", + "dev": true, "license": "MIT", "engines": { "node": ">=18" @@ -2323,6 +2366,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz", "integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==", + "dev": true, "license": "BlueOak-1.0.0", "engines": { "node": ">=18" @@ -2502,6 +2546,7 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.1.tgz", "integrity": "sha512-ecqj/sy1jcK1uWrwpR67UhYrIFQ+5WlGxth34WquCbamhFA6hkkwiu37o6J5xCHdo1oixJRfVRw+ywV+Hq/0Aw==", + "devOptional": true, "license": "Apache-2.0", "engines": { "node": ">=8" @@ -2578,6 +2623,7 @@ "version": "5.18.2", "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.2.tgz", "integrity": "sha512-6Jw4sE1maoRJo3q8MsSIn2onJFbLTOjY9hlx4DZXmOKvLRd1Ok2kXmAGXaafL2+ijsJZ1ClYbl/pmqr9+k4iUQ==", + "dev": true, "license": "MIT", "dependencies": { "graceful-fs": "^4.2.4", @@ -2676,6 +2722,7 @@ "version": "1.2.2", "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.2.2.tgz", "integrity": "sha512-JhFGDVJ7tmDJItKhYgJCGLOWjuK9vPxiXoUFLwLDc99NlmklilbiQJwoctZtt13+xMw91MCk/REan6MWHqDjyA==", + "dev": true, "license": "Apache-2.0", "engines": { "node": ">=12.0.0" @@ -2824,6 +2871,7 @@ "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/h3": { @@ -3177,6 +3225,7 @@ "version": "2.4.2", "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.4.2.tgz", "integrity": "sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A==", + "devOptional": true, "license": "MIT", "bin": { "jiti": "lib/jiti-cli.mjs" @@ -3194,10 +3243,17 @@ "js-yaml": "bin/js-yaml.js" } }, + "node_modules/leader-line-new": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/leader-line-new/-/leader-line-new-1.1.9.tgz", + "integrity": "sha512-x56aRYaqJTA4aAS2fgbSpvWKY3IxRXDSFeGkNBmCQ3LX44B3F1HEjcBTkCiK5I3W0nPWeUTWe7dTt59VtdfFWw==", + "license": "MIT" + }, "node_modules/lightningcss": { "version": "1.30.1", "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.30.1.tgz", "integrity": "sha512-xi6IyHML+c9+Q3W0S4fCQJOym42pyurFiJUHEcEyHS0CeKzia4yZDEsLlqOFykxOdHpNy0NmvVO31vcSqAxJCg==", + "devOptional": true, "license": "MPL-2.0", "dependencies": { "detect-libc": "^2.0.3" @@ -3438,6 +3494,15 @@ "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", "license": "ISC" }, + "node_modules/luxon": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/luxon/-/luxon-3.7.2.tgz", + "integrity": "sha512-vtEhXh/gNjI9Yg1u4jX/0YVPMvxzHuGgCm6tC5kZyb08yjGWGnqAjGJvcXbqQR2P3MyMEFnRbpcdFS6PBcLqew==", + "license": "MIT", + "engines": { + "node": ">=12" + } + }, "node_modules/magic-string": { "version": "0.30.19", "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.19.tgz", @@ -4275,6 +4340,7 @@ "version": "7.1.2", "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "dev": true, "license": "ISC", "engines": { "node": ">=16 || 14 >=14.17" @@ -4284,6 +4350,7 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.0.2.tgz", "integrity": "sha512-oG62iEk+CYt5Xj2YqI5Xi9xWUeZhDI8jjQmC5oThVH5JGCTgIjr7ciJDzC7MBzYd//WvR1OTmP5Q38Q8ShQtVA==", + "dev": true, "license": "MIT", "dependencies": { "minipass": "^7.1.2" @@ -4296,6 +4363,7 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-3.0.1.tgz", "integrity": "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==", + "dev": true, "license": "MIT", "bin": { "mkdirp": "dist/cjs/src/bin.js" @@ -4512,6 +4580,7 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", + "dev": true, "license": "MIT" }, "node_modules/picocolors": { @@ -5033,6 +5102,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", + "dev": true, "license": "ISC" }, "node_modules/sisteransi": { @@ -5076,12 +5146,14 @@ "version": "0.0.2", "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", + "dev": true, "license": "MIT" }, "node_modules/std-env": { "version": "3.10.0", "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.10.0.tgz", "integrity": "sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==", + "dev": true, "license": "MIT" }, "node_modules/string-width": { @@ -5152,6 +5224,7 @@ "version": "2.2.2", "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.2.tgz", "integrity": "sha512-Re10+NauLTMCudc7T5WLFLAwDhQ0JWdrMK+9B2M8zR5hRExKmsRDCBA7/aV/pNJFltmBFO5BAMlQFi/vq3nKOg==", + "dev": true, "license": "MIT", "engines": { "node": ">=6" @@ -5161,6 +5234,7 @@ "version": "7.4.3", "resolved": "https://registry.npmjs.org/tar/-/tar-7.4.3.tgz", "integrity": "sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw==", + "dev": true, "license": "ISC", "dependencies": { "@isaacs/fs-minipass": "^4.0.0", @@ -5184,6 +5258,7 @@ "version": "2.9.0", "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==", + "dev": true, "license": "MIT" }, "node_modules/tinyexec": { @@ -5215,6 +5290,7 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-3.0.3.tgz", "integrity": "sha512-PSkbLUoxOFRzJYjjxHJt9xro7D+iilgMX/C9lawzVuYiIdcihh9DXmVibBe8lmcFrRi/VzlPjBxbN7rH24q8/Q==", + "dev": true, "license": "MIT", "engines": { "node": ">=14.0.0" @@ -5585,6 +5661,19 @@ } } }, + "node_modules/uuid": { + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-13.0.0.tgz", + "integrity": "sha512-XQegIaBTVUjSHliKqcnFqYypAd4S+WCYt5NIeRs6w/UAry7z8Y9j5ZwRRL4kzq9U3sD6v+85er9FvkEaBpji2w==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "bin": { + "uuid": "dist-node/bin/uuid" + } + }, "node_modules/vfile": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.3.tgz", @@ -5724,6 +5813,7 @@ "version": "4.0.7", "resolved": "https://registry.npmjs.org/vitest/-/vitest-4.0.7.tgz", "integrity": "sha512-xQroKAadK503CrmbzCISvQUjeuvEZzv6U0wlnlVFOi5i3gnzfH4onyQ29f3lzpe0FresAiTAd3aqK0Bi/jLI8w==", + "dev": true, "license": "MIT", "dependencies": { "@vitest/expect": "4.0.7", @@ -5801,6 +5891,7 @@ "version": "0.3.2", "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.2.tgz", "integrity": "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==", + "dev": true, "license": "MIT" }, "node_modules/web-namespaces": { @@ -5826,6 +5917,7 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz", "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==", + "dev": true, "license": "MIT", "dependencies": { "siginfo": "^2.0.0", @@ -5880,6 +5972,7 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz", "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==", + "dev": true, "license": "BlueOak-1.0.0", "engines": { "node": ">=18" diff --git a/package.json b/package.json index 7702058..34a7b54 100644 --- a/package.json +++ b/package.json @@ -11,13 +11,17 @@ "test": "vitest" }, "dependencies": { - "@tailwindcss/vite": "^4.1.11", "astro": "^5.15.3", "flowbite": "^3.1.2", - "tailwindcss": "^4.1.11" + "leader-line-new": "^1.1.9", + "luxon": "^3.7.2", + "tailwindcss": "^4.1.11", + "uuid": "^13.0.0" }, "devDependencies": { "@playwright/test": "^1.56.1", + "@tailwindcss/vite": "^4.1.11", + "@types/luxon": "^3.7.1", "@types/node": "^24.10.0", "vitest": "^4.0.7" } diff --git a/src/components/Carousel.astro b/src/components/Carousel.astro deleted file mode 100644 index 0334527..0000000 --- a/src/components/Carousel.astro +++ /dev/null @@ -1,8 +0,0 @@ ---- -const { images } = Astro.props; ---- - \ No newline at end of file diff --git a/src/components/CustomCarousel.astro b/src/components/CustomCarousel.astro new file mode 100644 index 0000000..d594dcb --- /dev/null +++ b/src/components/CustomCarousel.astro @@ -0,0 +1,173 @@ +--- +import {Image} from 'astro:assets'; + +import type {carouselGroup} from "@interfaces/image-carousel.ts"; + +const groupToShow: carouselGroup = Astro.props.carouselGroup; +--- + + + + +
+ { + groupToShow.images.map((image, index) => ( + + )) + } +
+ + {(groupToShow.images.length > 1) && ( + +
+ { + groupToShow.images.map((_, index) => ( + + )) + } +
+ + + + )} +
+ + diff --git a/src/components/Navbar.astro b/src/components/Navbar.astro index ff2225c..5d12dcd 100644 --- a/src/components/Navbar.astro +++ b/src/components/Navbar.astro @@ -20,7 +20,7 @@ import {siteLayout} from "@data/site-layout.ts"; d="M1 1h15M1 7h15M1 13h15"/> - diff --git a/src/components/NestedNavbarEntries.astro b/src/components/NestedNavbarEntries.astro index 1344838..b999624 100644 --- a/src/components/NestedNavbarEntries.astro +++ b/src/components/NestedNavbarEntries.astro @@ -21,7 +21,7 @@ const getHrefPath = (entry: navLink): string => { data-dropdown-toggle={"dropdownNavbar" + getNavLinkSuffix(entry)} data-dropdown-placement="bottom" class="flex items-center justify-between py-2 px-3 w-full hover:text-caperren-green-light md:hover:bg-transparent md:border-0 md:hover:text-caperren-green-light md:p-0 "> - {entry.title} + {entry.navText}
+ {timeline.map((entry, index) => ( +
+

+ {entry.event} +

+

+ {entry.eventDetail} +

+ + {entry.description && ( +

+ {entry.description} +

+ )} +
+ ))} +
+ + + diff --git a/src/data/site-layout.ts b/src/data/site-layout.ts index 6620756..a7d7fe0 100644 --- a/src/data/site-layout.ts +++ b/src/data/site-layout.ts @@ -1,87 +1,87 @@ import type {navLink} from "@interfaces/site-layout.ts" export const siteLayout: navLink[] = [ - {title: "About", path: ""}, + {navText: "About", path: ""}, { - title: "Experiences", + navText: "Experiences", path: "experience", children: [ { - title: "SpaceX", + navText: "SpaceX", path: "spacex", children: [ { - title: "Hardware Test Engineer I/II", + navText: "Hardware Test Engineer I/II", path: "hardware-test-engineer-i-ii" }, { - title: "Avionics Test Engineering Internship", + navText: "Avionics Test Engineering Internship", path: "avionics-test-engineering-internship" } ] }, { - title: "OSU CEOAS", + navText: "OSU CEOAS", path: "osu-ceoas-ocean-mixing-group", children: [ { - title: "Robotics Oceanographic Surface Sampler", + navText: "Robotics Oceanographic Surface Sampler", path: "robotic-oceanographic-surface-sampler", }, { - title: "LeConte Glacier Deployments", + navText: "LeConte Glacier Deployments", path: "leconte-glacier-deployments", } ] }, { - title: "OSU SARL", + navText: "OSU SARL", path: "osu-sinnhuber-aquatic-research-laboratory", children: [ { - title: "Team Lead", + navText: "Team Lead", path: "team-lead", }, { - title: "Zebrafish Embryo Pick and Plate", + navText: "Zebrafish Embryo Pick and Plate", path: "zebrafish-embryo-pick-and-plate", }, { - title: "Shuttlebox Behavior System", + navText: "Shuttlebox Behavior System", path: "shuttlebox-behavior-system", }, { - title: "Dechorionator", + navText: "Dechorionator", path: "dechorionator", }, { - title: "Denso Embryo Pick and Plate", + navText: "Denso Embryo Pick and Plate", path: "denso-embryo-pick-and-plate", }, { - title: "ZScan Processor", + navText: "ZScan Processor", path: "zscan-processor", } ] }, { - title: "OSU Robotics Club", + navText: "OSU Robotics Club", path: "osu-robotics-club", children: [ { - title: "Club Officer", + navText: "Club Officer", path: "club-officer", }, { - title: "Mars Rover Software Team Lead", + navText: "Mars Rover Software Team Lead", path: "mars-rover-software-team-lead", }, { - title: "Mars Rover Emergency Software Team Lead", + navText: "Mars Rover Emergency Software Team Lead", path: "mars-rover-emergency-software-team-lead", }, { - title: "Mars Rover Electrical Team Lead", + navText: "Mars Rover Electrical Team Lead", path: "mars-rover-electrical-team-lead", } ] @@ -89,63 +89,85 @@ export const siteLayout: navLink[] = [ ] }, { - title: "Hobbies", + navText: "Hobbies", path: "hobby", children: [ { - title: "Homelab", path: "homelab", + navText: "Homelab", path: "homelab", children: [ - {title: "Home Server Rack", path: "home-server-rack"}, - {title: "Offsite Backup Rack", path: "offsite-backup-rack"}, - {title: "Kubernetes Cluster", path: "kubernetes-cluster"}, - {title: "Home Automation", path: "home-automation"}, + {navText: "Home Server Rack", path: "home-server-rack"}, + {navText: "Offsite Backup Rack", path: "offsite-backup-rack"}, + // {title: "Kubernetes Cluster", path: "kubernetes-cluster"}, + {navText: "Home Automation", path: "home-automation"}, ] }, { - title: "Motorcycling", + navText: "Motorcycling", path: "motorcycling", children: [ - {title: "Lineup", path: "lineup"}, - { - title: "Custom Accessories", - path: "custom-accessories", - children: [ - {title: "Chubby Buttons 2 Mount", path: "chubby-buttons-2-mount"}, - ] - }, - { - title: "Trips", - path: "trips", - children: [ - {title: "2025-08 | Alaska ", path: "2025-08-alaska"}, - {title: "2024-10 | Norway ", path: "2024-10-norway"} - ] - }, + {navText: "Lineup", path: "lineup"}, + // { + // title: "Custom Accessories", + // path: "custom-accessories", + // children: [ + // {title: "Chubby Buttons 2 Mount", path: "chubby-buttons-2-mount"}, + // ] + // }, + // { + // title: "Trips", + // path: "trips", + // children: [ + // {title: "2025-08 | Alaska ", path: "2025-08-alaska"}, + // {title: "2024-10 | Norway ", path: "2024-10-norway"} + // ] + // }, ] }, - { - title: "Homelab", path: "homelab", - children: [ - {title: "Home Server Rack", path: "home-server-rack"}, - {title: "Offsite Backup Rack", path: "offsite-backup-rack"}, - {title: "Kubernetes Cluster", path: "kubernetes-cluster"}, - {title: "Home Automation", path: "home-automation"}, - ] - }, - {title: "NixOS", path: "nixos"}, - {title: "Body Mods", path: "body-mods"}, + // { + // title: "Projects", path: "projects", + // children: [ + // {title: "Shed Solar", path: "shed-solar"}, + // {title: "OSSM Overkill Edition", path: "ossm-overkill-edition"}, + // ] + // }, + // {title: "NixOS", path: "nixos"}, + // {title: "Body Mods", path: "body-mods"}, ] }, { - title: "Resumes", + navText: "Resumes", path: "resume", children: [ - {title: "2025-11-10 | Complete CV", path: "2025-11-10-complete-cv"}, - {title: "2025-11-10 | Infrastructure Engineer", path: "2025-11-10-infrastructure-engineer"}, - {title: "2019-07-01 | Hardware Test Engineer", path: "2019-07-01-hardware-test-engineer"}, + // {title: "2025-11-10 | Complete CV", path: "2025-11-10-complete-cv"}, + {navText: "2025-11-10 | Infrastructure Engineer", path: "2025-11-10-infrastructure-engineer"}, + {navText: "2019-07-01 | Hardware Test Engineer", path: "2019-07-01-hardware-test-engineer"}, ] }, - {title: "Github", pubpath: "https://github.com/caperren"}, - {title: "LinkedIn", pubpath: "https://www.linkedin.com/in/caperren/"} -] \ No newline at end of file + {navText: "Github", pubpath: "https://github.com/caperren"}, + {navText: "LinkedIn", pubpath: "https://www.linkedin.com/in/caperren/"} +] + +export const pathToMetadata = (path: string): navLink => { + const paths = path.split("/").filter((entry) => entry); + let currentEntries: navLink[] = siteLayout; + let foundEntry: navLink | undefined; + + for (const path of paths) { + for (const currentEntry of currentEntries) { + if (currentEntry.path === path) { + foundEntry = currentEntry; + + if (foundEntry.children && foundEntry.children.length > 0) { + currentEntries = foundEntry.children; + } + } + } + } + + if (foundEntry === undefined) { + throw new Error(`${path} not found in site layout!`); + } + + return foundEntry; +} \ No newline at end of file diff --git a/src/env.d.ts b/src/env.d.ts index 47e19ac..b00f7aa 100644 --- a/src/env.d.ts +++ b/src/env.d.ts @@ -6,4 +6,11 @@ interface ImportMetaEnv { interface ImportMeta { readonly env: ImportMetaEnv; -} \ No newline at end of file +} + +declare global { + interface Window { + LeaderLine: any; + } +} +export {}; \ No newline at end of file diff --git a/src/interfaces/experience-metadata.ts b/src/interfaces/experience-metadata.ts new file mode 100644 index 0000000..d74934f --- /dev/null +++ b/src/interfaces/experience-metadata.ts @@ -0,0 +1,13 @@ +import { DateTime } from 'luxon'; + +export interface experience { + + +} +export interface subExperience { + name: string; + description: string; + + startDate: DateTime; + endDate?: DateTime; +} diff --git a/src/interfaces/image-carousel.ts b/src/interfaces/image-carousel.ts new file mode 100644 index 0000000..e6df1e6 --- /dev/null +++ b/src/interfaces/image-carousel.ts @@ -0,0 +1,5 @@ +export interface carouselGroup { + animation: "static" | "slide"; + interval?: number; + images: ImageMetadata[]; +} \ No newline at end of file diff --git a/src/interfaces/site-layout.ts b/src/interfaces/site-layout.ts index 7f47dd3..cd4f4a0 100644 --- a/src/interfaces/site-layout.ts +++ b/src/interfaces/site-layout.ts @@ -1,5 +1,5 @@ export interface navLink { - title: string; + navText: string; path?: string; pubpath?: string; children?: navLink[]; diff --git a/src/interfaces/timeline.ts b/src/interfaces/timeline.ts new file mode 100644 index 0000000..cdc8b77 --- /dev/null +++ b/src/interfaces/timeline.ts @@ -0,0 +1,6 @@ +export interface timelineEntry { + event: string; + eventDetail?: string + date: string; + description?: string; +} \ No newline at end of file diff --git a/src/layouts/BaseLayout.astro b/src/layouts/BaseLayout.astro index 7c45e4c..8088aed 100644 --- a/src/layouts/BaseLayout.astro +++ b/src/layouts/BaseLayout.astro @@ -1,7 +1,8 @@ --- -import '../styles/global.css' -import Navbar from '../components/Navbar.astro'; -import Footer from '../components/Footer.astro'; +import '@styles/global.css' + +import Navbar from '@components/Navbar.astro'; +import Footer from '@components/Footer.astro'; const pageTitle = Astro.props.title ? `${Astro.props.title} - Corwin Perren` : "Corwin Perren"; --- @@ -12,14 +13,19 @@ const pageTitle = Astro.props.title ? `${Astro.props.title} - Corwin Perren` : " {pageTitle} + + +
+ {(Astro.props.title) && ( +

{Astro.props.title}

+ )}