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
This commit is contained in:
@@ -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
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
|
||||
---
|
||||
|
||||
<h2 class="my-4 font-bold md:text-2xl">{Astro.props.text}</h2>
|
||||
@@ -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
5
src/components/H1.astro
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
|
||||
---
|
||||
|
||||
<h1 class="text-xl font-extrabold md:text-3xl"><slot /></h1>
|
||||
5
src/components/H2.astro
Normal file
5
src/components/H2.astro
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
|
||||
---
|
||||
|
||||
<h2 class="my-4 font-bold md:text-2xl"><slot /></h2>
|
||||
5
src/components/H3.astro
Normal file
5
src/components/H3.astro
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
|
||||
---
|
||||
|
||||
<h3 class="mt-4 mb-2 font-bold md:text-lg"><slot /></h3>
|
||||
@@ -1,14 +1,30 @@
|
||||
---
|
||||
interface Props {
|
||||
import type { ComponentPropsBase } from "@interfaces/components.ts";
|
||||
|
||||
interface Props extends ComponentPropsBase {
|
||||
href: 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 />
|
||||
</a>
|
||||
</>
|
||||
|
||||
@@ -14,6 +14,8 @@ const getHrefPath = (entry: navLink): string => {
|
||||
: "/" +
|
||||
(paths && paths.length ? [...paths, entry.path].join("/") : entry.path);
|
||||
};
|
||||
|
||||
const { pathname } = Astro.url;
|
||||
---
|
||||
|
||||
<ul
|
||||
@@ -26,14 +28,20 @@ const getHrefPath = (entry: navLink): string => {
|
||||
(entry.enabled ?? true) && (
|
||||
<li>
|
||||
{Array.isArray(entry.children) && entry.children.length ? (
|
||||
<div>
|
||||
<div
|
||||
class={
|
||||
pathname.startsWith(getHrefPath(entry))
|
||||
? "border-caperren-green border-b-2"
|
||||
: ""
|
||||
}
|
||||
>
|
||||
<button
|
||||
id={"dropdownNavbarLink" + getNavLinkSuffix(entry)}
|
||||
data-dropdown-toggle={
|
||||
"dropdownNavbar" + getNavLinkSuffix(entry)
|
||||
}
|
||||
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}
|
||||
<svg
|
||||
@@ -63,13 +71,24 @@ const getHrefPath = (entry: navLink): string => {
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<a
|
||||
href={getHrefPath(entry)}
|
||||
class="hover:text-caperren-green-light ring-caperren-green-dark block bg-transparent px-3 py-2 lg:p-0"
|
||||
aria-current="page"
|
||||
<div
|
||||
class={
|
||||
pathname === getHrefPath(entry)
|
||||
? "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>
|
||||
),
|
||||
|
||||
3
src/interfaces/components.ts
Normal file
3
src/interfaces/components.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
export interface ComponentPropsBase {
|
||||
class?: string;
|
||||
}
|
||||
@@ -2,6 +2,7 @@
|
||||
import "@styles/global.css";
|
||||
|
||||
import Footer from "@components/Footer.astro";
|
||||
import H1 from "@components/H1.astro";
|
||||
import Navbar from "@components/Navbar.astro";
|
||||
|
||||
import { pathToMetadata } from "@data/site-layout.ts";
|
||||
@@ -45,33 +46,23 @@ const pageEnabled = pathToMetadata(Astro.url.pathname).enabled ?? true;
|
||||
>
|
||||
<Navbar />
|
||||
<main class="mx-6 my-6">
|
||||
{
|
||||
title && showTitle && pageEnabled && (
|
||||
<h1
|
||||
class={
|
||||
"text-xl font-extrabold md:text-3xl " +
|
||||
(subTitles ? "" : "md:mb-6")
|
||||
}
|
||||
>
|
||||
{title}
|
||||
</h1>
|
||||
)
|
||||
}
|
||||
{
|
||||
showTitle &&
|
||||
pageEnabled &&
|
||||
subTitles?.map((subTitle, index) => (
|
||||
<p
|
||||
class={
|
||||
"text-sm font-bold md:text-xl " +
|
||||
(index == subTitles.length - 1 ? "mb-2 md:mb-6" : "")
|
||||
}
|
||||
>
|
||||
{subTitle}
|
||||
</p>
|
||||
))
|
||||
}
|
||||
{pageEnabled && <slot />}
|
||||
<div class="mb-2 md:mb-6">
|
||||
{
|
||||
title && showTitle && pageEnabled && (
|
||||
<H1 bottomMargin={!subTitles}>{title}</H1>
|
||||
)
|
||||
}
|
||||
{
|
||||
showTitle &&
|
||||
pageEnabled &&
|
||||
subTitles?.map((subTitle) => (
|
||||
<p class="text-sm font-bold md:text-xl">{subTitle}</p>
|
||||
))
|
||||
}
|
||||
</div>
|
||||
<div>
|
||||
{pageEnabled ? <slot /> : <H1>Under Construction</H1>}
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
<Footer />
|
||||
|
||||
@@ -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 Table from "@components/Table.astro";
|
||||
import Timeline from "@components/Timeline/Timeline.astro";
|
||||
import BaseLayout from "@layouts/BaseLayout.astro";
|
||||
|
||||
import type { carouselGroup } from "@interfaces/image-carousel.ts";
|
||||
import type { tableData } from "@interfaces/table.ts";
|
||||
@@ -104,14 +108,16 @@ const courseTable: tableData = {
|
||||
|
||||
<BaseLayout title="Education">
|
||||
<Carousel carouselGroup={diplomaCarouselGroup} />
|
||||
<h2 class="my-4 font-bold underline md:text-2xl">Timeline</h2>
|
||||
<H2>Timeline</H2>
|
||||
<Timeline timeline={timeline} />
|
||||
<h2 class="my-4 font-bold underline md:text-2xl">Oregon State University</h2>
|
||||
<a
|
||||
class="my-4 font-bold text-blue-500 underline hover:text-blue-300 md:text-lg"
|
||||
href="https://github.com/caperren/school_archives/tree/master/OSU%20Coursework"
|
||||
>Coursework Archives</a
|
||||
>
|
||||
<h3 class="my-4 font-bold underline md:text-lg">Course Listing</h3>
|
||||
<H2>Oregon State University</H2>
|
||||
<H3>
|
||||
<InlineLink
|
||||
class="font-bold md:text-lg"
|
||||
href="https://github.com/caperren/school_archives/tree/master/OSU%20Coursework"
|
||||
>Coursework Archives</InlineLink
|
||||
>
|
||||
</H3>
|
||||
<H3>Course Listing</H3>
|
||||
<Table data={courseTable} />
|
||||
</BaseLayout>
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
---
|
||||
import ExperienceLayout from "@layouts/ExperienceLayout.astro";
|
||||
|
||||
import H2 from "@components/CustomHtmlWrappers/H2.astro";
|
||||
import H3 from "@components/CustomHtmlWrappers/H3.astro";
|
||||
import H2 from "@components/H2.astro";
|
||||
import H3 from "@components/H3.astro";
|
||||
import Carousel from "@components/Media/CustomCarousel/CustomCarousel.astro";
|
||||
import Paragraph from "@components/Paragraph.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}>
|
||||
<Carousel carouselGroup={headerCarouselGroup} />
|
||||
<H2 text="Summary" />
|
||||
<H3 text="Timeline" />
|
||||
<H2>Summary</H2>
|
||||
<H3>Timeline</H3>
|
||||
<Timeline timeline={deploymentTimeline} />
|
||||
<H3 text="Location" />
|
||||
<H3>Location</H3>
|
||||
<iframe
|
||||
class="w-full"
|
||||
width="600"
|
||||
height="450"
|
||||
src="https://maps.google.com/maps?q=leconte%20glacier&t=k&z=11&ie=UTF8&iwloc=B&output=embed"
|
||||
></iframe>
|
||||
<H2 text="Details" />
|
||||
<H2>Details</H2>
|
||||
<Paragraphs>
|
||||
<Paragraph>
|
||||
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.
|
||||
</Paragraph>
|
||||
</Paragraphs>
|
||||
<H2 text="Videos" />
|
||||
<H2>Videos</H2>
|
||||
<div class="grid grid-cols-1 gap-4 md:grid-cols-2">
|
||||
{
|
||||
videos.map((video) => (
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
---
|
||||
import ExperienceLayout from "@layouts/ExperienceLayout.astro";
|
||||
|
||||
import H2 from "@components/CustomHtmlWrappers/H2.astro";
|
||||
import H3 from "@components/CustomHtmlWrappers/H3.astro";
|
||||
import H2 from "@components/H2.astro";
|
||||
import H3 from "@components/H3.astro";
|
||||
import LinkButton from "@components/LinkButton.astro";
|
||||
import Carousel from "@components/Media/CustomCarousel/CustomCarousel.astro";
|
||||
import PdfViewer from "@components/Media/PdfViewer.astro";
|
||||
@@ -63,10 +63,10 @@ const timeline: timelineEntry[] = [
|
||||
title="Official Scientific Publication"
|
||||
/>
|
||||
</div>
|
||||
<H2 text="Summary" />
|
||||
<H3 text="Timeline" />
|
||||
<H2>Summary</H2>
|
||||
<H3>Timeline</H3>
|
||||
<Timeline timeline={timeline} />
|
||||
<H3 text="Key Takeaways" />
|
||||
<H3>Key Takeaways</H3>
|
||||
<ul class="list-inside list-disc">
|
||||
<li>
|
||||
<div class="inline-block">
|
||||
@@ -103,9 +103,9 @@ const timeline: timelineEntry[] = [
|
||||
<hr class="text-caperren-green" />
|
||||
</div>
|
||||
</div>
|
||||
<H2 text="Details" />
|
||||
<H2>Details</H2>
|
||||
power and voltage logging
|
||||
<H2 text="Official Scientific Publication" />
|
||||
<H2>Official Scientific Publication</H2>
|
||||
<div class="h-334">
|
||||
<PdfViewer pdf={publication} />
|
||||
</div>
|
||||
|
||||
@@ -1,7 +1,13 @@
|
||||
---
|
||||
import Carousel from "@components/Media/CustomCarousel/CustomCarousel.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 injection_site from "@assets/hobby/body-mods/rfid-implant/injection-site.jpg";
|
||||
@@ -21,42 +27,42 @@ const rfidImplantCarouselGroup: carouselGroup = {
|
||||
---
|
||||
|
||||
<HobbyLayout title="Body Mods">
|
||||
<h2 class="my-4 font-bold underline md:text-2xl">RFID Implant</h2>
|
||||
<H2>RFID Implant</H2>
|
||||
<Carousel carouselGroup={rfidImplantCarouselGroup} />
|
||||
<p class="mt-4">
|
||||
Back when I was in college, a few of my friends and I got this crazy idea to
|
||||
all get RFID implants together. They are essentially the same things you'd
|
||||
use to microchip a pet, but with a slightly different firmware
|
||||
configuration, allowing scans with any 125KHz-compatible reader. The
|
||||
implants came from <a
|
||||
class="text-blue-500 hover:text-blue-300"
|
||||
href="https://dangerousthings.com/product/xem/">dangerousthings.com</a
|
||||
>, and we were lucky enough to have a vet-med student as a friend who made
|
||||
the installation a quick and painless process! I'm glad that I'm not afraid
|
||||
of needles, as the 16 gauge injector the kit came with was nothing to scoff
|
||||
at. Since healing, you would never know the implant was there, with the site
|
||||
leaving no scar or visible indication of its presence.
|
||||
</p>
|
||||
<p class="mt-4">
|
||||
With that out of the way, our group began work on hardware which would
|
||||
support the new implants. The goal was to have a generic usb-keyboard
|
||||
emulator for typing passwords with a valid scan, a car off-acc-on ignition
|
||||
replacement, and a fairly specialized modification to the OSU Robotics
|
||||
Club's doorway scanning system so they would support these on top of the
|
||||
official OSU ID cards. As tends to happen, life got busy, and only the
|
||||
usb-keyboard emulator actually came to fruition. The electronics and primary
|
||||
firmware were handled by <a
|
||||
class="text-blue-500 hover:text-blue-300"
|
||||
href="https://nickmccomb.net">Nick McComb</a
|
||||
>, enclosure by
|
||||
<a class="text-blue-500 hover:text-blue-300" href="https://dylanthrush.com"
|
||||
>Dylan Thrush</a
|
||||
>, 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
|
||||
the video on <a
|
||||
class="text-blue-500 hover:text-blue-300"
|
||||
href="https://nickmccomb.net/college/printed-circuit-boards/computer-access-module"
|
||||
>Nick's website</a
|
||||
>!
|
||||
</p>
|
||||
<H3>Details</H3>
|
||||
<Paragraphs>
|
||||
<Paragraph>
|
||||
Back when I was in college, a few of my friends and I got this crazy idea
|
||||
to all get RFID implants together. They are essentially the same things
|
||||
you'd use to microchip a pet, but with a slightly different firmware
|
||||
configuration, allowing scans with any 125KHz-compatible reader. The
|
||||
implants came from <InlineLink
|
||||
href="https://dangerousthings.com/product/xem/"
|
||||
>dangerousthings.com</InlineLink
|
||||
>, and we were lucky enough to have a vet-med student as a friend who made
|
||||
the installation a quick and painless process! I'm glad that I'm not
|
||||
afraid of needles, as the 16 gauge injector the kit came with was nothing
|
||||
to scoff at. Since healing, you would never know the implant was there,
|
||||
with the site leaving no scar or visible indication of its presence.
|
||||
</Paragraph>
|
||||
<Paragraph>
|
||||
With that out of the way, our group began work on hardware which would
|
||||
support the new implants. The goal was to have a generic usb-keyboard
|
||||
emulator for typing passwords with a valid scan, a car off-acc-on ignition
|
||||
replacement, and a fairly specialized modification to the OSU Robotics
|
||||
Club's doorway scanning system so they would support these on top of the
|
||||
official OSU ID cards. As tends to happen, life got busy, and only the
|
||||
usb-keyboard emulator actually came to fruition. The electronics and
|
||||
primary firmware were handled by <InlineLink href="https://nickmccomb.net"
|
||||
>Nick McComb</InlineLink
|
||||
>, enclosure by <InlineLink href="https://dylanthrush.com"
|
||||
>Dylan Thrush</InlineLink
|
||||
>, 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
|
||||
the video on <InlineLink
|
||||
href="https://nickmccomb.net/college/printed-circuit-boards/computer-access-module"
|
||||
>Nick's website</InlineLink
|
||||
>!
|
||||
</Paragraph>
|
||||
</Paragraphs>
|
||||
</HobbyLayout>
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
---
|
||||
import Carousel from "@components/Media/CustomCarousel/CustomCarousel.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 kz750 from "@assets/hobby/motorcycling/lineup/1979-kawasaki-kz750-senior-photo.jpg";
|
||||
@@ -37,15 +40,15 @@ const kz750CarouselGroup: carouselGroup = {
|
||||
---
|
||||
|
||||
<HobbyLayout title="Motorcycling - Lineup">
|
||||
<h2 class="my-4 font-bold underline md:text-2xl">Current Lineup</h2>
|
||||
<h3 class="my-4 font-bold underline md:text-lg">2015 Yamaha FJR 1300</h3>
|
||||
<H2>Current Lineup</H2>
|
||||
<H3>2015 Yamaha FJR 1300</H3>
|
||||
<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} />
|
||||
|
||||
<h2 class="my-4 font-bold underline md:text-2xl">Prior Lineup</h2>
|
||||
<h3 class="my-4 font-bold underline md:text-lg">2005 Suzuki DRZ 400</h3>
|
||||
<H2>Prior Lineup</H2>
|
||||
<H3>2005 Suzuki DRZ 400</H3>
|
||||
<Carousel carouselGroup={drzCarouselGroup} />
|
||||
|
||||
<h3 class="my-4 font-bold underline md:text-lg">
|
||||
@@ -53,9 +56,9 @@ const kz750CarouselGroup: carouselGroup = {
|
||||
</h3>
|
||||
<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} />
|
||||
|
||||
<h3 class="my-4 font-bold underline md:text-lg">1991 Kawasaki Ninja 600R</h3>
|
||||
<H3>1991 Kawasaki Ninja 600R</H3>
|
||||
<Carousel carouselGroup={ninjaCarouselGroup} />
|
||||
</HobbyLayout>
|
||||
|
||||
@@ -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 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";
|
||||
|
||||
@@ -16,81 +21,76 @@ const headerCarouselGroup: carouselGroup = {
|
||||
|
||||
<BaseLayout title="About" showTitle={false}>
|
||||
<Carousel carouselGroup={headerCarouselGroup} />
|
||||
<h2 class="my-4 font-bold underline md:text-2xl">Who Am I</h2>
|
||||
<p>
|
||||
My name is Corwin Perren, and I'm a multi-disciplinary engineer with a <a
|
||||
class="text-blue-500 hover:text-blue-300"
|
||||
href="/education">degree in computer science</a
|
||||
> 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
|
||||
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 solder, work on vehicles and engines, install and run Linux, manage enterprise
|
||||
computing infrastructure, build and repair computers, write scripts, and by the
|
||||
end of high school set out with a clear goal for my college years. I wanted to
|
||||
learn and teach myself enough to be able to think up almost any project, encompassing
|
||||
all facets of engineering, and be capable of driving it to completion with my
|
||||
own skill set.
|
||||
</p>
|
||||
<p class="mt-4">
|
||||
I think young me would be very pleased by how well I managed to achieve that
|
||||
goal! Through college, I learned electronics and PCB design, embedded and pc
|
||||
programming, basic mechanical design and fabrication, on top of learning how
|
||||
to work well with others in a team. I quickly realized that robotics was an
|
||||
ideal focus due to its inherent multi-disciplinary nature, and joined the
|
||||
OSU Robotics Club, which introduced me to people who are still my best
|
||||
friends today. Through student engineering jobs, I had the unique
|
||||
opportunity to work on some incredible projects such as the
|
||||
<a
|
||||
class="text-blue-500 hover:text-blue-300"
|
||||
href="/experience/osu-ceoas-ocean-mixing-group/robotic-oceanographic-surface-sampler"
|
||||
>robotic oceanographic surface sampler</a
|
||||
> and an <a
|
||||
class="text-blue-500 hover:text-blue-300"
|
||||
href="/experience/osu-sinnhuber-aquatic-research-laboratory/zebrafish-embryo-pick-and-plate"
|
||||
>embryo pick-and-plate machine</a
|
||||
>. 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 was
|
||||
the <a
|
||||
class="text-blue-500 hover:text-blue-300"
|
||||
href="/experience/osu-robotics-club/mars-rover-software-team-lead"
|
||||
>software lead</a
|
||||
>!
|
||||
</p>
|
||||
<p class="mt-4">
|
||||
After a short three-month <a
|
||||
class="text-blue-500 hover:text-blue-300"
|
||||
href="/experience/spacex/avionics-test-engineering-internship"
|
||||
>internship</a
|
||||
> at SpaceX in Hawthorne at the end of college, I applied for a <a
|
||||
class="text-blue-500 hover:text-blue-300"
|
||||
href="/experience/spacex/hardware-test-engineer-i-ii">test engineering</a
|
||||
> position with the company's Starlink team and was hired in mid-2019. For six
|
||||
years, I developed test system hardware, software, harnesses, mechanical fixtures,
|
||||
devops infrastructure, websites, and tooling to ensure that Starlink, Falcon,
|
||||
Dragon, and Starship component tests were producing well-validated and reliable
|
||||
hardware. Through it all, I got to apply and hone every skill I had developed,
|
||||
while learning countless more. Now though, it's on to the next adventure, whatever
|
||||
that may be!
|
||||
</p>
|
||||
<p class="mt-4">
|
||||
To learn more about my experiences, hobbies, interests, and skills, feel
|
||||
free to explore the site! While the short summary above provides some
|
||||
insight into who I am, it leaves out plenty! For example, I've been an avid <a
|
||||
class="text-blue-500 hover:text-blue-300"
|
||||
href="/hobby/motorcycling/lineup">motorcycle rider</a
|
||||
> since I was sixteen, and have an <a
|
||||
class="text-blue-500 hover:text-blue-300"
|
||||
href="/hobby/body-mods">rfid implant</a
|
||||
> in my hand!
|
||||
</p>
|
||||
<p class="mt-4">
|
||||
If you're interested in contacting me, feel free to message on <a
|
||||
class="text-blue-500 hover:text-blue-300"
|
||||
href="https://github.com/caperren">LinkedIn</a
|
||||
>, 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>
|
||||
<H2>Who Am I</H2>
|
||||
<Paragraphs>
|
||||
<Paragraph>
|
||||
My name is Corwin Perren, and I'm a multi-disciplinary engineer with a <InlineLink
|
||||
href="/education">degree in computer science</InlineLink
|
||||
> 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
|
||||
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 solder, work on vehicles and engines, install and run Linux, manage
|
||||
enterprise computing infrastructure, build and repair computers, write scripts,
|
||||
and by the end of high school set out with a clear goal for my college years.
|
||||
I wanted to learn and teach myself enough to be able to think up almost any
|
||||
project, encompassing all facets of engineering, and be capable of driving it
|
||||
to completion with my own skill set.
|
||||
</Paragraph>
|
||||
<Paragraph>
|
||||
I think young me would be very pleased by how well I managed to achieve
|
||||
that goal! Through college, I learned electronics and PCB design, embedded
|
||||
and pc programming, basic mechanical design and fabrication, on top of
|
||||
learning how to work well with others in a team. I quickly realized that
|
||||
robotics was an ideal focus due to its inherent multi-disciplinary nature,
|
||||
and joined the OSU Robotics Club, which introduced me to people who are
|
||||
still my best friends today. Through student engineering jobs, I had the
|
||||
unique opportunity to work on some incredible projects such as the
|
||||
<InlineLink
|
||||
href="/experience/osu-ceoas-ocean-mixing-group/robotic-oceanographic-surface-sampler"
|
||||
>robotic oceanographic surface sampler</InlineLink
|
||||
>
|
||||
and an <InlineLink
|
||||
href="/experience/osu-sinnhuber-aquatic-research-laboratory/zebrafish-embryo-pick-and-plate"
|
||||
>embryo pick-and-plate machine</InlineLink
|
||||
>. 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
|
||||
was the <InlineLink
|
||||
href="/experience/osu-robotics-club/mars-rover-software-team-lead"
|
||||
>software lead</InlineLink
|
||||
>!
|
||||
</Paragraph>
|
||||
<Paragraph>
|
||||
After a short three-month <InlineLink
|
||||
href="/experience/spacex/avionics-test-engineering-internship"
|
||||
>internship</InlineLink
|
||||
> at SpaceX in Hawthorne at the end of college, I applied for a <InlineLink
|
||||
href="/experience/spacex/hardware-test-engineer-i-ii"
|
||||
>test engineering</InlineLink
|
||||
> position with the company's Starlink team and was hired in mid-2019. For six
|
||||
years, I developed test system hardware, software, harnesses, mechanical fixtures,
|
||||
devops infrastructure, websites, and tooling to ensure that Starlink, Falcon,
|
||||
Dragon, and Starship component tests were producing well-validated and reliable
|
||||
hardware. Through it all, I got to apply and hone every skill I had developed,
|
||||
while learning countless more. Now though, it's on to the next adventure, whatever
|
||||
that may be!
|
||||
</Paragraph>
|
||||
<Paragraph>
|
||||
To learn more about my experiences, hobbies, interests, and skills, feel
|
||||
free to explore the site! While the short summary above provides some
|
||||
insight into who I am, it leaves out plenty! For example, I've been an
|
||||
avid <InlineLink href="/hobby/motorcycling/lineup"
|
||||
>motorcycle rider</InlineLink
|
||||
> since I was sixteen, and have an <InlineLink href="/hobby/body-mods"
|
||||
>rfid implant</InlineLink
|
||||
> in my hand!
|
||||
</Paragraph>
|
||||
<Paragraph>
|
||||
If you're interested in contacting me, feel free to message on <InlineLink
|
||||
href="https://github.com/caperren">LinkedIn</InlineLink
|
||||
>, or via the primary contact methods on my <InlineLink
|
||||
href="/resume/2025-11-10-infrastructure-engineer">resume</InlineLink
|
||||
>.
|
||||
</Paragraph>
|
||||
</Paragraphs>
|
||||
</BaseLayout>
|
||||
|
||||
@@ -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 resume from "@assets/resume/corwin_perren_2019-07-01_hardware_test_engineer.pdf";
|
||||
---
|
||||
|
||||
<ResumeLayout title="2019-07-01 - Hardware Test Engineer" resume={resume} />
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
---
|
||||
import resume from "@assets/resume/corwin_perren_2025-10-27-infrastructure_engineer.pdf";
|
||||
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} />
|
||||
|
||||
Reference in New Issue
Block a user