1
0
Fork 0

Separate all visually different components into different files

main
Ethan Reece 2024-08-03 19:59:16 -05:00
parent 2dd6e8aaa3
commit af4d11b653
Signed by: me
GPG Key ID: 198E9EB433DB1B28
36 changed files with 585 additions and 465 deletions

View File

@ -1,5 +1,5 @@
default:
guix time-machine --channels=./channels.scm.lock -- shell --container --emulate-fhs --manifest=./manifest.scm -- typst compile ./src/main.typ ./out/resume.pdf --font-path=/usr/share/fonts
guix time-machine --channels=./channels.scm.lock -- shell --container --emulate-fhs --manifest=./manifest.scm -- typst compile ./src/document.typ ./out/resume.pdf --font-path=/usr/share/fonts
fonts:
guix time-machine --channels=./channels.scm.lock -- shell --container --emulate-fhs --manifest=./manifest.scm -- typst fonts --font-path=/usr/share/fonts

140
src/content.typ 100644
View File

@ -0,0 +1,140 @@
#let content = (
identity: (
name: "Ethan Reece",
email: "contact@ethanreece.com",
phone: "(208) 515-2094",
location: "Richardson, TX",
website: "https://ethanreece.com/"
),
skills: (
(
title: "DevOps and System Administration",
items: (
"Linux",
"Git",
"GitHub Actions",
"Docker",
"Guix",
),
),
(
title: "Programming Languages",
items: (
"JavaScript",
"C#",
"Java",
"C",
"C++",
"Guile/Scheme",
),
),
(
title: "Layout and Web Development",
items: (
"HTML",
"CSS",
"React",
"ASP.NET",
"Express.js",
"Astro",
"Typst",
),
),
),
education: (
(
title: "The University of Texas at Dallas",
degree: "Bachelor of Science in Computer Science",
graduation: "May 2026",
gpa: "Current GPA: 3.749",
coursework: (
completed: (
"Programming Language Paradigms",
"Digital Logic & Computer Design",
"Operating Systems Concepts",
"Probability and Statistics for CS",
"Data Structures and Algorithms",
"Software Engineering",
"C/C++ Programming in UNIX",
"Computer Architecture",
"Discrete Mathematics II",
),
current: (
"Database Systems",
"Advanced Algorithm Design & Analysis",
),
),
highlights: (
"Collegium V Honors Program",
),
),
),
work_experience: (
(
title: "Scrumfish Software",
location: "Nampa, ID",
timeframe: "June August (2022, 2023)",
role: "Software Engineering Intern",
skills: (
"C#/ASP.NET",
"JavaScript/React",
"Microsoft SQL Server",
"GitHub",
),
highlights: (
"Developed ASP.NET APIs for data management, multifactor authentication, and document conversion.",
"Created a React-based UI for a book critique platform, supporting document viewing, sharing, and annotation.",
"Automated the update of email templates in the database using SQL and PowerShell scripts.",
),
),
(
title: "R-Technics",
location: "Boise, ID",
timeframe: "June August (2022, 2023)",
role: "Software Engineering Intern",
skills: (
"Azure",
"Windows Server",
"Docker",
"C#/ASP.NET",
),
highlights: (
"Supported server maintenance through update research, implementation, and monitoring.",
"Developed a C# program to fetch song lyrics and metadata from an API, later integrated into the main product.",
"Enhanced a server application with Docker and Linux support; established an Azure DevOps pipeline for build automation.",
),
),
),
professional_development: (
(
title: "Personal Server Administration",
timeframe: "2020 Present",
role: "Hobby",
skills: (
"Linux",
"Docker",
"Guix/Guile",
"Git",
"Proxmox",
"Google Cloud",
),
highlights: (
"Manage a physical server using Proxmox, Debian VMs, and Docker for several applications.",
"Migrate new applications to Guix to utilize declarative configuration for reduced state, fine-grained system control, and increased resource efficiency.",
"Implement a VPN via Google Cloud Compute Engine to navigate CGNAT limitations.",
"Host various services including Forgejo, TrueNAS, Nextcloud, and Vaultwarden.",
),
),
(
title: "Cybersecurity Courses",
timeframe: "February 2023 November 2023",
role: "CodePath CYB101, CYB102",
skills: (
"Linux",
),
highlights: (
"Gained knowledge in cybersecurity tools and defense strategies.",
),
),
),
)

13
src/document.typ 100644
View File

