Skip to main content
The resume site at ryan.war.re is Ryan Warren’s full online resume — a statically exported Next.js page that lists his technical skills, professional work history, side projects, and education. Like the main site, it uses a root redirect and hosts its content at /n.
Visiting ryan.war.re/ redirects to ryan.war.re/n via an HTML meta refresh tag, for the same reason as the main site: the project uses Next.js static export with no server available for HTTP-level redirects. A <noscript> fallback link is also included on the root page.

Resume Sections

The resume page is divided into four top-level sections, each introduced by an <Experience> heading component and populated by one or more <Activity> entries.

Technical Experience

Lists the programming languages, tools, and editors Ryan works with day-to-day, followed by a brief statement of engineering interests.

Relevant Work Experience

Chronological employment history from his 2012 student tech role at UW through his current Senior Software Engineer position at Stripe.

Related Activities

Personal projects and coursework, including the PiDuinoLock hardware project and ongoing web programming experience.

Education

Bachelor of Science in Computer Science and Software Engineering from the University of Washington, graduated June 2015.

Work Experience Entries

The following positions are rendered in reverse chronological order under the Relevant Work Experience heading.
RoleCompanyTeamPeriod
Senior Software EngineerStripeInternal ToolsMarch 2024 – Present
Software Engineer IIStripeInternal ToolsMarch 2021 – February 2024
Software Engineer IIAmazonAdsJuly 2019 – February 2021
Software EngineerAmazonAdsJuly 2017 – June 2019
Software Engineer IIPorchAugust 2016 – July 2017
Software EngineerPorchJuly 2015 – August 2016
Software Engineer InternTicketmaster/Live NationCommerce, Order ProcessingMarch 2015 – June 2015
Software Engineer InternTicketmaster/Live NationCommerce, Order ProcessingJune 2014 – December 2014
Web Development InternSporcleJune 2013 – June 2014
Technical Student AssistantUniversity of WashingtonJune 2012 – October 2013

React Components

The resume is assembled from four custom React components. Each has a narrow, well-defined responsibility.

Experience — Section Heading

The simplest component. It accepts a single heading string prop and renders it as an <h2>.
type ExperienceProps = {
  heading: string
}

export default function Experience(props: ExperienceProps) {
  return <h2>{props.heading}</h2>
}
Usage in the page:
<Experience heading={'Relevant Work Experience'} />

Activity — Individual Entry

Activity is the primary content component. It renders a single job, project, or coursework entry — including the title, company (optionally linked), team name, date range, auto-calculated duration, and a bullet list of accomplishments.
type ActivityProps = {
  name: string | ReactNode
  company?: string
  team?: string
  start?: string
  end: string
  items: Array<string | ReactNode>
  companyLink?: string
}
The name and each entry in items accept either a plain string or a full ReactNode. This allows inline links (via <ExperienceItem>) to be embedded directly inside bullet points — for example, referencing Authy for 2FA or Bitbucket for source control.
Duration calculation. When a start date is provided, Activity uses date-fns to calculate and display the elapsed time. The string "Present" is interpreted as today’s date.
import { intervalToDuration, parse } from 'date-fns'
import pluralize from 'pluralize'

function formatDuration(start: string, end: string): string {
  const endDate =
    end.toLowerCase() === 'present'
      ? new Date()
      : parse(end, 'MMMM yyyy', new Date())

  const interval = intervalToDuration({
    start: parse(start, 'MMMM yyyy', new Date()),
    end: endDate,
  })

  const parts = []
  if (interval.years && interval.years > 0)
    parts.push(`${interval.years} ${pluralize('Year', interval.years)}`)
  if (interval.months && interval.months > 0)
    parts.push(`${interval.months} ${pluralize('Month', interval.months)}`)

  return parts.join(' ')
}
The formatted duration is displayed in brackets next to the entry heading — for example, [3 Years 5 Months] — and is re-calculated at build time each time the site is deployed.

ActivityList — Bullet List of Accomplishments

ActivityList receives the items array from Activity and renders each entry as an <li> inside a <ul>. It handles both string and ReactNode items transparently.
type ActivityListProps = {
  items: Array<string | ReactNode>
}

export default function ActivityList(props: ActivityListProps) {
  return (
    <ul>
      {props.items.map((item, idx) => (
        <li key={`activity-list-${idx}`}>{item}</li>
      ))}
    </ul>
  )
}

ExperienceItem — Linked Skill or Technology Name

ExperienceItem renders either a plain text span or a hyperlink, depending on whether a url prop is provided. It is used in two ways:
  1. Inline within ActivityList items — to link third-party tools mentioned in bullet points (e.g., Authy, Nymi, WordPress).
  2. In the Technical Experience section — to render each technology and editor as a clickable link.
export type ExperienceItemProps = {
  name: string
  url?: string
}

export default function ExperienceItem(props: ExperienceItemProps) {
  if (props.url) {
    return (
      <a href={props.url} target="_blank" rel="noopener noreferrer">
        {props.name}
      </a>
    )
  }
  return <>{props.name}</>
}

Technical Experience Section

The Technical Experience section uses ActivityList directly (without an Activity wrapper) to display two bullet points. Each technology and editor name in those bullets is rendered as an <ExperienceItem> link. Technologies listed:
Language / ToolLink
Javajava.com
Rubyruby-lang.org
Reactreact.dev
Scalascala-lang.org
Gogo.dev
PHPphp.net
C++cplusplus.com
gitgit-scm.com
Bashgnu.org/software/bash
MySQLmysql.com
PostgreSQLpostgresql.org
Editors listed: Claude Code, Cursor, Vim, IntelliJ, vscode
The editors Claude Code, Cursor, Vim, and IntelliJ are defined in an editors array of ExperienceItemProps and mapped into linked items. vscode is appended separately after the mapped list as & vscode, linked to code.visualstudio.com.
The second bullet point reads: “Excited by backend and full stack platform development, with a curiosity for security and AI.”

Open Graph and Metadata

The resume page configures its <Head> with og:type set to profile (rather than website), and includes Open Graph profile fields alongside standard Twitter Card tags.
<meta property="og:type" content="profile" />
<meta property="og:url" content="https://ryan.war.re/n" />
<meta property="og:title" content="Ryan Warren - Resume" />
<meta property="og:description"
  content="Senior Software Engineer at Stripe. Experienced in Java, Ruby, React, Scala, Go, and more." />
<meta property="profile:first_name" content="Ryan" />
<meta property="profile:last_name" content="Warren" />
<meta property="og:image" content="https://ryan.war.re/og.svg" />
<meta property="og:image:width" content="1200" />
<meta property="og:image:height" content="630" />
<meta property="og:site_name" content="War.re" />

<meta name="twitter:card" content="summary" />
<meta name="twitter:title" content="Ryan Warren - Resume" />
<meta name="twitter:description" content="Senior Software Engineer at Stripe" />

<meta name="keywords"
  content="Ryan Warren, Software Engineer, Stripe, Resume, Java, Ruby, React, Scala, Go, Seattle" />
The robots and googlebot meta tags include noemailindex on the resume (unlike the main site), which prevents search engines from indexing the ryan@war.re email address that appears in the resume header.