|  | 
| 1 | 1 | package view | 
| 2 | 2 | 
 | 
| 3 |  | -import ( | 
| 4 |  | -	"github.com/m8rmclaren/website/template/components" | 
| 5 |  | -	"html" | 
| 6 |  | -	"regexp" | 
| 7 |  | -	"strings" | 
| 8 |  | -) | 
|  | 3 | +import "github.com/m8rmclaren/website/template/components" | 
| 9 | 4 | 
 | 
| 10 | 5 | templ keyfactorProductOwnerDescription() { | 
| 11 | 6 | 	<p> | 
| @@ -36,9 +31,8 @@ templ keyfactorIntegrationEngineerDescription() { | 
| 36 | 31 |            hover:text-blue-800 hover:decoration-blue-600 hover:underline-offset-4 | 
| 37 | 32 |            focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2" | 
| 38 | 33 | 		>Simple Environment Service</a> | 
| 39 |  | -		, a full-stack platform that lets teams spin up demo, development, and QA environments for Keyfactor’s enterprise products with an  | 
| 40 |  | -		@components.InlineBold("intuitive UI.") | 
| 41 |  | -		The UI and backend fully abstract the underlying infrastructure and product dependencies to deliver a reliable and repeatable workflow. The system was adopted by  | 
|  | 34 | +		, a full-stack platform that lets teams spin up batteries-included demo, development, and QA environments for Keyfactor’s enterprise products in under 10 minutes.  | 
|  | 35 | +		The service abstracts the deployment & configuration of applications using Kubernetes under the hood to deliver a reliable and repeatable workflow. The system was adopted by  | 
| 42 | 36 | 		@components.InlineBold("20%+") | 
| 43 | 37 | 		of staff, and scaled to  | 
| 44 | 38 | 		@components.InlineBold("100+ environments") | 
| @@ -80,105 +74,128 @@ templ keyfactorIntegrationEngineerInternDescription() { | 
| 80 | 74 | 	</p> | 
| 81 | 75 | } | 
| 82 | 76 | 
 | 
|  | 77 | +templ eaglesatBusSystemsIntegrationTeamLead() { | 
|  | 78 | +	<p> | 
|  | 79 | +		Designed mission profiles for each sub-system on board EagleSat-2 to implement the required satellite functionality. Mission profiles are implemented with finite state machines that maintain nominal satellite operation while EagleSat-2 is not in contact with the ground station on ERAU's campus.  | 
|  | 80 | +	</p> | 
|  | 81 | +	<p> | 
|  | 82 | +		Configured and managed the On-Board Computer (OBC) real-time operating system (FreeRTOS with CMSIS RTOS V2 API) and developed low-level drivers for serial communication (CAN, UART, I2C). | 
|  | 83 | +	</p> | 
|  | 84 | +} | 
|  | 85 | + | 
|  | 86 | +templ eaglesatCommunicationsTeamLead() { | 
|  | 87 | +	<p> | 
|  | 88 | +		Led the communications sub-system team for the EagleSat mission, leading the design, development, and integration of a full-stack satellite communication framework to implement command and control (C2) over EagleSat-2. | 
|  | 89 | +	</p> | 
|  | 90 | +	<p> | 
|  | 91 | +		Designed and implemented a headless UHF ground station and a packet-radio communication application (C++) to handle packet routing between the primary C2 platform and the satellite, provide connection statistics, detect satellite range, and calculate Doppler shift. | 
|  | 92 | +	</p> | 
|  | 93 | +} | 
|  | 94 | + | 
| 83 | 95 | templ homeAdvisorITInternDescription() { | 
| 84 | 96 | 	<p> | 
| 85 |  | -		First-line IT support for a team of over 2,800 at HomeAdvisor. | 
|  | 97 | +		First-line IT support for a team of over 2,800 at HomeAdvisor.   | 
| 86 | 98 | 	</p> | 
| 87 | 99 | 	<p> | 
| 88 |  | -		Coordinated incident response to proper teams during outages. | 
|  | 100 | +		Coordinated incident response to proper teams during outages, administered Active Directory & Exchange environments, provisioned new-hire workstations & software. | 
| 89 | 101 | 	</p> | 
| 90 | 102 | } | 
| 91 | 103 | 
 | 
| 92 | 104 | templ erauSoftwareEngineeringDescription() { | 
| 93 | 105 | 	<p> | 
| 94 |  | -		Space Track | 
|  | 106 | +		@components.InlineBold("GPA: ") | 
|  | 107 | +		3.89 (magna cum laude) | 
|  | 108 | +	</p> | 
|  | 109 | +	<p> | 
|  | 110 | +		@components.InlineBold("Activities & Societies: ") | 
|  | 111 | +		EagleSat Engineering Team Lead, UAS Club Secretary, Cyber Defense Club, Computer Science II TA | 
| 95 | 112 | 	</p> | 
| 96 | 113 | } | 
| 97 | 114 | 
 | 
| 98 | 115 | templ Experience() { | 
| 99 |  | -	<div class="flex flex-col gap-2"> | 
| 100 |  | -		<div class="flex flex-col md:flex-row gap-8"> | 
| 101 |  | -			<h2 class="text-3xl font-bold w-36">Industry</h2> | 
| 102 |  | -			<div class="flex flex-col gap-8"> | 
| 103 |  | -				@experienceCard( | 
| 104 |  | -					"Keyfactor", | 
| 105 |  | -					"Product Owner", | 
| 106 |  | -					"Remote", | 
| 107 |  | -					"November 2024-August 2025", | 
| 108 |  | -					keyfactorProductOwnerDescription(), | 
| 109 |  | -				) | 
| 110 |  | -				@experienceCard( | 
| 111 |  | -					"Keyfactor", | 
| 112 |  | -					"Software Engineer - Integrations", | 
| 113 |  | -					"Remote", | 
| 114 |  | -					"May 2023-November 2024", | 
| 115 |  | -					keyfactorIntegrationEngineerDescription(), | 
| 116 |  | -				) | 
| 117 |  | -				@experienceCard( | 
| 118 |  | -					"Keyfactor", | 
| 119 |  | -					"Software Engineer Intern - Integrations", | 
| 120 |  | -					"Remote", | 
| 121 |  | -					"June 2020-May 2023", | 
| 122 |  | -					keyfactorIntegrationEngineerInternDescription(), | 
| 123 |  | -				) | 
| 124 |  | -				@experienceCard( | 
| 125 |  | -					"Home Advisor", | 
| 126 |  | -					"Service Desk Intern", | 
| 127 |  | -					"Denver, CO", | 
| 128 |  | -					"June 2017-August 2019", | 
| 129 |  | -					homeAdvisorITInternDescription(), | 
| 130 |  | -				) | 
| 131 |  | -			</div> | 
|  | 116 | +	<div class="flex flex-col md:flex-row gap-8"> | 
|  | 117 | +		<div class="min-w-40 shrink-0"> | 
|  | 118 | +			<h2 class="text-3xl font-bold">Industry</h2> | 
|  | 119 | +		</div> | 
|  | 120 | +		<div class="flex flex-col gap-8"> | 
|  | 121 | +			@experienceCard( | 
|  | 122 | +				"Keyfactor", | 
|  | 123 | +				"Product Management", | 
|  | 124 | +				"Product Owner", | 
|  | 125 | +				"Remote", | 
|  | 126 | +				"Nov 2024-Aug 2025", | 
|  | 127 | +				keyfactorProductOwnerDescription(), | 
|  | 128 | +			) | 
|  | 129 | +			@experienceCard( | 
|  | 130 | +				"Keyfactor", | 
|  | 131 | +				"Integrations", | 
|  | 132 | +				"Software Engineer", | 
|  | 133 | +				"Remote", | 
|  | 134 | +				"May 2023-Nov 2024", | 
|  | 135 | +				keyfactorIntegrationEngineerDescription(), | 
|  | 136 | +			) | 
|  | 137 | +			@experienceCard( | 
|  | 138 | +				"Keyfactor", | 
|  | 139 | +				"Integrations", | 
|  | 140 | +				"Software Engineer Intern", | 
|  | 141 | +				"Remote", | 
|  | 142 | +				"Jun 2020-May 2023", | 
|  | 143 | +				keyfactorIntegrationEngineerInternDescription(), | 
|  | 144 | +			) | 
|  | 145 | +			@experienceCard( | 
|  | 146 | +				"EagleSat", | 
|  | 147 | +				"", | 
|  | 148 | +				"Bus Systems Integration Manager", | 
|  | 149 | +				"Prescott, AZ", | 
|  | 150 | +				"Sep 2022-May 2023", | 
|  | 151 | +				eaglesatBusSystemsIntegrationTeamLead(), | 
|  | 152 | +			) | 
|  | 153 | +			@experienceCard( | 
|  | 154 | +				"EagleSat", | 
|  | 155 | +				"", | 
|  | 156 | +				"Communications & Ground Station Team Lead", | 
|  | 157 | +				"Prescott, AZ", | 
|  | 158 | +				"May 2021-Sep 2022", | 
|  | 159 | +				eaglesatCommunicationsTeamLead(), | 
|  | 160 | +			) | 
|  | 161 | +			@experienceCard( | 
|  | 162 | +				"Home Advisor", | 
|  | 163 | +				"Technical Operations", | 
|  | 164 | +				"Service Desk Intern", | 
|  | 165 | +				"Denver, CO", | 
|  | 166 | +				"Jun 2017-Aug 2019", | 
|  | 167 | +				homeAdvisorITInternDescription(), | 
|  | 168 | +			) | 
| 132 | 169 | 		</div> | 
| 133 | 170 | 	</div> | 
| 134 | 171 | } | 
| 135 | 172 | 
 | 
| 136 | 173 | templ Education() { | 
| 137 |  | -	<div class="flex flex-col gap-2"> | 
| 138 |  | -		<div class="flex flex-col md:flex-row gap-8"> | 
| 139 |  | -			<h2 class="text-3xl font-bold w-36">Academia</h2> | 
|  | 174 | +	<div class="flex flex-col md:flex-row gap-8"> | 
|  | 175 | +		<div class="min-w-40 shrink-0"> | 
|  | 176 | +			<h2 class="text-3xl font-bold">Academia</h2> | 
|  | 177 | +		</div> | 
|  | 178 | +		<div class="flex flex-col gap-8 justify-self-start"> | 
| 140 | 179 | 			@experienceCard( | 
| 141 | 180 | 				"Embry-Riddle Aeronautical University", | 
|  | 181 | +				"", | 
| 142 | 182 | 				"BS, Software Engineering", | 
| 143 | 183 | 				"Prescott, AZ", | 
| 144 |  | -				"August 2019-May 2023", | 
|  | 184 | +				"Aug 2019-May 2023", | 
| 145 | 185 | 				erauSoftwareEngineeringDescription(), | 
| 146 | 186 | 			) | 
| 147 | 187 | 		</div> | 
| 148 | 188 | 	</div> | 
| 149 | 189 | } | 
| 150 | 190 | 
 | 
| 151 |  | -var boldRe = regexp.MustCompile(`\*\*(.+?)\*\*`) | 
| 152 |  | - | 
| 153 |  | -func parseBoldTempl(line string) templ.Component { | 
| 154 |  | -	var b strings.Builder | 
| 155 |  | -	last := 0 | 
| 156 |  | - | 
| 157 |  | -	for _, m := range boldRe.FindAllStringSubmatchIndex(line, -1) { | 
| 158 |  | -		start, end := m[0], m[1] | 
| 159 |  | -		innerStart, innerEnd := m[2], m[3] | 
| 160 |  | - | 
| 161 |  | -		// Write text before **...**, escaped. | 
| 162 |  | -		b.WriteString(html.EscapeString(line[last:start])) | 
| 163 |  | - | 
| 164 |  | -		// Write the bold span with escaped inner text. | 
| 165 |  | -		b.WriteString(`<span class="font-bold">`) | 
| 166 |  | -		b.WriteString(html.EscapeString(line[innerStart:innerEnd])) | 
| 167 |  | -		b.WriteString(`</span>`) | 
| 168 |  | - | 
| 169 |  | -		last = end | 
| 170 |  | -	} | 
| 171 |  | - | 
| 172 |  | -	// Write the trailing text, escaped. | 
| 173 |  | -	b.WriteString(html.EscapeString(line[last:])) | 
| 174 |  | - | 
| 175 |  | -	// Important: tell Templ this is safe HTML so it won't escape the tags. | 
| 176 |  | -	return templ.Raw(b.String()) | 
| 177 |  | -} | 
| 178 |  | - | 
| 179 |  | -templ experienceCard(company, title, location, duration string, description templ.Component) { | 
|  | 191 | +templ experienceCard(company, team, title, location, duration string, description templ.Component) { | 
| 180 | 192 | 	<div class="flex flex-col gap-1"> | 
| 181 |  | -		<h2 class="text-xl font-bold">{ company } • { title }</h2> | 
|  | 193 | +		<h3 class="text-xl font-bold"> | 
|  | 194 | +			{ company } • { title } | 
|  | 195 | +			if team != "" { | 
|  | 196 | +				— { team } | 
|  | 197 | +			} | 
|  | 198 | +		</h3> | 
| 182 | 199 | 		<p class="font-medium"> | 
| 183 | 200 | 			{ location } • { duration } | 
| 184 | 201 | 		</p> | 
|  | 
0 commit comments