@ -0,0 +1,13 @@
#{
import "content.typ": content
import "page/resume.typ": page_resume
set document(
title: "Resume",
author: content.identity.name,
keywords: "resume",
date: none,
)
page_resume(..content)
}

View File

@ -1,153 +0,0 @@
#{
import "page_resume.typ": page_resume
let config = (
identity: (
name: "Ethan Reece",
email: "contact@ethanreece.com",
phone: "(208) 515-2094",
location: "Richardson, TX",
website: "https://ethanreece.com/"
),
skills: (
(
title: "DevOps and System Administration",
items: (
"Linux",
"Git",
"GitHub Actions",
"Docker",
"Guix",
),
),
(
title: "Programming Languages",
items: (
"JavaScript",
"C#",
"Java",
"C",
"C++",
"Guile/Scheme",
),
),
(
title: "Layout and Web Development",
items: (
"HTML",
"CSS",
"React",
"ASP.NET",
"Express.js",
"Astro",
"Typst",
),
),
),
education: (
(
title: "The University of Texas at Dallas",
degree: "Bachelor of Science in Computer Science",
graduation: "May 2026",
gpa: "Current GPA: 3.749",
coursework: (
completed: (
"Programming Language Paradigms",
"Digital Logic & Computer Design",
"Operating Systems Concepts",
"Probability and Statistics for CS",
"Data Structures and Algorithms",
"Software Engineering",
"C/C++ Programming in UNIX",
"Computer Architecture",
"Discrete Mathematics II",
),
current: (
"Database Systems",
"Advanced Algorithm Design & Analysis",
),
),
highlights: (
"Collegium V Honors Program",
),
),
),
work_experience: (
(
title: "Scrumfish Software",
location: "Nampa, ID",
timeframe: "June August (2022, 2023)",
role: "Software Engineering Intern",
skills: (
"C#/ASP.NET",
"JavaScript/React",
"Microsoft SQL Server",
"GitHub",
),
highlights: (
"Developed ASP.NET APIs for data management, multifactor authentication, and document conversion.",
"Created a React-based UI for a book critique platform, supporting document viewing, sharing, and annotation.",
"Automated the update of email templates in the database using SQL and PowerShell scripts.",
),
),
(
title: "R-Technics",
location: "Boise, ID",
timeframe: "June August (2022, 2023)",
role: "Software Engineering Intern",
skills: (
"Azure",
"Windows Server",
"Docker",
"C#/ASP.NET",
),
highlights: (
"Supported server maintenance through update research, implementation, and monitoring.",
"Developed a C# program to fetch song lyrics and metadata from an API, later integrated into the main product.",
"Enhanced a server application with Docker and Linux support; established an Azure DevOps pipeline for build automation.",
),
),
),
professional_development: (
(
title: "Personal Server Administration",
timeframe: "2020 Present",
role: "Hobby",
skills: (
"Linux",
"Docker",
"Guix/Guile",
"Git",
"Proxmox",
"Google Cloud",
),
highlights: (
"Manage a physical server using Proxmox, Debian VMs, and Docker for several applications.",
"Migrate new applications to Guix to utilize declarative configuration for reduced state, fine-grained system control, and increased resource efficiency.",
"Implement a VPN via Google Cloud Compute Engine to navigate CGNAT limitations.",
"Host various services including Forgejo, TrueNAS, Nextcloud, and Vaultwarden.",
),
),
(
title: "Cybersecurity Courses",
timeframe: "February 2023 November 2023",
role: "CodePath CYB101, CYB102",
skills: (
"Linux",
),
highlights: (
"Gained knowledge in cybersecurity tools and defense strategies.",
),
),
),
)
set document(
title: "Resume",
author: config.identity.name,
keywords: "resume",
date: none,
)
page_resume(..config)
}

View File

@ -0,0 +1,64 @@
#let page_resume(
identity: (
name: "",
email: "",
phone: "",
location: "",
website: "",
),
skills: (
(
title: "",
items: (""),
),
),
education: (
(
title: "",
degree: "",
graduation: "",
gpa: "",
coursework: (""),
highlights: (""),
),
),
work_experience: (
(
title: "",
location: "",
timeframe: "",
role: "",
skills: (""),
highlights: (""),
),
),
professional_development: (
(
title: "",
timeframe: "",
role: "",
skills: (""),
highlights: (""),
),
),
) = {
import "../base/text.typ": base_text
import "../base/page.typ": base_page
import "resume/heading.typ": page_resume_heading
import "resume/content.typ": page_resume_content
base_page(
base_text(
grid(
gutter: 2.75em,
page_resume_heading(identity: identity),
page_resume_content(
skills: skills,
education: education,
work_experience: work_experience,
professional_development: professional_development,
)
)
)
)
}

View File

@ -0,0 +1,50 @@
#let page_resume_content(
skills: (
(
title: "",
items: (""),
),
),
education: (
(
title: "",
degree: "",
graduation: "",
gpa: "",
coursework: (""),
highlights: (""),
),
),
work_experience: (
(
title: "",
location: "",
timeframe: "",
role: "",
skills: (""),
highlights: (""),
),
),
professional_development: (
(
title: "",
timeframe: "",
role: "",
skills: (""),
highlights: (""),
),
),
) = {
import "../../section/skills.typ": section_skills
import "../../section/education.typ": section_education
import "../../section/work_experience.typ": section_work_experience
import "../../section/professional_development.typ": section_professional_development
grid(
gutter: 2.4em,
section_skills(skills: skills),
section_education(education: education),
section_work_experience(work_experience: work_experience),
section_professional_development(professional_development: professional_development),
)
}

View File

@ -0,0 +1,24 @@
#let page_resume_heading(
identity: (
name: "",
email: "",
phone: "",
location: "",
website: "",
),
) = {
import "heading/name.typ": page_resume_heading_name
import "heading/contact_info.typ": page_resume_heading_contact_info
grid(
gutter: 1.5em,
align: center,
page_resume_heading_name(name: identity.name),
page_resume_heading_contact_info(
email: identity.email,
phone: identity.phone,
location: identity.location,
website: identity.website,
),
)
}

View File

@ -0,0 +1,18 @@
#let page_resume_heading_contact_info(
email: "",
phone: "",
location: "",
website: "",
) = text(
size: 1.05em,
weight: "medium",
grid(
columns: 4,
rows: 1,
gutter: 4em,
email,
phone,
location,
website,
)
)

View File

@ -0,0 +1,13 @@
#let page_resume_heading_name(name: "") = {
import "../../../base/text.typ": base_text
heading(
base_text(
text(
size: 2.8em,
weight: "extrabold",
name
)
)
)
}

View File

@ -1,111 +0,0 @@
#let page_resume(
identity: (
name: "",
email: "",
phone: "",
location: "",
website: "",
),
skills: (
(
title: "",
items: (""),
),
),
education: (
(
title: "",
degree: "",
graduation: "",
gpa: "",
coursework: (""),
highlights: (""),
),
),
work_experience: (
(
title: "",
location: "",
timeframe: "",
role: "",
skills: (""),
highlights: (""),
),
),
professional_development: (
(
title: "",
timeframe: "",
role: "",
skills: (""),
highlights: (""),
),
),
) = {
import "base/text.typ": base_text
import "base/page.typ": base_page
import "section/identity.typ": section_identity
import "section/skills.typ": section_skills
import "section/education.typ": section_education
import "section/work_experience.typ": section_work_experience
import "section/professional_development.typ": section_professional_development
let resume_content(
skills: (
(
title: "",
items: (""),
),
),
education: (
(
title: "",
degree: "",
graduation: "",
gpa: "",
coursework: (""),
highlights: (""),
),
),
work_experience: (
(
title: "",
location: "",
timeframe: "",
role: "",
skills: (""),
highlights: (""),
),
),
professional_development: (
(
title: "",
timeframe: "",
role: "",
skills: (""),
highlights: (""),
),
),
) = grid(
gutter: 2.4em,
section_skills(skills: skills),
section_education(education: education),
section_work_experience(work_experience: work_experience),
section_professional_development(professional_development: professional_development),
)
base_page(
base_text(
grid(
gutter: 2.75em,
section_identity(identity: identity),
resume_content(
skills: skills,
education: education,
work_experience: work_experience,
professional_development: professional_development,
)
)
)
)
}

View File

@ -0,0 +1,4 @@
#let section_base_body(body) = pad(
left: 1em,
body
)

View File

@ -12,15 +12,10 @@
),
) = {
import "small.typ": section_base_small
import "item.typ": section_base_item
import "items.typ": section_base_items
section_base_small(
title: title,
grid(
gutter: 1.5em,
for item in items {
section_base_item(..item)
}
)
section_base_items(items: items)
)
}

View File

@ -0,0 +1,14 @@
#let section_base_heading(title: "") = {
import "../../base/text.typ": base_text
heading(
level: 2,
base_text(
text(
size: 1.3em,
weight: "bold",
title
)
)
)
}

