Skip to content

Instantly share code, notes, and snippets.

@sonhanguyen
Last active March 17, 2023 00:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sonhanguyen/357a0e5e8b2bbffdb69aed351a437950 to your computer and use it in GitHub Desktop.
Save sonhanguyen/357a0e5e8b2bbffdb69aed351a437950 to your computer and use it in GitHub Desktop.
resume
<head>
<style>
@media print { body { height: 297mm } }
body {
width: 210mm;
font-family: Helvetica Neue, Helvetica, Arial, sans-serif;
margin: 0;
display: flex;
}
aside {
width: 35%;
height: 100vh;
border-right: 1px solid black;
}
aside,
main {
display: flex;
flex-direction: column;
}
h1 {
font-size: x-large;
margin-block-start: 2rem;
margin-block-end: 1rem;
}
header {
padding-bottom: 2rem;
}
</style>
</head>
<body>
<aside style='padding: 0 1rem; text-align: right'>
<header>
<h1>Son Ha Nguyen</h1>
<a>+84 968 992 888</a> (travelling)
<a>sonhanguyen@outlook.com</a>
<a>linkedin.com/in/sonhanguyen</a>
<a>github.com/sonhanguyen</a>
</header>
<p style='text-align: left'>
Polyglot software developer. I am currently interested in web technologies, data engineering and domain driven design. My ideal role is where I work in a full-stack capacity and exposed to every part of the problems at hand.
</p>
<div>
<h1>Skill summary</h1>
<style>
.skill > :first-line {
font-weight: bold;
}
</style>
<div class=skill>
<p> Webpack, React, nextjs, styled-components, typescript (<a>git.io/fjWHd</a>, <a>git.io/fhmGY</a>, <a>git.io/vbRu8</a>, <a>git.io/vAHjn</a>)
<p> Nodejs, Java, Docker, AWS (CloudFormation, Fargate, Dynamo), Postgres, Terraform
<p> Exposure to other technologies: Xamarin, Python (<a>git.io/JTP93</a>), Kotlin (<a>git.io/vbRuQ</a>),
<p> Functional/reactive programming (RxJS)
<p> OOP design patterns
<p> Knowledge sharing (<a>git.io/vAHjC</a>)
</div>
</div>
</aside>
<main>
<style>
h2 {
font-size: 1.1rem;
}
.row {
display: flex;
}
.col {
display: flex;
flex-direction: column;
}
.flex {
display: flex;
align-content: stretch;
flex: 1;
}
.padded {
margin: 1rem;
}
.right {
text-align: right;
}
</style>
<div class='padded' style='margin-top: 0; font-size: small'>
<h1>Employment</h1>
<template id=my-job>
<style>
[name=end]:not(:empty) + i {
display: none;
}
[name=end] + i {
display: flex;
order: 1
}
[name=start] {
display: flex;
order: 2
}
[name=end]:not(:empty):before {
content: '-';
padding: 0 .5rem;
}
[name=end] {
display: flex;
order: 3
}
</style>
<div>
<h2>
<slot name=title></slot>
<span style='display: inline-block'> | <slot name=company></span>
</h2>
<div class='row'>
<div class='flex'><slot name=description></slot></div>
<div class='row right'>
<slot name=start></slot>
<slot name=end></slot><i>since&nbsp;</i>
</div>
</div>
<slot>
</div>
</template>
<my-job
title='Freelancer'
start=09/2022
>
I took some time off back home in Vietnam to take care of familly matters, then used this as an opportunity to travel SEA and work on smaller web projects
</my-job>
<my-job
description='Collaborative design platform'
title='Growth Engineer'
start=07/2021
end=08/2022
>
<a slot=company href=invision.com>InVision</a>
<ul>
<li> Working across multiple services: backend, frontend, data to drive adoption for InVision new colaborative whiteboard offering Freehand
<li> Golang, React
</ul>
</my-job>
<my-job
description='Cloud training platform'
title='Software Development Consultant'
start=01/2021
end=07/2021
>
<a slot=company>Shine Solutions</a>
<ul>
<li> <a href=acloud.guru>ACloudGuru</a> (data migration project): AWS Step Function, Serverless, GraphQL
</ul>
</my-job>
<my-job
description='FX broker, wallet & onboarding application'
title='Front-end lead'
start=04/2018
end=12/2020
>
<a slot=company href=pepperstone.com>PepperStone</a>
<ul>
<li> Sprint planning and running agile ceremonies
<li> Mentoring and managing developers from the offshore team
<li> React, Typescript, redux-saga
<li> Micro services with golang, OpenAPI, json-schema
<li> AWS Fargate, Buidkite
<li> TDD: Cypress, Jest
<li> Payments APIs (Paypal, Worldpay...)
<li> Design system (storybook)
</ul>
</my-job>
<my-job
description='Adtech cloud-based software'
title='Frontend Engineer'
start=12/2016
end=03/2018
>
<a slot=company href=adslot.com>Adslot</a>
<ul>
<li> Porting the front-end from an older to a more modern stack (angularjs/coffeescript to react/redux).
<li> Unit testing using enzyme.
<li> Maintainer of company's open source library, in a trello/travis/github workflow.
<li> Mentoring junior devs, code review
<li> Introducing typescript to the team.
</ul>
</my-job>
<my-job
description='In-house product team, cloud-based data management solution'
title='Software Engineer'
start=05/2016
end=11/2016
>
<a slot=company href=alexsolutions.com.au>Alex Solutions</a>
<ul>
<li> Refactor the front-end to introduce React, mobx, webpack & react-router.
<li> XML-based ETL engine: picked up junit, sbt, jabx in the process. The engine accommodates for execution of scripts (case in point: xQuery & SQL) remotely in the ETL job template. MVP in 3 weeks. The subsequent works utilise springboot and rxjava.
</ul>
</my-job>
<div style='page-break-inside: avoid'>
<h1>Education</h1>
<template id=my-qualification>
<div>
<div class='flex'>
<div class='flex col'>
<div>
<article class='flex'><slot name=course></article>
<slot name=description>
</div>
<slot name=university>
</div>
<div class='col'>
<div class='row' style='align-self: flex-end'>
<i>class of</i>&nbsp;<slot name=year>
</div>
<slot name=campus>
</div>
</div>
<slot>
</div>
</template>
<my-qualification
course='Master of Information Technology'
description='(Professional Computing)'
university='Swinburne University of Technology'
campus='Melbourne, Australia'
year=2016
>
<p> Project work with OpenCV </p>
</my-qualification>
<my-qualification
course='Bachelor of Software Engineering'
university='Posts and Telecommunication Institute of Technology'
campus='Hanoi, Vietnam'
year=2013
>
<ul>
<li> Capstone project in sentiment analysis (weka, lucence, SVM)
<li> ACM-ICPC contester
</ul>
</my-qualification>
</div>
</div>
</main>
<script>
/**
* @arg {Node} fragment
* @arg {NamedNodeMap} attributes
*
* @return {Node}
*/
const withDefaults = (fragment, attributes) => {
const node = fragment.cloneNode(true)
for(let i = 0; i < attributes.length; ++i) {
const { value, name } = attributes.item(i)
const slot = node.querySelector(`slot[name=${name}]`)
if (slot) slot.innerText = value
}
return node
}
/** @template T @arg {Array<T | Array<T>>} @return {T[]} */
const flatten = it => [].concat(...it)
/**
* @arg {{ adoptedStyleSheets: ReadonlyArray<CSSStyleSheet> }} target
* @arg {...CSSStyleSheet} styleSheets
*/
const prependStyle = (target, ...styleSheets) => {
const rules = flatten(styleSheets.map(it => [...it.cssRules]))
const css = new CSSStyleSheet() // only tested on Chrome Beta as of Dec 2021
rules.forEach(({ cssText }) => css.insertRule(cssText))
target.adoptedStyleSheets = [ css, ...target.adoptedStyleSheets ]
}
/**
* @arg {Node} template
* @arg {{ styleSheets: CSSStyleSheet[] }}
*
* @return {CustomElementConstructor}
*/
const createComponent = (template, { styleSheets = [] } = document) =>
class extends HTMLElement {
constructor() {
super();
this.attachShadow({ mode: 'open' })
.appendChild(withDefaults(template, this.attributes))
prependStyle(this.shadowRoot, ...styleSheets)
}
}
/** @arg {{ id: string, content: DocumentFragment }} */
const registerComponent = ({ id, content }) =>
customElements.define(id, createComponent(content))
document
.querySelectorAll`template`
.forEach(registerComponent)
</script>
<script>
document
.querySelectorAll`a`
.forEach(link => {
const { innerText } = link
let href = link.getAttribute`href` || innerText
if (href.match(/^\+?[ -\d]+$/))
href = 'tel:' + href.replace(/[ -]/g, '')
else if (href.includes`@`)
href = 'mailto:' + innerText
else href = href.replace(/^([^:]+:\/\/)?/, 'https://')
Object.assign(link, { href })
})
</script>
</body>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment