diff --git a/Makefile b/Makefile index 78cf6ab..524a7ac 100644 --- a/Makefile +++ b/Makefile @@ -15,7 +15,8 @@ cleanup-check \ cleanup-code \ convert_video \ - convert_video_times + convert_video_times \ + generate_asset_imports default: dev @@ -89,3 +90,9 @@ convert_video_times: -qp 28 \ -an \ $(output) + +generate_asset_imports: + @for assets_path in `find "src/assets/${assets_relative_path}" -maxdepth 1 -type f -printf "%f\n"`; do \ + without_extension=$${assets_path/%.*}; \ + echo "import $${without_extension//-/_} from \"@assets/${assets_relative_path}/$$assets_path\";"; \ + done; diff --git a/project-words.txt b/project-words.txt index f08e445..5bb8d68 100644 --- a/project-words.txt +++ b/project-words.txt @@ -13,13 +13,17 @@ Concours CONSERV Corwin dangerousthings +dechorionation Dechorionator +dechorionators dockerization dockerizing drumheller ebox +ELMI fhhs flowbite +flowrate Gitea HDFS headshot @@ -34,6 +38,8 @@ leconte Loctite luxon MGMT +Micropumps +Millis Mokai Multimeters nixos @@ -42,26 +48,32 @@ Onshape OSSM OSURC Passthroughs +pcbs Perren Perren's Pixhawk Protocase pubpath RFID +Rito RSSI SARL +showerheads Shuttlebox sinnhuber sitemapindex Smartsheet +solderable ssds Starlink steller Steller +Tanguay Teamcenter timelapse triaging trivago +Truong Unstow uuidv vaapi diff --git a/src/assets/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator/assembly-internal-overview.jpg b/src/assets/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator/assembly-internal-overview.jpg new file mode 100644 index 0000000..45fe04e Binary files /dev/null and b/src/assets/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator/assembly-internal-overview.jpg differ diff --git a/src/assets/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator/assembly-pcb-connected.jpg b/src/assets/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator/assembly-pcb-connected.jpg new file mode 100644 index 0000000..fa3f8eb Binary files /dev/null and b/src/assets/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator/assembly-pcb-connected.jpg differ diff --git a/src/assets/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator/assembly-pcb-front-on.jpg b/src/assets/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator/assembly-pcb-front-on.jpg new file mode 100644 index 0000000..e018024 Binary files /dev/null and b/src/assets/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator/assembly-pcb-front-on.jpg differ diff --git a/src/assets/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator/assembly-pcb-front.jpg b/src/assets/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator/assembly-pcb-front.jpg new file mode 100644 index 0000000..1ae8392 Binary files /dev/null and b/src/assets/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator/assembly-pcb-front.jpg differ diff --git a/src/assets/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator/assembly-pcb-rear.jpg b/src/assets/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator/assembly-pcb-rear.jpg new file mode 100644 index 0000000..655e6d8 Binary files /dev/null and b/src/assets/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator/assembly-pcb-rear.jpg differ diff --git a/src/assets/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator/assembly-surround-front.jpg b/src/assets/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator/assembly-surround-front.jpg new file mode 100644 index 0000000..88c78a9 Binary files /dev/null and b/src/assets/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator/assembly-surround-front.jpg differ diff --git a/src/assets/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator/assembly-surround-rear.jpg b/src/assets/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator/assembly-surround-rear.jpg new file mode 100644 index 0000000..77f1417 Binary files /dev/null and b/src/assets/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator/assembly-surround-rear.jpg differ diff --git a/src/assets/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator/off-front-lid-open.jpg b/src/assets/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator/off-front-lid-open.jpg new file mode 100644 index 0000000..5c9ffd9 Binary files /dev/null and b/src/assets/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator/off-front-lid-open.jpg differ diff --git a/src/assets/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator/off-front.jpg b/src/assets/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator/off-front.jpg new file mode 100644 index 0000000..4473097 Binary files /dev/null and b/src/assets/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator/off-front.jpg differ diff --git a/src/assets/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator/on-front-closeup.jpg b/src/assets/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator/on-front-closeup.jpg new file mode 100644 index 0000000..f1cc7b7 Binary files /dev/null and b/src/assets/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator/on-front-closeup.jpg differ diff --git a/src/assets/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator/on-front.jpg b/src/assets/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator/on-front.jpg new file mode 100644 index 0000000..57d288b Binary files /dev/null and b/src/assets/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator/on-front.jpg differ diff --git a/src/assets/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator/on-mid-cycle.jpg b/src/assets/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator/on-mid-cycle.jpg new file mode 100644 index 0000000..e5e1b9c Binary files /dev/null and b/src/assets/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator/on-mid-cycle.jpg differ diff --git a/src/assets/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator/pcbs/1-1-0/assembled-bottom-angle.jpg b/src/assets/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator/pcbs/1-1-0/assembled-bottom-angle.jpg new file mode 100644 index 0000000..fe15185 Binary files /dev/null and b/src/assets/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator/pcbs/1-1-0/assembled-bottom-angle.jpg differ diff --git a/src/assets/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator/pcbs/1-1-0/assembled-bottom.jpg b/src/assets/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator/pcbs/1-1-0/assembled-bottom.jpg new file mode 100644 index 0000000..e888356 Binary files /dev/null and b/src/assets/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator/pcbs/1-1-0/assembled-bottom.jpg differ diff --git a/src/assets/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator/pcbs/1-1-0/assembled-side.jpg b/src/assets/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator/pcbs/1-1-0/assembled-side.jpg new file mode 100644 index 0000000..99b9c14 Binary files /dev/null and b/src/assets/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator/pcbs/1-1-0/assembled-side.jpg differ diff --git a/src/assets/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator/pcbs/1-1-0/bare-bottom.png b/src/assets/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator/pcbs/1-1-0/bare-bottom.png new file mode 100644 index 0000000..4d362ad Binary files /dev/null and b/src/assets/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator/pcbs/1-1-0/bare-bottom.png differ diff --git a/src/assets/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator/pcbs/1-1-0/bare-top.png b/src/assets/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator/pcbs/1-1-0/bare-top.png new file mode 100644 index 0000000..952c31f Binary files /dev/null and b/src/assets/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator/pcbs/1-1-0/bare-top.png differ diff --git a/src/assets/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator/pcbs/3-0-0/assembled-main-bottom.jpg b/src/assets/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator/pcbs/3-0-0/assembled-main-bottom.jpg new file mode 100644 index 0000000..5c9c2ac Binary files /dev/null and b/src/assets/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator/pcbs/3-0-0/assembled-main-bottom.jpg differ diff --git a/src/assets/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator/pcbs/3-0-0/assembled-side.jpg b/src/assets/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator/pcbs/3-0-0/assembled-side.jpg new file mode 100644 index 0000000..e1c85d4 Binary files /dev/null and b/src/assets/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator/pcbs/3-0-0/assembled-side.jpg differ diff --git a/src/assets/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator/pcbs/3-0-0/bare-main-bottom.jpg b/src/assets/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator/pcbs/3-0-0/bare-main-bottom.jpg new file mode 100644 index 0000000..eb4f971 Binary files /dev/null and b/src/assets/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator/pcbs/3-0-0/bare-main-bottom.jpg differ diff --git a/src/assets/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator/pcbs/3-0-0/bare-main-top.jpg b/src/assets/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator/pcbs/3-0-0/bare-main-top.jpg new file mode 100644 index 0000000..a30e459 Binary files /dev/null and b/src/assets/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator/pcbs/3-0-0/bare-main-top.jpg differ diff --git a/src/assets/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator/pcbs/3-0-0/bare-surround-bottom.jpg b/src/assets/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator/pcbs/3-0-0/bare-surround-bottom.jpg new file mode 100644 index 0000000..3840fc6 Binary files /dev/null and b/src/assets/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator/pcbs/3-0-0/bare-surround-bottom.jpg differ diff --git a/src/assets/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator/pcbs/3-0-0/bare-surround-top.jpg b/src/assets/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator/pcbs/3-0-0/bare-surround-top.jpg new file mode 100644 index 0000000..dc166e9 Binary files /dev/null and b/src/assets/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator/pcbs/3-0-0/bare-surround-top.jpg differ diff --git a/src/assets/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator/pcbs/3-0-0/half-assembled-main-top-surround-bottom-lcd.jpg b/src/assets/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator/pcbs/3-0-0/half-assembled-main-top-surround-bottom-lcd.jpg new file mode 100644 index 0000000..b9b2e1d Binary files /dev/null and b/src/assets/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator/pcbs/3-0-0/half-assembled-main-top-surround-bottom-lcd.jpg differ diff --git a/src/assets/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator/pcbs/3-0-0/half-assembled-main-top-surround-bottom.jpg b/src/assets/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator/pcbs/3-0-0/half-assembled-main-top-surround-bottom.jpg new file mode 100644 index 0000000..1bcb346 Binary files /dev/null and b/src/assets/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator/pcbs/3-0-0/half-assembled-main-top-surround-bottom.jpg differ diff --git a/src/assets/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator/rear-water-manifold.jpg b/src/assets/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator/rear-water-manifold.jpg new file mode 100644 index 0000000..964861e Binary files /dev/null and b/src/assets/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator/rear-water-manifold.jpg differ diff --git a/src/assets/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator/rear.jpg b/src/assets/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator/rear.jpg new file mode 100644 index 0000000..d37e623 Binary files /dev/null and b/src/assets/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator/rear.jpg differ diff --git a/src/assets/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator/top-drain.jpg b/src/assets/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator/top-drain.jpg new file mode 100644 index 0000000..98f6e2f Binary files /dev/null and b/src/assets/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator/top-drain.jpg differ diff --git a/src/assets/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator/top-holder-closeup.jpg b/src/assets/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator/top-holder-closeup.jpg new file mode 100644 index 0000000..f58838f Binary files /dev/null and b/src/assets/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator/top-holder-closeup.jpg differ diff --git a/src/assets/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator/top-lid-open.jpg b/src/assets/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator/top-lid-open.jpg new file mode 100644 index 0000000..cba252f Binary files /dev/null and b/src/assets/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator/top-lid-open.jpg differ diff --git a/src/assets/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator/top-showerhead.jpg b/src/assets/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator/top-showerhead.jpg new file mode 100644 index 0000000..9220b6f Binary files /dev/null and b/src/assets/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator/top-showerhead.jpg differ diff --git a/src/assets/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator/travel-setup.jpg b/src/assets/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator/travel-setup.jpg new file mode 100644 index 0000000..c95d9d7 Binary files /dev/null and b/src/assets/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator/travel-setup.jpg differ diff --git a/src/assets/experience/osu-sinnhuber-aquatic-research-laboratory/zebrafish-embryo-pick-and-plate/installation-and-tuning.jpg b/src/assets/experience/osu-sinnhuber-aquatic-research-laboratory/zebrafish-embryo-pick-and-plate/installation-and-tuning.jpg new file mode 100644 index 0000000..5d8a889 Binary files /dev/null and b/src/assets/experience/osu-sinnhuber-aquatic-research-laboratory/zebrafish-embryo-pick-and-plate/installation-and-tuning.jpg differ diff --git a/src/assets/experience/osu-sinnhuber-aquatic-research-laboratory/zebrafish-embryo-pick-and-plate/pre-travel.jpg b/src/assets/experience/osu-sinnhuber-aquatic-research-laboratory/zebrafish-embryo-pick-and-plate/pre-travel.jpg new file mode 100644 index 0000000..13c35a4 Binary files /dev/null and b/src/assets/experience/osu-sinnhuber-aquatic-research-laboratory/zebrafish-embryo-pick-and-plate/pre-travel.jpg differ diff --git a/src/assets/about/alaska-bike-mountain-ocean.jpg b/src/assets/hobby/motorcycling/trips/2025-08-alaska/alaska-bike-mountain-ocean.jpg similarity index 100% rename from src/assets/about/alaska-bike-mountain-ocean.jpg rename to src/assets/hobby/motorcycling/trips/2025-08-alaska/alaska-bike-mountain-ocean.jpg diff --git a/src/components/Media/CustomCarousel/CustomCarousel.astro b/src/components/Media/CustomCarousel/CustomCarousel.astro index f287c30..fbf634c 100644 --- a/src/components/Media/CustomCarousel/CustomCarousel.astro +++ b/src/components/Media/CustomCarousel/CustomCarousel.astro @@ -1,15 +1,21 @@ --- import { Image } from "astro:assets"; +import type { ComponentPropsBase } from "@interfaces/components.ts"; import type { carouselGroup } from "@interfaces/image-carousel.ts"; -const groupToShow: carouselGroup = Astro.props.carouselGroup; +interface Props extends ComponentPropsBase { + carouselGroup: carouselGroup; + showBorder?: boolean; +} + +const { class: className, carouselGroup, showBorder = true } = Astro.props; ---
-
+
{ - groupToShow.images.map((image, index) => ( - - )) + carouselGroup.images && + carouselGroup.images.map((image, index) => ( + + )) }
{ - groupToShow.images.length > 1 && ( + carouselGroup.images && carouselGroup.images.length > 1 && (
- {groupToShow.images.map((_, index) => ( -
diff --git a/src/components/PageGroup.astro b/src/components/PageGroup.astro index ae14e15..53139ce 100644 --- a/src/components/PageGroup.astro +++ b/src/components/PageGroup.astro @@ -3,7 +3,7 @@ const hasHeader = Astro.slots.has("header"); const hasDefault = Astro.slots.has("default"); --- -
+
{ Astro.slots.has("header") && (
diff --git a/src/components/PrintedCircuitBoard.astro b/src/components/PrintedCircuitBoard.astro new file mode 100644 index 0000000..0adeae8 --- /dev/null +++ b/src/components/PrintedCircuitBoard.astro @@ -0,0 +1,51 @@ +--- +import Carousel from "@components/Media/CustomCarousel/CustomCarousel.astro"; +import Ul from "@components/Ul.astro"; + +import type { + printedCircuitBoard, + printedCircuitBoardRevision, +} from "@interfaces/printed-circuit-board.ts"; + +interface Props { + pcb: printedCircuitBoard; +} + +const { pcb } = Astro.props; +const semanticPcbRevisionSort = ( + a: printedCircuitBoardRevision, + b: printedCircuitBoardRevision, +): number => + -((a.major - b.major) * 100 + (a.minor - b.minor) * 10 + (a.patch - b.patch)); +--- + +
+ { + pcb.revisions?.sort(semanticPcbRevisionSort).map((revision) => ( +
+
+
+ Revision: + + {revision.major}.{revision.minor}.{revision.patch} + +
+
{revision.date.toISODate()}
+
+
+ +
+ {revision.notes && revision.notes.length > 0 && ( +
    + )} +
+ )) + } +
diff --git a/src/components/Timeline/Timeline.astro b/src/components/Timeline/Timeline.astro index ca38d55..6bf9855 100644 --- a/src/components/Timeline/Timeline.astro +++ b/src/components/Timeline/Timeline.astro @@ -1,7 +1,11 @@ --- import type { timelineEntry } from "@interfaces/timeline.ts"; -const timeline: timelineEntry[] = Astro.props.timeline || []; +interface Props { + timeline: timelineEntry[]; +} + +const { timeline = [] } = Astro.props; --- @@ -11,21 +15,25 @@ const timeline: timelineEntry[] = Astro.props.timeline || []; data-timeline > { - timeline.map((entry, index) => ( -
-

{entry.event}

-

{entry.eventDetail}

- - {entry.description && ( -

{entry.description}

- )} -
- )) + timeline + .sort((a: timelineEntry, b: timelineEntry) => + a.date.diff(b.date).toMillis(), + ) + .map((entry, index) => ( +
+

{entry.event}

+

{entry.eventDetail}

+ + {entry.description && ( +

{entry.description}

+ )} +
+ )) }
+ pcb.revisions?.map((revision) => ({ + event: `PCB Released: ${pcb.name} `, + eventDetail: `Revision: ${revision.major}.${revision.minor}.${revision.patch}`, + date: revision.date, + })); diff --git a/src/interfaces/site-layout.ts b/src/interfaces/site-layout.ts index 19bb829..380395f 100644 --- a/src/interfaces/site-layout.ts +++ b/src/interfaces/site-layout.ts @@ -1,8 +1,13 @@ export interface navLink { enabled?: boolean; hidden?: boolean; + placeholderEntry?: boolean; + navText: string; + isSubItem?: boolean; // For visual distinction only + path?: string; pubpath?: string; + children?: navLink[]; } diff --git a/src/interfaces/timeline.ts b/src/interfaces/timeline.ts index 484318b..d1d250d 100644 --- a/src/interfaces/timeline.ts +++ b/src/interfaces/timeline.ts @@ -1,6 +1,8 @@ +import { DateTime } from "luxon"; + export interface timelineEntry { event: string; eventDetail?: string; - date: string; + date: DateTime; description?: string; } diff --git a/src/interfaces/yt-video.ts b/src/interfaces/video.ts similarity index 100% rename from src/interfaces/yt-video.ts rename to src/interfaces/video.ts diff --git a/src/layouts/BaseLayout.astro b/src/layouts/BaseLayout.astro index 24e2e8f..6e91dc0 100644 --- a/src/layouts/BaseLayout.astro +++ b/src/layouts/BaseLayout.astro @@ -46,7 +46,7 @@ const pageEnabled = pathToMetadata(Astro.url.pathname).enabled ?? true; class="grow overflow-x-hidden overflow-y-scroll" > -
+
{ showTitle && pageEnabled && ( diff --git a/src/pages/education.astro b/src/pages/education.astro index a64fd14..3b07d9e 100644 --- a/src/pages/education.astro +++ b/src/pages/education.astro @@ -1,4 +1,6 @@ --- +import { DateTime } from "luxon"; + import BaseLayout from "@layouts/BaseLayout.astro"; import H2 from "@components/H2.astro"; @@ -25,12 +27,12 @@ const timeline: timelineEntry[] = [ { event: "High School Diploma", eventDetail: "Friday Harbor High School", - date: "June 2011", + date: DateTime.fromISO("2011-06-15"), }, { event: "B.S. Computer Science", eventDetail: "Oregon State University", - date: "June 2019", + date: DateTime.fromISO("2019-06-15"), }, ]; diff --git a/src/pages/experience/osu-ceoas-ocean-mixing-group/osu-ceoas-ocean-mixing-group.ts b/src/pages/experience/osu-ceoas-ocean-mixing-group/osu-ceoas-ocean-mixing-group.ts index 8f404b2..0bde20c 100644 --- a/src/pages/experience/osu-ceoas-ocean-mixing-group/osu-ceoas-ocean-mixing-group.ts +++ b/src/pages/experience/osu-ceoas-ocean-mixing-group/osu-ceoas-ocean-mixing-group.ts @@ -1,25 +1,27 @@ +import { DateTime } from "luxon"; + import type { timelineEntry } from "@interfaces/timeline.ts"; export const deploymentTimeline: timelineEntry[] = [ { event: "Setup & Ocean Trials", eventDetail: "Petersburg, AK", - date: "April 2017", + date: DateTime.fromISO("2017-04-01"), }, { event: "Glacier Deployment #1", eventDetail: "LeConte Glacier, AK", - date: "May 2017", + date: DateTime.fromISO("2017-05-01"), }, { event: "Glacier Deployment #2", eventDetail: "LeConte Glacier, AK", - date: "September 2017", + date: DateTime.fromISO("2017-09-01"), }, { event: "Scientific Paper Published", eventDetail: "The Oceanographic Society", - date: "September 2017", + date: DateTime.fromISO("2017-09-02"), }, ]; diff --git a/src/pages/experience/osu-ceoas-ocean-mixing-group/robotic-oceanographic-surface-sampler.astro b/src/pages/experience/osu-ceoas-ocean-mixing-group/robotic-oceanographic-surface-sampler.astro index 157575c..7488dcc 100644 --- a/src/pages/experience/osu-ceoas-ocean-mixing-group/robotic-oceanographic-surface-sampler.astro +++ b/src/pages/experience/osu-ceoas-ocean-mixing-group/robotic-oceanographic-surface-sampler.astro @@ -30,6 +30,7 @@ import publication from "@assets/experience/osu-ceoas-ocean-mixing-group/robotic import ross_team from "@assets/experience/osu-ceoas-ocean-mixing-group/robotic-oceanographic-surface-sampler/ross-team.jpg"; import ui from "@assets/experience/osu-ceoas-ocean-mixing-group/robotic-oceanographic-surface-sampler/ui.jpg"; +import { DateTime } from "luxon"; import { deploymentTimeline, subTitles, @@ -53,13 +54,13 @@ const timeline: timelineEntry[] = [ { event: "Started", eventDetail: "Joined ROSS", - date: "April 2016", + date: DateTime.fromISO("2016-04-01"), }, ...deploymentTimeline, { event: "Finished", eventDetail: "Left ROSS", - date: "May 2018", + date: DateTime.fromISO("2018-05-01"), }, ]; diff --git a/src/pages/experience/osu-robotics-club/mars-rover-software-team-lead.astro b/src/pages/experience/osu-robotics-club/mars-rover-software-team-lead.astro index c784130..57aa706 100644 --- a/src/pages/experience/osu-robotics-club/mars-rover-software-team-lead.astro +++ b/src/pages/experience/osu-robotics-club/mars-rover-software-team-lead.astro @@ -1,11 +1,15 @@ --- +import ExperienceLayout from "@layouts/ExperienceLayout.astro"; + import H2 from "@components/H2.astro"; import Carousel from "@components/Media/CustomCarousel/CustomCarousel.astro"; import YtVideo from "@components/Media/YtVideo.astro"; import PageGroup from "@components/PageGroup.astro"; + import type { carouselGroup } from "@interfaces/image-carousel.ts"; -import type { videoConfig } from "@interfaces/yt-video.ts"; -import ExperienceLayout from "@layouts/ExperienceLayout.astro"; +import type { videoConfig } from "@interfaces/video.ts"; + +import { roverSubTitles } from "./osu-robotics-club.ts"; import circ_champions from "@assets/experience/osu-robotics-club/mars-rover-software-lead/circ-champions.jpg"; import corwin_at_competition from "@assets/experience/osu-robotics-club/mars-rover-software-lead/corwin-at-competition.jpg"; @@ -47,7 +51,7 @@ const videos: videoConfig[] = [ ]; --- - + diff --git a/src/pages/experience/osu-robotics-club/osu-robotics-club.ts b/src/pages/experience/osu-robotics-club/osu-robotics-club.ts new file mode 100644 index 0000000..a138c02 --- /dev/null +++ b/src/pages/experience/osu-robotics-club/osu-robotics-club.ts @@ -0,0 +1,3 @@ +export const subTitles = ["Oregon State University", "OSU Robotics Club"]; + +export const roverSubTitles = [...subTitles, "Mars Rover Team"]; diff --git a/src/pages/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator.astro b/src/pages/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator.astro index e04d8af..fc0dc0f 100644 --- a/src/pages/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator.astro +++ b/src/pages/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator.astro @@ -1,5 +1,235 @@ --- import ExperienceLayout from "@layouts/ExperienceLayout.astro"; + +import H2 from "@components/H2.astro"; +import H3 from "@components/H3.astro"; +import Li from "@components/Li.astro"; +import CustomCarousel from "@components/Media/CustomCarousel/CustomCarousel.astro"; +import PageGroup from "@components/PageGroup.astro"; +import Paragraph from "@components/Paragraph.astro"; +import Paragraphs from "@components/Paragraphs.astro"; +import PrintedCircuitBoard from "@components/PrintedCircuitBoard.astro"; +import SkillMatrix from "@components/SkillMatrix/SkillMatrix.astro"; +import Timeline from "@components/Timeline/Timeline.astro"; +import Ul from "@components/Ul.astro"; + +import type { carouselGroup } from "@interfaces/image-carousel.ts"; +import { timelineFromPrintedCircuitBoard } from "@interfaces/printed-circuit-board.ts"; +import type { categorySkills } from "@interfaces/skill-matrix.ts"; +import type { timelineEntry } from "@interfaces/timeline.ts"; + +import { dechorionatorPcb } from "./dechorionator.ts"; +import { + subTitles, + workingTimeline, +} from "./osu-sinnhuber-aquatic-research-laboratory.ts"; + +import assembly_internal_overview from "@assets/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator/assembly-internal-overview.jpg"; +import assembly_pcb_connected from "@assets/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator/assembly-pcb-connected.jpg"; +import assembly_pcb_front_on from "@assets/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator/assembly-pcb-front-on.jpg"; +import assembly_pcb_front from "@assets/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator/assembly-pcb-front.jpg"; +import assembly_pcb_rear from "@assets/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator/assembly-pcb-rear.jpg"; +import assembly_surround_front from "@assets/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator/assembly-surround-front.jpg"; +import assembly_surround_rear from "@assets/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator/assembly-surround-rear.jpg"; +import off_front_lid_open from "@assets/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator/off-front-lid-open.jpg"; +import off_front from "@assets/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator/off-front.jpg"; +import on_front_closeup from "@assets/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator/on-front-closeup.jpg"; +import on_front from "@assets/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator/on-front.jpg"; +import rear_water_manifold from "@assets/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator/rear-water-manifold.jpg"; +import rear from "@assets/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator/rear.jpg"; +import top_drain from "@assets/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator/top-drain.jpg"; +import top_holder_closeup from "@assets/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator/top-holder-closeup.jpg"; +import top_lid_open from "@assets/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator/top-lid-open.jpg"; +import top_showerhead from "@assets/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator/top-showerhead.jpg"; +import travel_setup from "@assets/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator/travel-setup.jpg"; +import InlineLink from "@components/InlineLink.astro"; +import PopoverWordDefinition from "@components/PopoverWordDefinition.astro"; + +const headerCarouselGroup: carouselGroup = { + animation: "slide", + images: [ + off_front, + off_front_lid_open, + on_front, + on_front_closeup, + top_lid_open, + top_showerhead, + top_drain, + top_holder_closeup, + rear, + rear_water_manifold, + travel_setup, + + assembly_surround_front, + assembly_surround_rear, + assembly_pcb_rear, + assembly_pcb_front, + assembly_pcb_front_on, + assembly_pcb_connected, + assembly_internal_overview, + ], +}; + +const timeline: timelineEntry[] = [ + ...workingTimeline, + ...timelineFromPrintedCircuitBoard(dechorionatorPcb), +]; + +const categorizedSkills: categorySkills[] = [ + { + category: "Electrical", + skills: [ + { + item: "Schematic & PCB Design", + subItems: [ + { item: "Mentor Graphics PADS" }, + { item: "Altium Designer" }, + ], + }, + { + item: "PCB Assembly & Rework", + subItems: [ + { item: "Handheld Soldering" }, + { item: "Handheld Hot-Air Reflow" }, + { item: "Oven Reflow" }, + ], + }, + { + item: "Electrical Diagnostics", + subItems: [{ item: "Multimeters" }, { item: "Oscilloscopes" }], + }, + ], + }, + { + category: "Software & Environments", + skills: [ + { item: "Git" }, + { + item: "Programming", + subItems: [{ item: "Low-Level Embedded C/C++ (Atmel Studio)" }], + }, + ], + }, +]; --- - + + + +

Summary

+ +

Timeline

+ +
+ +

Key Takeaways

+
    +
  • Created an all-in-one tool for removing the chorions of zebrafish + embryos in a controlled and repeatable manner
  • +
  • Developed custom PCBs to handle motion, pump control, and user + interaction
  • +
  • Deployed multiple units to the lab, and one to an east-coast partner + laboratory
  • +
  • Cost reduced to roughly 1/5 that of the lab's previous dechorionation + hardware
  • +
+
+ +
+ +

Details

+ + + Before delving into what was built, some quick context is probably + needed. A dechorionator is a device that removes chorions from embryos. Chorions are the outer membranes of an embryo which provide + protection, and a permeable membrane which can allow gasses and nutrients + to reach the developing animal inside. As SARL is a toxicology lab, and its + experiments need to be deterministic, this protective layer can drastically + skew tests results, and even worse, can can variances embryo to embryo, or + egg batch to egg batch. To remove this, a special protein is added to a petri-dish + full of embryos, and then the dish is gently swirled with jerking start and + stop motions. The goal is to provide light agitation between the embryo, the + dish, and their neighbors, helping the protein eat away the chorion and sluff + off into the dish. This can, and has been done by hand, but when I joined + SARL they already had two machines which which could automatically perform + this task. However, they were incredibly expensive and massively overcomplicated, + requiring a whole table's worth of custom shaker units, networked peristaltic + pumps, and servos. The engineering team was tasked with simplifying this setup + while reducing both their size and cost. + + + We started with a shaker unit from the + company ELMI, which had a stepper-motor-based drive system, making it a perfect + candidate for easy retrofit. After gutting the existing electronics, and taking + some measurements, I started on a custom PCB design. Basic requirements were + that the board needed to be able to control the stepper motor, control the + speed of a liquid pump, provide controls to users, allow for config editing + from those controls, and provide a screen for cycle progress and editing those + config values. Since this was one of the first PCBs I'd ever designed and + hand-assembled, I started with a basic proof-of-concept which was for bench + use only (revision: 1.1.0). While I worked on the electronics, my co-worker + and good friend Dylan Thrush was busy designing a top-plate for the shaker to hold the dishes, shower + them with water, and drain the pumped-in liquid. + + + First tests showed that the overall concept was going to work, just + needing signal conditioning for the rotary encoder to avoid ghosted or + missing inputs. A larger problem we found was that the brushed-dc-motor + driven peristaltic pump was not going to be able to supply the flowrate + needed to properly shower the four dishes. We'd already chosen one of + the highest-flowrate pumps which could fit inside the shaker housing, + and ended up having to pivot to a much more expensive one from TCS + Micropumps. Luckily, not only did it solve our flowrate problem, but + also held up much better to the saltwater solution being pumped through + it than our initial choice. + + + With the proof-of-concept design functional, I began a redesign of the + control PCB to replace the existing control panel and drive circuitry + from the ELMI shaker (revision: 3.0.0). The existing control circuitry + had a unique assembly design that I'd not encountered before, using a + PCB with solderable standoffs as the front panel, and soldered copper + strips as retention tabs. I was so fascinated by the design that I + decided to emulate it. Check out the images at the end of the reel above + to see how this unique assembly was put together! Around the time that + the PCBs were ready, we'd hired a new engineer, Aaron Rito, who I tasked with writing the firmware while providing input and + guidance. + + + Over the next few months, many revisions were made to the firmware, as + well as mechanical designs for the showerheads and water manifold. Dylan + also had a final design for the top-plate milled out that looked + beautiful. Once those changes were complete, we provided the prototype + unit to the researchers, along with documentation on how to use the + tuning values. They then spent a few weeks running the new dechorionator + alongside the old ones, while tweaking these parameters until the + performance matched. We then built up four more units, and pre-flashed + them with this configuration. Three of these went into the lab, where a + total of four of our new dechorionators sat on the same table where just + two prior-generation ones used to live. It even had additional space for + pre and post prep work on the petri-dishes! The last one I installed in + a partner lab on the east coast after flying there with the head of the + lab, Robyn Tanguay and deputy director, Lisa Truong. + + +
+ +

Printed Circuit Boards

+ +
+
diff --git a/src/pages/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator.ts b/src/pages/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator.ts new file mode 100644 index 0000000..2bcbc97 --- /dev/null +++ b/src/pages/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator.ts @@ -0,0 +1,56 @@ +import { DateTime } from "luxon"; + +import type { printedCircuitBoard } from "@interfaces/printed-circuit-board.ts"; + +import pcb_1_1_0_assembled_bottom_angle from "@assets/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator/pcbs/1-1-0/assembled-bottom-angle.jpg"; +import pcb_1_1_0_assembled_bottom from "@assets/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator/pcbs/1-1-0/assembled-bottom.jpg"; +import pcb_1_1_0_assembled_side from "@assets/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator/pcbs/1-1-0/assembled-side.jpg"; +import pcb_1_1_0_bare_bottom from "@assets/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator/pcbs/1-1-0/bare-bottom.png"; +import pcb_1_1_0_bare_top from "@assets/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator/pcbs/1-1-0/bare-top.png"; +import assembled_main_bottom from "@assets/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator/pcbs/3-0-0/assembled-main-bottom.jpg"; +import assembled_side from "@assets/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator/pcbs/3-0-0/assembled-side.jpg"; +import bare_main_bottom from "@assets/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator/pcbs/3-0-0/bare-main-bottom.jpg"; +import bare_main_top from "@assets/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator/pcbs/3-0-0/bare-main-top.jpg"; +import bare_surround_bottom from "@assets/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator/pcbs/3-0-0/bare-surround-bottom.jpg"; +import bare_surround_top from "@assets/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator/pcbs/3-0-0/bare-surround-top.jpg"; +import half_assembled_main_top_surround_bottom_lcd from "@assets/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator/pcbs/3-0-0/half-assembled-main-top-surround-bottom-lcd.jpg"; +import half_assembled_main_top_surround_bottom from "@assets/experience/osu-sinnhuber-aquatic-research-laboratory/dechorionator/pcbs/3-0-0/half-assembled-main-top-surround-bottom.jpg"; + +export const dechorionatorPcb: printedCircuitBoard = { + name: "Dechorionator", + description: + "Control board which provides motion and water flow control, along with user control and monitoring.", + + revisions: [ + { + major: 3, + minor: 0, + patch: 0, + date: DateTime.fromISO("2015-08-30"), + images: [ + half_assembled_main_top_surround_bottom, + half_assembled_main_top_surround_bottom_lcd, + assembled_main_bottom, + assembled_side, + bare_main_top, + bare_main_bottom, + bare_surround_top, + bare_surround_bottom, + ], + }, + { + major: 1, + minor: 1, + patch: 0, + date: DateTime.fromISO("2014-05-10"), + images: [ + pcb_1_1_0_assembled_bottom_angle, + pcb_1_1_0_assembled_bottom, + pcb_1_1_0_assembled_side, + pcb_1_1_0_bare_top, + pcb_1_1_0_bare_bottom, + ], + // notes: [{ item: "Effective first functional revision" }], + }, + ], +}; diff --git a/src/pages/experience/osu-sinnhuber-aquatic-research-laboratory/osu-sinnhuber-aquatic-research-laboratory.ts b/src/pages/experience/osu-sinnhuber-aquatic-research-laboratory/osu-sinnhuber-aquatic-research-laboratory.ts new file mode 100644 index 0000000..c07ac78 --- /dev/null +++ b/src/pages/experience/osu-sinnhuber-aquatic-research-laboratory/osu-sinnhuber-aquatic-research-laboratory.ts @@ -0,0 +1,23 @@ +import { DateTime } from "luxon"; + +import type { timelineEntry } from "@interfaces/timeline.ts"; + +export const subTitles = [ + "Oregon State University", + "College of Agricultural Sciences", + "Department of Environmental and Molecular Toxicology", + "Sinnhuber Aquatic Research Laboratory", +]; + +export const workingTimeline: timelineEntry[] = [ + { + event: "Started", + eventDetail: "Joined SARL Engineering", + date: DateTime.fromISO("2013-09-01"), + }, + { + event: "Finished", + eventDetail: "Left SARL Engineering", + date: DateTime.fromISO("2019-08-01"), + }, +]; diff --git a/src/pages/experience/osu-sinnhuber-aquatic-research-laboratory/team-lead.astro b/src/pages/experience/osu-sinnhuber-aquatic-research-laboratory/team-lead.astro deleted file mode 100644 index cbaeec4..0000000 --- a/src/pages/experience/osu-sinnhuber-aquatic-research-laboratory/team-lead.astro +++ /dev/null @@ -1,5 +0,0 @@ ---- -import ExperienceLayout from "@layouts/ExperienceLayout.astro"; ---- - - diff --git a/src/pages/experience/spacex/avionics-test-engineering-internship.astro b/src/pages/experience/spacex/avionics-test-engineering-internship.astro index 4290856..4f8fe49 100644 --- a/src/pages/experience/spacex/avionics-test-engineering-internship.astro +++ b/src/pages/experience/spacex/avionics-test-engineering-internship.astro @@ -19,6 +19,7 @@ import swag from "@assets/experience/spacex/avionics-test-engineering-internship import type { carouselGroup } from "@interfaces/image-carousel.ts"; import type { categorySkills } from "@interfaces/skill-matrix.ts"; import type { timelineEntry } from "@interfaces/timeline.ts"; +import { DateTime } from "luxon"; const headerCarouselGroup: carouselGroup = { animation: "slide", @@ -28,11 +29,11 @@ const headerCarouselGroup: carouselGroup = { const timeline: timelineEntry[] = [ { event: "Started", - date: "January 2019", + date: DateTime.fromISO("2019-01-01"), }, { event: "Finished", - date: "March 2019", + date: DateTime.fromISO("2019-03-01"), }, ]; diff --git a/src/pages/experience/spacex/hardware-test-engineer-i-ii.astro b/src/pages/experience/spacex/hardware-test-engineer-i-ii.astro index af0d4a6..c5e8478 100644 --- a/src/pages/experience/spacex/hardware-test-engineer-i-ii.astro +++ b/src/pages/experience/spacex/hardware-test-engineer-i-ii.astro @@ -20,6 +20,7 @@ import type { timelineEntry } from "@interfaces/timeline.ts"; import five_year_patch from "@assets/experience/spacex/hardware-test-engineer-i-ii/five-year-patch.jpg"; import starlink_headquarters_selfie from "@assets/experience/spacex/hardware-test-engineer-i-ii/starlink-headquarters-selfie.jpg"; import starlink_patch from "@assets/experience/spacex/hardware-test-engineer-i-ii/starlink-patch.jpg"; +import { DateTime } from "luxon"; const headerCarouselGroup: carouselGroup = { animation: "slide", @@ -30,28 +31,28 @@ const timeline: timelineEntry[] = [ { event: "Started", eventDetail: "Satellite Hardware Test Team", - date: "September 2019", + date: DateTime.fromISO("2019-09-01"), description: "Owned test systems for four generations of Starlink flight computers and two generations of power boards", }, { event: "Transitioned To Remote", eventDetail: "Moved To Oregon", - date: "August 2022", + date: DateTime.fromISO("2022-08-01"), description: "Personal decision, but I was allowed to work on tools for the build reliability engineering team", }, { event: "Changed Teams", eventDetail: "Components Test Infra Team", - date: "March 2024", + date: DateTime.fromISO("2024-03-01"), description: "Vertical move that allowed for broader application of my skills", }, { event: "Finished", eventDetail: "Thanks for all the fish!", - date: "April 2025", + date: DateTime.fromISO("2025-04-01"), description: "Celebrated five and a half years of helping put thousands of satellites, and dozens of rockets, into orbit", }, diff --git a/src/pages/hobby/this-website.astro b/src/pages/hobby/this-website.astro index e7b8cea..5c068bb 100644 --- a/src/pages/hobby/this-website.astro +++ b/src/pages/hobby/this-website.astro @@ -103,16 +103,16 @@ const categorizedSkills: categorySkills[] = [ From the DevOps perspective, I created a Makefile within the repo for local development targets to build, run, and test both in a pure context, and within a Docker container. After pushing updates on a - branch to my local Gitea instance, and opening a pull request, the - website performs spelling checks, runs unit tests, and integration - tests. Once these pass, the website is built into a Docker container and - uploaded to the registry in my Gitea instance. The image is then - deployed to staging on my , allowing - for manual validation of the changes. In order to merge, the build, - test, and deploy actions must pass, and ideally I should be empirically - validating the staging deployment. After merging and closing the pull - request, another action builds, tests, and deploys the main branch in - the same way as before, but to production, and is what you see here! + branch to my local Gitea instance, and opening a pull request, an + actions runner performs spelling checks, runs unit tests, and + integration tests. Once these pass, the website is built into a Docker + container and uploaded to the registry in my Gitea instance. The image + is then deployed to staging on my , + allowing for manual validation of the changes. In order to merge, the + build, test, and deploy actions must pass, and I empirically validate + the deployment. Post-merge, a similar action builds, tests, and deploys + the main branch in the same way as before, but to production, and is + what you see here! diff --git a/src/pages/index.astro b/src/pages/index.astro index b950f26..03f4502 100644 --- a/src/pages/index.astro +++ b/src/pages/index.astro @@ -10,9 +10,9 @@ import Paragraphs from "@components/Paragraphs.astro"; import type { carouselGroup } from "@interfaces/image-carousel.ts"; -import alaska_bike_mountain_ocean from "@assets/about/alaska-bike-mountain-ocean.jpg"; import headshot from "@assets/about/headshot.jpg"; import circ_champions from "@assets/experience/osu-robotics-club/mars-rover-software-lead/circ-champions.jpg"; +import alaska_bike_mountain_ocean from "@assets/hobby/motorcycling/trips/2025-08-alaska/alaska-bike-mountain-ocean.jpg"; const headerCarouselGroup: carouselGroup = { animation: "slide", @@ -88,7 +88,7 @@ const headerCarouselGroup: carouselGroup = { >rfid implant in my hand! - +
If you're interested in contacting me, feel free to message on LinkedIn + diff --git a/src/pages/resume/2025-11-10-infrastructure-engineer.astro b/src/pages/resume/2025-11-10-infrastructure-engineer.astro index 2f97304..0d76c7f 100644 --- a/src/pages/resume/2025-11-10-infrastructure-engineer.astro +++ b/src/pages/resume/2025-11-10-infrastructure-engineer.astro @@ -4,4 +4,8 @@ import ResumeLayout from "@layouts/ResumeLayout.astro"; import resume from "@assets/resume/corwin_perren_2025-10-27_infrastructure_engineer.pdf"; --- - +