View File

@ -6,31 +6,18 @@
skills: (""),
highlights: (""),
) = {
import "../../base/text.typ": base_text
import "item/header.typ": section_base_item_header
let item_highlights(highlights: highlights) = for highlight in highlights {
block(
below: 1em,
par(
justify: true,
highlight
)
)
}
import "item/heading.typ": section_base_item_heading
import "item/highlights.typ": section_base_item_highlights
grid(
gutter: 0.95em,
section_base_item_header(
section_base_item_heading(
title: title,
subtitle: subtitle,
role: role,
timeframe: timeframe,
skills: skills,
),
pad(
left: 2em,
item_highlights(highlights: highlights)
)
section_base_item_highlights(highlights: highlights)
)
}

View File

@ -1,66 +0,0 @@
#let section_base_item_header(
title: "",
subtitle: "",
role: "",
timeframe: "",
skills: (""),
) = {
import "../../../base/text.typ": base_text
let header_title(
title: "",
subtitle: "",
) = grid(
columns: 2,
gutter: 1.5em,
align: bottom,
heading(
level: 2,
base_text(
text(
weight: "semibold",
title
)
)
),
text(
size: .9em,
weight: "extralight",
subtitle
),
)
grid(
columns: 2,
rows: 2,
gutter: 0.75em,
align: (
left,
right,
),
header_title(
title: title,
subtitle: subtitle,
),
block(
width: 100%,
text(
weight: "regular",
timeframe
)
),
text(
weight: "light",
size: .95em,
role
),
block(
width: 100%,
text(
weight: "light",
size: .95em,
skills.join(", ")
)
),
)
}

View File

@ -0,0 +1,29 @@
#let section_base_item_heading(
title: "",
subtitle: "",
role: "",
timeframe: "",
skills: (""),
) = {
import "heading/title.typ": section_base_item_heading_title
import "heading/timeframe.typ": section_base_item_heading_timeframe
import "heading/role.typ": section_base_item_heading_role
import "heading/skills.typ": section_base_item_heading_skills
grid(
columns: 2,
rows: 2,
gutter: 0.75em,
align: (
left,
right,
),
section_base_item_heading_title(
title: title,
subtitle: subtitle,
),
section_base_item_heading_timeframe(timeframe: timeframe),
section_base_item_heading_role(role: role),
section_base_item_heading_skills(skills: skills),
)
}

View File

@ -0,0 +1,5 @@
#let section_base_item_heading_role(role: "") = text(
weight: "light",
size: .95em,
role
)

View File

@ -0,0 +1,10 @@
#let section_base_item_heading_skills(
skills: ("")
) = block(
width: 100%,
text(
weight: "light",
size: .95em,
skills.join(", ")
)
)

View File

@ -0,0 +1,13 @@
#let section_base_item_heading_timeframe(
title: "",
subtitle: "",
role: "",
timeframe: "",
skills: (""),
) = block(
width: 100%,
text(
weight: "regular",
timeframe
)
)

View File

@ -0,0 +1,15 @@
#let section_base_item_heading_title(
title: "",
subtitle: "",
) = {
import "title/main.typ": section_base_item_heading_title_main
import "title/subtitle.typ": section_base_item_heading_title_subtitle
grid(
columns: 2,
gutter: 1.5em,
align: bottom,
section_base_item_heading_title_main(title: title),
section_base_item_heading_title_subtitle(subtitle: subtitle),
)
}

View File

@ -0,0 +1,13 @@
#let section_base_item_heading_title_main(title: "") = {
import "../../../../../base/text.typ": base_text
heading(
level: 3,
base_text(
text(
weight: "semibold",
title
)
)
)
}

View File

@ -0,0 +1,8 @@
#let section_base_item_heading_title_subtitle(
title: "",
subtitle: "",
) = text(
size: .9em,
weight: "extralight",
subtitle
)

View File

@ -0,0 +1,14 @@
#let section_base_item_highlights(
highlights: (""),
) = pad(
left: 2em,
for highlight in highlights {
block(
below: 1em,
par(
justify: true,
highlight
)
)
}
)

View File

@ -0,0 +1,21 @@
#let section_base_items(
items: (
(
title: "",
subtitle: "",
role: "",
timeframe: "",
skills: (""),
highlights: (""),
),
),
) = {
import "item.typ": section_base_item
grid(
gutter: 1.5em,
for item in items {
section_base_item(..item)
}
)
}

View File

