Removed unused build, refactored H1-3 to use slot based setup, added visual and aria page highlighting for navbar links, switched all pages to use custom H1-3, better new page/tab handling for inline links #12

Merged
caperren merged 1 commits from website-content-updates into main 2025-12-05 22:39:08 +00:00
18 changed files with 248 additions and 224 deletions
Showing only changes of commit 4b5f65bfdd - Show all commits

View File

@@ -1,27 +0,0 @@
name: Playwright Tests
on:
push:
branches: [main, master]
pull_request:
branches: [main, master]
jobs:
test:
timeout-minutes: 60
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: lts/*
- name: Install dependencies
run: npm ci
- name: Install Playwright Browsers
run: npx playwright install --with-deps
- name: Run Playwright tests
run: npx playwright test
- uses: actions/upload-artifact@v4
if: ${{ !cancelled() }}
with:
name: playwright-report
path: playwright-report/
retention-days: 30

View File

@@ -1,5 +0,0 @@
---
---
<h2 class="my-4 font-bold md:text-2xl">{Astro.props.text}</h2>

View File

@@ -1,5 +0,0 @@
---
---
<h3 class="mt-4 mb-2 font-bold md:text-lg">{Astro.props.text}</h3>

5
src/components/H1.astro Normal file
View File

@@ -0,0 +1,5 @@
---
---
<h1 class="text-xl font-extrabold md:text-3xl"><slot /></h1>

5
src/components/H2.astro Normal file
View File

@@ -0,0 +1,5 @@
---
---
<h2 class="my-4 font-bold md:text-2xl"><slot /></h2>

5
src/components/H3.astro Normal file
View File

@@ -0,0 +1,5 @@
---
---
<h3 class="mt-4 mb-2 font-bold md:text-lg"><slot /></h3>

View File

@@ -1,14 +1,30 @@
--- ---
interface Props { import type { ComponentPropsBase } from "@interfaces/components.ts";
interface Props extends ComponentPropsBase {
href: string; href: string;
target?: string; target?: string;
} }
const { href, target = "_blank" } = Astro.props; const { class: className, href, target } = Astro.props;
let finalTarget: string | undefined = target;
if (target === undefined) {
if (href.startsWith("/")) {
finalTarget = "";
} else {
finalTarget = "_blank";
}
}
--- ---
<> <>
<a class="text-blue-500 hover:text-blue-300" href={href} target={target}> <a
class:list={["text-blue-500", "hover:text-blue-300", className]}
href={href}
target={finalTarget}
>
<slot /> <slot />
</a> </a>
</> </>

View File

@@ -14,6 +14,8 @@ const getHrefPath = (entry: navLink): string => {
: "/" + : "/" +
(paths && paths.length ? [...paths, entry.path].join("/") : entry.path); (paths && paths.length ? [...paths, entry.path].join("/") : entry.path);
}; };
const { pathname } = Astro.url;
--- ---
<ul <ul
@@ -26,14 +28,20 @@ const getHrefPath = (entry: navLink): string => {
(entry.enabled ?? true) && ( (entry.enabled ?? true) && (
<li> <li>
{Array.isArray(entry.children) && entry.children.length ? ( {Array.isArray(entry.children) && entry.children.length ? (
<div> <div
class={
pathname.startsWith(getHrefPath(entry))
? "border-caperren-green border-b-2"
: ""
}
>
<button <button
id={"dropdownNavbarLink" + getNavLinkSuffix(entry)} id={"dropdownNavbarLink" + getNavLinkSuffix(entry)}
data-dropdown-toggle={ data-dropdown-toggle={
"dropdownNavbar" + getNavLinkSuffix(entry) "dropdownNavbar" + getNavLinkSuffix(entry)
} }
data-dropdown-placement="bottom" data-dropdown-placement="bottom"
class="hover:text-caperren-green-light lg:hover:text-caperren-green-light flex w-full items-center justify-between px-3 py-2 lg:border-0 lg:p-0 lg:hover:bg-transparent" class="hover:text-caperren-green-light lg:hover:text-caperren-green-light flex w-full items-center justify-between px-3 py-2 lg:p-0 lg:hover:bg-transparent"
> >
{entry.navText} {entry.navText}
<svg <svg
@@ -63,13 +71,24 @@ const getHrefPath = (entry: navLink): string => {
</div> </div>
</div> </div>
) : ( ) : (
<a <div
href={getHrefPath(entry)} class={
class="hover:text-caperren-green-light ring-caperren-green-dark block bg-transparent px-3 py-2 lg:p-0" pathname === getHrefPath(entry)
aria-current="page" ? "border-caperren-green border-b-2"
: ""
}
> >
{entry.navText} <a
</a> href={getHrefPath(entry)}
target={getHrefPath(entry).startsWith("/") ? "" : "_blank"}
class="hover:text-caperren-green-light ring-caperren-green-dark block bg-transparent px-3 py-2 lg:p-0"
aria-current={
pathname === getHrefPath(entry) ? "page" : undefined
}
>
{entry.navText}
</a>
</div>
)} )}
</li> </li>
), ),

View File

@@ -0,0 +1,3 @@
export interface ComponentPropsBase {
class?: string;
}

View File

@@ -2,6 +2,7 @@
import "@styles/global.css"; import "@styles/global.css";
import Footer from "@components/Footer.astro"; import Footer from "@components/Footer.astro";
import H1 from "@components/H1.astro";
import Navbar from "@components/Navbar.astro"; import Navbar from "@components/Navbar.astro";
import { pathToMetadata } from "@data/site-layout.ts"; import { pathToMetadata } from "@data/site-layout.ts";
@@ -45,33 +46,23 @@ const pageEnabled = pathToMetadata(Astro.url.pathname).enabled ?? true;
> >
<Navbar /> <Navbar />
<main class="mx-6 my-6"> <main class="mx-6 my-6">
{ <div class="mb-2 md:mb-6">
title && showTitle && pageEnabled && ( {
<h1 title && showTitle && pageEnabled && (
class={ <H1 bottomMargin={!subTitles}>{title}</H1>
"text-xl font-extrabold md:text-3xl " + )
(subTitles ? "" : "md:mb-6") }
} {
> showTitle &&
{title} pageEnabled &&
</h1> subTitles?.map((subTitle) => (
) <p class="text-sm font-bold md:text-xl">{subTitle}</p>
} ))
{ }
showTitle && </div>
pageEnabled && <div>
subTitles?.map((subTitle, index) => ( {pageEnabled ? <slot /> : <H1>Under Construction</H1>}
<p </div>
class={
"text-sm font-bold md:text-xl " +
(index == subTitles.length - 1 ? "mb-2 md:mb-6" : "")
}
>
{subTitle}
</p>
))
}
{pageEnabled && <slot />}
</main> </main>
</div> </div>
<Footer /> <Footer />

View File

@@ -1,8 +1,12 @@
--- ---
import BaseLayout from "@layouts/BaseLayout.astro";
import H2 from "@components/H2.astro";
import H3 from "@components/H3.astro";
import InlineLink from "@components/InlineLink.astro";
import Carousel from "@components/Media/CustomCarousel/CustomCarousel.astro"; import Carousel from "@components/Media/CustomCarousel/CustomCarousel.astro";
import Table from "@components/Table.astro"; import Table from "@components/Table.astro";
import Timeline from "@components/Timeline/Timeline.astro"; import Timeline from "@components/Timeline/Timeline.astro";
import BaseLayout from "@layouts/BaseLayout.astro";
import type { carouselGroup } from "@interfaces/image-carousel.ts"; import type { carouselGroup } from "@interfaces/image-carousel.ts";
import type { tableData } from "@interfaces/table.ts"; import type { tableData } from "@interfaces/table.ts";
@@ -104,14 +108,16 @@ const courseTable: tableData = {
<BaseLayout title="Education"> <BaseLayout title="Education">
<Carousel carouselGroup={diplomaCarouselGroup} /> <Carousel carouselGroup={diplomaCarouselGroup} />
<h2 class="my-4 font-bold underline md:text-2xl">Timeline</h2> <H2>Timeline</H2>
<Timeline timeline={timeline} /> <Timeline timeline={timeline} />
<h2 class="my-4 font-bold underline md:text-2xl">Oregon State University</h2> <H2>Oregon State University</H2>
<a <H3>
class="my-4 font-bold text-blue-500 underline hover:text-blue-300 md:text-lg" <InlineLink
href="https://github.com/caperren/school_archives/tree/master/OSU%20Coursework" class="font-bold md:text-lg"
>Coursework Archives</a href="https://github.com/caperren/school_archives/tree/master/OSU%20Coursework"
> >Coursework Archives</InlineLink
<h3 class="my-4 font-bold underline md:text-lg">Course Listing</h3> >
</H3>
<H3>Course Listing</H3>
<Table data={courseTable} /> <Table data={courseTable} />
</BaseLayout> </BaseLayout>

View File

@@ -1,8 +1,8 @@
--- ---
import ExperienceLayout from "@layouts/ExperienceLayout.astro"; import ExperienceLayout from "@layouts/ExperienceLayout.astro";
import H2 from "@components/CustomHtmlWrappers/H2.astro"; import H2 from "@components/H2.astro";
import H3 from "@components/CustomHtmlWrappers/H3.astro"; import H3 from "@components/H3.astro";
import Carousel from "@components/Media/CustomCarousel/CustomCarousel.astro"; import Carousel from "@components/Media/CustomCarousel/CustomCarousel.astro";
import Paragraph from "@components/Paragraph.astro"; import Paragraph from "@components/Paragraph.astro";
import Timeline from "@components/Timeline/Timeline.astro"; import Timeline from "@components/Timeline/Timeline.astro";
@@ -65,17 +65,17 @@ import { subTitles } from "./osu-ceoas-ocean-mixing-group.ts";
<ExperienceLayout title="LeConte Glacier Deployments" subTitles={subTitles}> <ExperienceLayout title="LeConte Glacier Deployments" subTitles={subTitles}>
<Carousel carouselGroup={headerCarouselGroup} /> <Carousel carouselGroup={headerCarouselGroup} />
<H2 text="Summary" /> <H2>Summary</H2>
<H3 text="Timeline" /> <H3>Timeline</H3>
<Timeline timeline={deploymentTimeline} /> <Timeline timeline={deploymentTimeline} />
<H3 text="Location" /> <H3>Location</H3>
<iframe <iframe
class="w-full" class="w-full"
width="600" width="600"
height="450" height="450"
src="https://maps.google.com/maps?q=leconte%20glacier&t=k&z=11&ie=UTF8&iwloc=B&output=embed" src="https://maps.google.com/maps?q=leconte%20glacier&t=k&z=11&ie=UTF8&iwloc=B&output=embed"
></iframe> ></iframe>
<H2 text="Details" /> <H2>Details</H2>
<Paragraphs> <Paragraphs>
<Paragraph> <Paragraph>
As part of my time working on the As part of my time working on the
@@ -122,7 +122,7 @@ import { subTitles } from "./osu-ceoas-ocean-mixing-group.ts";
on for the rest of my life. on for the rest of my life.
</Paragraph> </Paragraph>
</Paragraphs> </Paragraphs>
<H2 text="Videos" /> <H2>Videos</H2>
<div class="grid grid-cols-1 gap-4 md:grid-cols-2"> <div class="grid grid-cols-1 gap-4 md:grid-cols-2">
{ {
videos.map((video) => ( videos.map((video) => (

View File

@@ -1,8 +1,8 @@
--- ---
import ExperienceLayout from "@layouts/ExperienceLayout.astro"; import ExperienceLayout from "@layouts/ExperienceLayout.astro";
import H2 from "@components/CustomHtmlWrappers/H2.astro"; import H2 from "@components/H2.astro";
import H3 from "@components/CustomHtmlWrappers/H3.astro"; import H3 from "@components/H3.astro";
import LinkButton from "@components/LinkButton.astro"; import LinkButton from "@components/LinkButton.astro";
import Carousel from "@components/Media/CustomCarousel/CustomCarousel.astro"; import Carousel from "@components/Media/CustomCarousel/CustomCarousel.astro";
import PdfViewer from "@components/Media/PdfViewer.astro"; import PdfViewer from "@components/Media/PdfViewer.astro";
@@ -63,10 +63,10 @@ const timeline: timelineEntry[] = [
title="Official Scientific Publication" title="Official Scientific Publication"
/> />
</div> </div>
<H2 text="Summary" /> <H2>Summary</H2>
<H3 text="Timeline" /> <H3>Timeline</H3>
<Timeline timeline={timeline} /> <Timeline timeline={timeline} />
<H3 text="Key Takeaways" /> <H3>Key Takeaways</H3>
<ul class="list-inside list-disc"> <ul class="list-inside list-disc">
<li> <li>
<div class="inline-block"> <div class="inline-block">
@@ -103,9 +103,9 @@ const timeline: timelineEntry[] = [
<hr class="text-caperren-green" /> <hr class="text-caperren-green" />
</div> </div>
</div> </div>
<H2 text="Details" /> <H2>Details</H2>
power and voltage logging power and voltage logging
<H2 text="Official Scientific Publication" /> <H2>Official Scientific Publication</H2>
<div class="h-334"> <div class="h-334">
<PdfViewer pdf={publication} /> <PdfViewer pdf={publication} />
</div> </div>

View File

@@ -1,7 +1,13 @@
--- ---
import Carousel from "@components/Media/CustomCarousel/CustomCarousel.astro";
import HobbyLayout from "@layouts/HobbyLayout.astro"; import HobbyLayout from "@layouts/HobbyLayout.astro";
import H2 from "@components/H2.astro";
import H3 from "@components/H3.astro";
import InlineLink from "@components/InlineLink.astro";
import Carousel from "@components/Media/CustomCarousel/CustomCarousel.astro";
import Paragraph from "@components/Paragraph.astro";
import Paragraphs from "@components/Paragraphs.astro";
import type { carouselGroup } from "@interfaces/image-carousel.ts"; import type { carouselGroup } from "@interfaces/image-carousel.ts";
import injection_site from "@assets/hobby/body-mods/rfid-implant/injection-site.jpg"; import injection_site from "@assets/hobby/body-mods/rfid-implant/injection-site.jpg";
@@ -21,42 +27,42 @@ const rfidImplantCarouselGroup: carouselGroup = {
--- ---
<HobbyLayout title="Body Mods"> <HobbyLayout title="Body Mods">
<h2 class="my-4 font-bold underline md:text-2xl">RFID Implant</h2> <H2>RFID Implant</H2>
<Carousel carouselGroup={rfidImplantCarouselGroup} /> <Carousel carouselGroup={rfidImplantCarouselGroup} />
<p class="mt-4"> <H3>Details</H3>
Back when I was in college, a few of my friends and I got this crazy idea to <Paragraphs>
all get RFID implants together. They are essentially the same things you'd <Paragraph>
use to microchip a pet, but with a slightly different firmware Back when I was in college, a few of my friends and I got this crazy idea
configuration, allowing scans with any 125KHz-compatible reader. The to all get RFID implants together. They are essentially the same things
implants came from <a you'd use to microchip a pet, but with a slightly different firmware
class="text-blue-500 hover:text-blue-300" configuration, allowing scans with any 125KHz-compatible reader. The
href="https://dangerousthings.com/product/xem/">dangerousthings.com</a implants came from <InlineLink
>, and we were lucky enough to have a vet-med student as a friend who made href="https://dangerousthings.com/product/xem/"
the installation a quick and painless process! I'm glad that I'm not afraid >dangerousthings.com</InlineLink
of needles, as the 16 gauge injector the kit came with was nothing to scoff >, and we were lucky enough to have a vet-med student as a friend who made
at. Since healing, you would never know the implant was there, with the site the installation a quick and painless process! I'm glad that I'm not
leaving no scar or visible indication of its presence. afraid of needles, as the 16 gauge injector the kit came with was nothing
</p> to scoff at. Since healing, you would never know the implant was there,
<p class="mt-4"> with the site leaving no scar or visible indication of its presence.
With that out of the way, our group began work on hardware which would </Paragraph>
support the new implants. The goal was to have a generic usb-keyboard <Paragraph>
emulator for typing passwords with a valid scan, a car off-acc-on ignition With that out of the way, our group began work on hardware which would
replacement, and a fairly specialized modification to the OSU Robotics support the new implants. The goal was to have a generic usb-keyboard
Club's doorway scanning system so they would support these on top of the emulator for typing passwords with a valid scan, a car off-acc-on ignition
official OSU ID cards. As tends to happen, life got busy, and only the replacement, and a fairly specialized modification to the OSU Robotics
usb-keyboard emulator actually came to fruition. The electronics and primary Club's doorway scanning system so they would support these on top of the
firmware were handled by <a official OSU ID cards. As tends to happen, life got busy, and only the
class="text-blue-500 hover:text-blue-300" usb-keyboard emulator actually came to fruition. The electronics and
href="https://nickmccomb.net">Nick McComb</a primary firmware were handled by <InlineLink href="https://nickmccomb.net"
>, enclosure by >Nick McComb</InlineLink
<a class="text-blue-500 hover:text-blue-300" href="https://dylanthrush.com" >, enclosure by <InlineLink href="https://dylanthrush.com"
>Dylan Thrush</a >Dylan Thrush</InlineLink
>, and I supported some minor firmware development and debugging. If you >, and I supported some minor firmware development and debugging. If you
want to see an example of the keyboard emulator unlocking a PC, check out want to see an example of the keyboard emulator unlocking a PC, check out
the video on <a the video on <InlineLink
class="text-blue-500 hover:text-blue-300" href="https://nickmccomb.net/college/printed-circuit-boards/computer-access-module"
href="https://nickmccomb.net/college/printed-circuit-boards/computer-access-module" >Nick's website</InlineLink
>Nick's website</a >!
>! </Paragraph>
</p> </Paragraphs>
</HobbyLayout> </HobbyLayout>

View File

@@ -1,7 +1,10 @@
--- ---
import Carousel from "@components/Media/CustomCarousel/CustomCarousel.astro";
import HobbyLayout from "@layouts/HobbyLayout.astro"; import HobbyLayout from "@layouts/HobbyLayout.astro";
import H2 from "@components/H2.astro";
import H3 from "@components/H3.astro";
import Carousel from "@components/Media/CustomCarousel/CustomCarousel.astro";
import type { carouselGroup } from "@interfaces/image-carousel.ts"; import type { carouselGroup } from "@interfaces/image-carousel.ts";
import kz750 from "@assets/hobby/motorcycling/lineup/1979-kawasaki-kz750-senior-photo.jpg"; import kz750 from "@assets/hobby/motorcycling/lineup/1979-kawasaki-kz750-senior-photo.jpg";
@@ -37,15 +40,15 @@ const kz750CarouselGroup: carouselGroup = {
--- ---
<HobbyLayout title="Motorcycling - Lineup"> <HobbyLayout title="Motorcycling - Lineup">
<h2 class="my-4 font-bold underline md:text-2xl">Current Lineup</h2> <H2>Current Lineup</H2>
<h3 class="my-4 font-bold underline md:text-lg">2015 Yamaha FJR 1300</h3> <H3>2015 Yamaha FJR 1300</H3>
<Carousel carouselGroup={fjrCarouselGroup} /> <Carousel carouselGroup={fjrCarouselGroup} />
<h3 class="my-4 font-bold underline md:text-lg">2021 CSC SG400</h3> <H3>2021 CSC SG400</H3>
<Carousel carouselGroup={cscCarouselGroup} /> <Carousel carouselGroup={cscCarouselGroup} />
<h2 class="my-4 font-bold underline md:text-2xl">Prior Lineup</h2> <H2>Prior Lineup</H2>
<h3 class="my-4 font-bold underline md:text-lg">2005 Suzuki DRZ 400</h3> <H3>2005 Suzuki DRZ 400</H3>
<Carousel carouselGroup={drzCarouselGroup} /> <Carousel carouselGroup={drzCarouselGroup} />
<h3 class="my-4 font-bold underline md:text-lg"> <h3 class="my-4 font-bold underline md:text-lg">
@@ -53,9 +56,9 @@ const kz750CarouselGroup: carouselGroup = {
</h3> </h3>
<Carousel carouselGroup={concoursCarouselGroup} /> <Carousel carouselGroup={concoursCarouselGroup} />
<h3 class="my-4 font-bold underline md:text-lg">1979 Kawasaki KZ750</h3> <H3>1979 Kawasaki KZ750</H3>
<Carousel carouselGroup={kz750CarouselGroup} /> <Carousel carouselGroup={kz750CarouselGroup} />
<h3 class="my-4 font-bold underline md:text-lg">1991 Kawasaki Ninja 600R</h3> <H3>1991 Kawasaki Ninja 600R</H3>
<Carousel carouselGroup={ninjaCarouselGroup} /> <Carousel carouselGroup={ninjaCarouselGroup} />
</HobbyLayout> </HobbyLayout>

View File

@@ -1,6 +1,11 @@
--- ---
import BaseLayout from "@layouts/BaseLayout.astro";
import H2 from "@components/H2.astro";
import InlineLink from "@components/InlineLink.astro";
import Carousel from "@components/Media/CustomCarousel/CustomCarousel.astro"; import Carousel from "@components/Media/CustomCarousel/CustomCarousel.astro";
import BaseLayout from "../layouts/BaseLayout.astro"; import Paragraph from "@components/Paragraph.astro";
import Paragraphs from "@components/Paragraphs.astro";
import type { carouselGroup } from "@interfaces/image-carousel.ts"; import type { carouselGroup } from "@interfaces/image-carousel.ts";
@@ -16,81 +21,76 @@ const headerCarouselGroup: carouselGroup = {
<BaseLayout title="About" showTitle={false}> <BaseLayout title="About" showTitle={false}>
<Carousel carouselGroup={headerCarouselGroup} /> <Carousel carouselGroup={headerCarouselGroup} />
<h2 class="my-4 font-bold underline md:text-2xl">Who Am I</h2> <H2>Who Am I</H2>
<p> <Paragraphs>
My name is Corwin Perren, and I'm a multi-disciplinary engineer with a <a <Paragraph>
class="text-blue-500 hover:text-blue-300" My name is Corwin Perren, and I'm a multi-disciplinary engineer with a <InlineLink
href="/education">degree in computer science</a href="/education">degree in computer science</InlineLink
> from Oregon State University. For as long as I can remember, I've been fascinated > from Oregon State University. For as long as I can remember, I've been fascinated
by how things work, never being shy about taking them apart to learn the gritty by how things work, never being shy about taking them apart to learn the gritty
details. At a young age, I began tinkering, adding lights and fans and doorbells details. At a young age, I began tinkering, adding lights and fans and doorbells
to the pretend cardboard box houses my brother and I would play in. Later, I learned to the pretend cardboard box houses my brother and I would play in. Later, I
to solder, work on vehicles and engines, install and run Linux, manage enterprise learned to solder, work on vehicles and engines, install and run Linux, manage
computing infrastructure, build and repair computers, write scripts, and by the enterprise computing infrastructure, build and repair computers, write scripts,
end of high school set out with a clear goal for my college years. I wanted to and by the end of high school set out with a clear goal for my college years.
learn and teach myself enough to be able to think up almost any project, encompassing I wanted to learn and teach myself enough to be able to think up almost any
all facets of engineering, and be capable of driving it to completion with my project, encompassing all facets of engineering, and be capable of driving it
own skill set. to completion with my own skill set.
</p> </Paragraph>
<p class="mt-4"> <Paragraph>
I think young me would be very pleased by how well I managed to achieve that I think young me would be very pleased by how well I managed to achieve
goal! Through college, I learned electronics and PCB design, embedded and pc that goal! Through college, I learned electronics and PCB design, embedded
programming, basic mechanical design and fabrication, on top of learning how and pc programming, basic mechanical design and fabrication, on top of
to work well with others in a team. I quickly realized that robotics was an learning how to work well with others in a team. I quickly realized that
ideal focus due to its inherent multi-disciplinary nature, and joined the robotics was an ideal focus due to its inherent multi-disciplinary nature,
OSU Robotics Club, which introduced me to people who are still my best and joined the OSU Robotics Club, which introduced me to people who are
friends today. Through student engineering jobs, I had the unique still my best friends today. Through student engineering jobs, I had the
opportunity to work on some incredible projects such as the unique opportunity to work on some incredible projects such as the
<a <InlineLink
class="text-blue-500 hover:text-blue-300" href="/experience/osu-ceoas-ocean-mixing-group/robotic-oceanographic-surface-sampler"
href="/experience/osu-ceoas-ocean-mixing-group/robotic-oceanographic-surface-sampler" >robotic oceanographic surface sampler</InlineLink
>robotic oceanographic surface sampler</a >
> and an <a and an <InlineLink
class="text-blue-500 hover:text-blue-300" href="/experience/osu-sinnhuber-aquatic-research-laboratory/zebrafish-embryo-pick-and-plate"
href="/experience/osu-sinnhuber-aquatic-research-laboratory/zebrafish-embryo-pick-and-plate" >embryo pick-and-plate machine</InlineLink
>embryo pick-and-plate machine</a >. One my my proudest moments was when our club's mars rover took first
>. One my my proudest moments was when our club's mars rover took first place at the Candian International Rover Challenge in 2018, for which I
place at the Candian International Rover Challenge in 2018, for which I was was the <InlineLink
the <a href="/experience/osu-robotics-club/mars-rover-software-team-lead"
class="text-blue-500 hover:text-blue-300" >software lead</InlineLink
href="/experience/osu-robotics-club/mars-rover-software-team-lead" >!
>software lead</a </Paragraph>
>! <Paragraph>
</p> After a short three-month <InlineLink
<p class="mt-4"> href="/experience/spacex/avionics-test-engineering-internship"
After a short three-month <a >internship</InlineLink
class="text-blue-500 hover:text-blue-300" > at SpaceX in Hawthorne at the end of college, I applied for a <InlineLink
href="/experience/spacex/avionics-test-engineering-internship" href="/experience/spacex/hardware-test-engineer-i-ii"
>internship</a >test engineering</InlineLink
> at SpaceX in Hawthorne at the end of college, I applied for a <a > position with the company's Starlink team and was hired in mid-2019. For six
class="text-blue-500 hover:text-blue-300" years, I developed test system hardware, software, harnesses, mechanical fixtures,
href="/experience/spacex/hardware-test-engineer-i-ii">test engineering</a devops infrastructure, websites, and tooling to ensure that Starlink, Falcon,
> position with the company's Starlink team and was hired in mid-2019. For six Dragon, and Starship component tests were producing well-validated and reliable
years, I developed test system hardware, software, harnesses, mechanical fixtures, hardware. Through it all, I got to apply and hone every skill I had developed,
devops infrastructure, websites, and tooling to ensure that Starlink, Falcon, while learning countless more. Now though, it's on to the next adventure, whatever
Dragon, and Starship component tests were producing well-validated and reliable that may be!
hardware. Through it all, I got to apply and hone every skill I had developed, </Paragraph>
while learning countless more. Now though, it's on to the next adventure, whatever <Paragraph>
that may be! To learn more about my experiences, hobbies, interests, and skills, feel
</p> free to explore the site! While the short summary above provides some
<p class="mt-4"> insight into who I am, it leaves out plenty! For example, I've been an
To learn more about my experiences, hobbies, interests, and skills, feel avid <InlineLink href="/hobby/motorcycling/lineup"
free to explore the site! While the short summary above provides some >motorcycle rider</InlineLink
insight into who I am, it leaves out plenty! For example, I've been an avid <a > since I was sixteen, and have an <InlineLink href="/hobby/body-mods"
class="text-blue-500 hover:text-blue-300" >rfid implant</InlineLink
href="/hobby/motorcycling/lineup">motorcycle rider</a > in my hand!
> since I was sixteen, and have an <a </Paragraph>
class="text-blue-500 hover:text-blue-300" <Paragraph>
href="/hobby/body-mods">rfid implant</a If you're interested in contacting me, feel free to message on <InlineLink
> in my hand! href="https://github.com/caperren">LinkedIn</InlineLink
</p> >, or via the primary contact methods on my <InlineLink
<p class="mt-4"> href="/resume/2025-11-10-infrastructure-engineer">resume</InlineLink
If you're interested in contacting me, feel free to message on <a >.
class="text-blue-500 hover:text-blue-300" </Paragraph>
href="https://github.com/caperren">LinkedIn</a </Paragraphs>
>, or via the primary contact methods on my <a
class="text-blue-500 hover:text-blue-300"
href="/resume/2025-11-10-infrastructure-engineer">resume</a
>.
</p>
</BaseLayout> </BaseLayout>

View File

@@ -1,6 +1,7 @@
--- ---
import resume from "@assets/resume/corwin_perren_2019-07-01_hardware_test_engineer.pdf";
import ResumeLayout from "@layouts/ResumeLayout.astro"; import ResumeLayout from "@layouts/ResumeLayout.astro";
import resume from "@assets/resume/corwin_perren_2019-07-01_hardware_test_engineer.pdf";
--- ---
<ResumeLayout title="2019-07-01 - Hardware Test Engineer" resume={resume} /> <ResumeLayout title="2019-07-01 - Hardware Test Engineer" resume={resume} />

View File

@@ -1,6 +1,7 @@
--- ---
import resume from "@assets/resume/corwin_perren_2025-10-27-infrastructure_engineer.pdf";
import ResumeLayout from "@layouts/ResumeLayout.astro"; import ResumeLayout from "@layouts/ResumeLayout.astro";
import resume from "@assets/resume/corwin_perren_2025-10-27-infrastructure_engineer.pdf";
--- ---
<ResumeLayout title="2025-10-27 - Infrastructure Engineer" resume={resume} /> <ResumeLayout title="2025-10-27 - Infrastructure Engineer" resume={resume} />