@ -2,22 +2,12 @@
title: "",
body
) = {
import "../../base/text.typ": base_text
import "heading.typ": section_base_heading
import "body.typ": section_base_body
grid(
gutter: 1.1em,
heading(
base_text(
text(
size: 1.3em,
weight: "bold",
title
)
)
),
pad(
left: 1em,
body
)
section_base_heading(title: title),
section_base_body(body),
)
}

View File

@ -2,46 +2,15 @@
completed: (""),
current: (""),
) = {
let coursework_content(
completed: (""),
current: (""),
) = grid(
columns: 2,
rows: 2,
gutter: 1em,
text(
weight: "regular",
"Completed",
),
text(
weight: "light",
completed.join(", "),
),
text(
weight: "regular",
"Current",
),
text(
weight: "light",
current.join(", "),
),
)
import "coursework/heading.typ": section_education_coursework_heading
import "coursework/content.typ": section_education_coursework_content
grid(
gutter: .95em,
text(
weight: "medium",
"Relevant Coursework"
),
pad(
left: 1.5em,
text(
size: .95em,
coursework_content(
completed: completed,
current: current,
)
)
section_education_coursework_heading(),
section_education_coursework_content(
completed: completed,
current: current,
)
)
}

View File

@ -0,0 +1,26 @@
#let section_education_coursework_content(
completed: (""),
current: (""),
) = {
import "content/section.typ": section_education_coursework_content_section
pad(
left: 1.5em,
text(
size: .95em,
grid(
columns: 2,
rows: 2,
gutter: 1em,
..section_education_coursework_content_section(
title: "Completed",
list: completed,
),
..section_education_coursework_content_section(
title: "Current",
list: current,
),
)
)
)
}

View File

@ -0,0 +1,12 @@
#let section_education_coursework_content_section(
title: "",
list: (""),
) = {
import "section/heading.typ": section_education_coursework_content_section_heading
import "section/content.typ": section_education_coursework_content_section_content
(
section_education_coursework_content_section_heading(title: title),
section_education_coursework_content_section_content(list: list),
)
}

View File

@ -0,0 +1,6 @@
#let section_education_coursework_content_section_content(
list: (""),
) = text(
weight: "light",
list.join(", "),
)

View File

@ -0,0 +1,13 @@
#let section_education_coursework_content_section_heading(title: "") = {
import "../../../../../base/text.typ": base_text
heading(
level: 5,
base_text(
text(
weight: "regular",
title,
)
)
)
}

View File

@ -0,0 +1,13 @@
#let section_education_coursework_heading() = {
import "../../../base/text.typ": base_text
heading(
level: 4,
base_text(
text(
weight: "medium",
"Relevant Coursework"
)
)
)
}

View File

@ -1,46 +0,0 @@
#let section_identity(
identity: (
name: "",
email: "",
phone: "",
location: "",
website: "",
),
) = {
let title(title: "") = text(
size: 2.8em,
weight: "extrabold",
title
)
let contact_info(
email: "",
phone: "",
location: "",
website: "",
) = text(
size: 1.05em,
weight: "medium",
grid(
columns: 4,
rows: 1,
gutter: 4em,
email,
phone,
location,
website,
)
)
grid(
gutter: 1.5em,
align: center,
title(title: identity.name),
contact_info(
email: identity.email,
phone: identity.phone,
location: identity.location,
website: identity.website,
),
)
}

View File

@ -6,8 +6,8 @@
),
),
) = {
import "../base/text.typ": base_text
import "base/small.typ": section_base_small
import "skills/section.typ": section_skills_section
section_base_small(
title: "Skills",
@ -15,18 +15,7 @@
columns: 2,
gutter: 1em,
..for skill in skills {
(
heading(
level: 2,
base_text(
text(
weight: "semibold",
skill.title
)
)
),
skill.items.join(", "),
)
section_skills_section(..skill)
}
)
)

View File

@ -0,0 +1,12 @@
#let section_skills_section(
title: "",
items: (""),
) = {
import "section/heading.typ": section_skills_section_heading
import "section/content.typ": section_skills_section_content
(
section_skills_section_heading(title: title),
section_skills_section_content(items: items),
)
}

View File

@ -0,0 +1,3 @@
#let section_skills_section_content(
items: (""),
) = items.join(", ")

View File

@ -0,0 +1,13 @@
#let section_skills_section_heading(title: "") = {
import "../../../base/text.typ": base_text
heading(
level: 3,
base_text(
text(
weight: "semibold",
title
)
)
)
}