summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Van Doorn <vandoorn.nick@gmail.com>2019-03-19 02:27:22 -0700
committerNick Van Doorn <vandoorn.nick@gmail.com>2019-03-19 02:27:22 -0700
commit59564767382afafbdae858bce829ab10486a8980 (patch)
treec46c1bbc21c1145a13c7fbcce01f33878ae9a378
parent09eea921546d98d31da53a60d25df2e68ed56efb (diff)
Split `Project` component into `ProjectDetail`
-rw-r--r--src/components/project-detail.js54
-rw-r--r--src/components/project.js50
-rw-r--r--src/pages/about.js7
-rw-r--r--src/pages/index.js3
-rw-r--r--src/pages/projects.js92
-rw-r--r--src/pages/work.js186
6 files changed, 283 insertions, 109 deletions
diff --git a/src/components/project-detail.js b/src/components/project-detail.js
new file mode 100644
index 0000000..f84a5c9
--- /dev/null
+++ b/src/components/project-detail.js
@@ -0,0 +1,54 @@
+import React from 'react'
+import { css } from '@emotion/core'
+
+import { SplitContainer } from './split-container'
+import { Image } from './image'
+import { margins, breakpoints } from './globals'
+
+const descContainerStyle = css`
+ width: 100%;
+ display: flex;
+ flex-direction: column;
+ justify-content: flex-start;
+ @media (min-width: ${breakpoints[0].breakpoint}px) {
+ margin: 0 0 0 ${margins.md}px;
+ flex: 1;
+ }
+ & > * {
+ margin: 0 0 ${margins.md}px 0;
+ }
+`
+
+const imgContainerStyle = css`
+ display: flex;
+ & > *:not(:last-child) {
+ margin-right: ${margins.sm}px;
+ }
+`
+
+export const ProjectDetail = ({ listItems, header, images }) => (
+ <section
+ css={css`
+ width: 100%;
+ margin-bottom: ${margins.md}px;
+ `}
+ >
+ <SplitContainer>
+ <div css={descContainerStyle}>
+ {header ? <h4>{header}</h4> : null}
+ {listItems ? (
+ <ul>
+ {listItems.map((k, i) => (
+ <li key={`detail-item-${i}`}>{k}</li>
+ ))}
+ </ul>
+ ) : null}
+ </div>
+ <div css={imgContainerStyle}>
+ {images
+ ? images.map((k, i) => <Image key={`image-${i}`} {...k} />)
+ : null}
+ </div>
+ </SplitContainer>
+ </section>
+)
diff --git a/src/components/project.js b/src/components/project.js
index 9b5bf7e..b827d70 100644
--- a/src/components/project.js
+++ b/src/components/project.js
@@ -5,13 +5,13 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { faLink } from '@fortawesome/free-solid-svg-icons'
import { Tag } from './tag'
-import { margins, breakpoints } from './globals'
+import { ProjectDetail } from './project-detail'
+import { margins } from './globals'
const projectHeadingStyle = css`
margin: 0 ${margins.sm}px 0 0;
`
const projectBriefStyle = css`
- margin: 0;
font-weight: 300;
`
@@ -20,10 +20,6 @@ const projectBlockStyle = css`
flex-wrap: wrap;
`
-const imgStyle = css`
- max-height: 85vw;
-`
-
const linkStyle = css`
display: flex;
align-content: center;
@@ -37,6 +33,9 @@ const linkStyle = css`
const projectStyle = css`
margin: 0 0 ${margins.lg}px 0;
+ & > * {
+ margin: 0 0 ${margins.md}px 0;
+ }
`
const linkIconStyle = css`
@@ -63,29 +62,6 @@ const dateStyle = css`
`
export const Project = p => {
- const marginRight = p.imgUrl ? margins.md : 0
- const descContainerStyle = css`
- font-weight: 300;
- display: flex;
- flex-direction: column;
- justify-content: center;
- margin: ${margins.md}px 0 0 0;
- @media (min-width: ${breakpoints[0].breakpoint}px) {
- margin: 0 0 0 ${marginRight}px;
- flex: 1;
- }
- & > * {
- margin: 0 0 ${margins.md}px 0;
- }
-
- & img {
- max-height: 150px;
- align-self: flex-end;
- box-shadow: 0 14px 28px rgba(0,0,0,0.25), 0 10px 10px rgba(0,0,0,0.22);
- 0 15px 12px rgba(0, 0, 0, 0.22);
- margin-bottom: ${margins.md}px;
- }
- `
return (
<article css={projectStyle}>
<div css={projectHeadingContainerStyle}>
@@ -107,8 +83,20 @@ export const Project = p => {
</div>
<h3 css={projectBriefStyle}>{p.brief}</h3>
<div css={projectBlockStyle}>
- {p.imgUrl ? <img src={p.imgUrl} alt={p.imgAlt} css={imgStyle} /> : null}
- {p.desc ? <div css={descContainerStyle}>{p.desc}</div> : null}
+ {p.desc ? (
+ <div
+ css={css`
+ margin-bottom: ${margins.md}px;
+ `}
+ >
+ {p.desc}
+ </div>
+ ) : null}
+ {p.projectDetails
+ ? p.projectDetails.map((k, i) => (
+ <ProjectDetail key={`project-detail-${i}`} {...k} />
+ ))
+ : null}
</div>
</article>
)
diff --git a/src/pages/about.js b/src/pages/about.js
index daab814..c8f050e 100644
--- a/src/pages/about.js
+++ b/src/pages/about.js
@@ -9,6 +9,7 @@ import {
} from '@fortawesome/free-solid-svg-icons'
import Layout from '../components/layout'
+import { margins } from '../components/globals'
import { AboutEntry } from '../components/about-entry'
import { Personal } from '../components/personal'
import { SplitContainer } from '../components/split-container'
@@ -100,7 +101,11 @@ export default () => (
<Personal {...personalProps} />
<div>
{aboutLists.map((entry, i) => (
- <AboutEntry {...entry} key={`about-entry-${i}`} />
+ <AboutEntry
+ {...entry}
+ headerMargin={`0 0 ${margins.md}px 0`}
+ key={`about-entry-${i}`}
+ />
))}
</div>
</SplitContainer>
diff --git a/src/pages/index.js b/src/pages/index.js
index 14e4b4d..26c481c 100644
--- a/src/pages/index.js
+++ b/src/pages/index.js
@@ -7,7 +7,8 @@ import Layout from '../components/layout'
import { Splash } from '../components/splash'
const indexData = {
- heroText: `Let's make computers work for us`,
+ heroText: `Hello world 👋`,
+ heroTagline: `Let's build software for life`,
heroBtnTo: '/about',
heroBtn: (
<>
diff --git a/src/pages/projects.js b/src/pages/projects.js
index 8ee306c..0c55834 100644
--- a/src/pages/projects.js
+++ b/src/pages/projects.js
@@ -16,15 +16,27 @@ export const projects = [
brief:
'A Battlesnake so close to the metal, 6 CVEs have been opened while reading',
date: 'Feb 2019 - Present',
- desc: 'I tried to make a really fast snake',
+ desc: (
+ <p>
+ A fast snake where everything is implemented by hand in C to perform a
+ fast traversal of all possible game states. The implementation is still
+ unfinished but I hope to enter it in the Battlesnake 2020 competition.
+ </p>
+ ),
url: '//github.com/nvandoorn/cnaked'
},
{
name: 'naive',
brief: 'A naive implementation of a NoSQL database',
date: 'Jan 2019 - Present',
- desc:
- 'Use this database in prod and you will be on the news for the wrong reasons',
+ desc: (
+ <p>
+ A small realtime NoSQL database that can be used locally or over a
+ network. The public interface for this database mimic that of the
+ Firebase Realtime Database and data is persisted using a static JSON
+ file. For that reason, I do not suggest using this in production.
+ </p>
+ ),
url: '//github.com/nvandoorn/naive',
showOnCv: true
},
@@ -32,8 +44,12 @@ export const projects = [
name: 'Pipefitter',
brief: 'Automated audits and monitoring for your ISP',
date: 'Nov 2018 - Present',
- desc: `My home internet performance is really bad and my ISP never believes me.
- Hopefully they will soon. Designed for maximum plug-ability`,
+ desc: (
+ <p>
+ My home internet performance is consistently below spec and my ISP never
+ believes me. Hopefully they will soon. Designed for maximum plug-ability
+ </p>
+ ),
url: '//github.com/nvandoorn/pipefitter',
showOnCv: true
},
@@ -41,8 +57,12 @@ export const projects = [
name: 'funCtional',
brief: 'Functional programming in C with statically allocated memory',
date: 'Aug 2018',
- desc: `I like functional programming and I like C, so I tried to combine the two.
- In reality, a simple for loop is better, but I had fun trying this.`,
+ desc: (
+ <p>
+ I like functional programming and I like C, so I tried to combine the
+ two. In reality, a simple for loop is better, but I had fun trying this.
+ </p>
+ ),
imgUrl: functional,
inProd: true,
url: '//github.com/nvandoorn/functional'
@@ -52,9 +72,13 @@ export const projects = [
brief: 'Non-volatile time series data storage',
date: 'Jun 2018 - Present',
imgUrl: storageService,
- desc: `The Legato Linux framework offers out of the box support for
- uploading time series data, but not storing it locally. For this reason,
- we created this service to persist data for offline cases.`,
+ desc: (
+ <p>
+ The Legato Linux framework offers out of the box support for uploading
+ time series data, but not storing it locally. For this reason, we
+ created this service to persist data for offline cases.
+ </p>
+ ),
url: '//github.com/brnkl/legato-storage-service'
},
{
@@ -63,10 +87,14 @@ export const projects = [
'Monitor GPS in a separate process to avoid blocking single threaded apps',
date: 'April 2018',
imgUrl: gpsMonitor,
- desc: `Instead of managing and synchronizing a thread to monitor GPS location
- on embedded devices, this service asynchronously monitors the GPS position
- and allows users to retrieve it using an inter process API
- (see more about Legato IPC APIs here).`,
+ desc: (
+ <p>
+ Instead of managing and synchronizing a thread to monitor GPS location
+ on embedded devices, this service asynchronously monitors the GPS
+ position and allows users to retrieve it using an inter process API (see
+ more about Legato IPC APIs here).
+ </p>
+ ),
inProd: true,
url: '//github.com/brnkl/gps-monitor',
showOnCv: true
@@ -75,11 +103,16 @@ export const projects = [
name: 'CF3 Config App',
brief: 'Automatically configure common settings for CF3 based modules',
date: 'April 2018',
- desc: `Sierra Wireless offers a range of cellular modules based on a common socket with a
- common set of inputs and outputs.A range of commonly used input / output pins and UART
- connections must be configured by running an AT command over a serial connection to the
- CF3 based modem.Run this app once and the CF3 based module will support the full range of
- GPIO pins and UARTs in the Linux userspace.`,
+ desc: (
+ <p>
+ Sierra Wireless offers a range of cellular modules based on a common
+ socket with a common set of inputs and outputs.A range of commonly used
+ input / output pins and UART connections must be configured by running
+ an AT command over a serial connection to the CF3 based modem.Run this
+ app once and the CF3 based module will support the full range of GPIO
+ pins and UARTs in the Linux userspace.
+ </p>
+ ),
inProd: true,
url: ''
},
@@ -87,12 +120,17 @@ export const projects = [
name: 'Legato Camera Driver',
brief: 'Support for the VC0706 camera on a Legato based project',
date: 'Nov 2017 - Dec 2017',
- desc: `The VC0706 camera is one of the only low power remote cameras with an open protocol
- (serial port based).The seller, Adafruit, supplies open source drivers implemented
- in Python and C++ with the purpose of running on Arduino based systems. This means
- a dependency on certain Arduino libraries for reading and writing to the serial port.
- We re-implemented the C++ driver in C without the dependence on anything
- not included in Linux (with the exception of a few Legato specific macros).`,
+ desc: (
+ <p>
+ The VC0706 camera is one of the only low power remote cameras with an
+ open protocol (serial port based).The seller, Adafruit, supplies open
+ source drivers implemented in Python and C++ with the purpose of running
+ on Arduino based systems. This means a dependency on certain Arduino
+ libraries for reading and writing to the serial port. We re-implemented
+ the C++ driver in C without the dependence on anything not included in
+ Linux (with the exception of a few Legato specific macros).
+ </p>
+ ),
imgUrl: camera,
inProd: true,
url: '//github.com/brnkl/VC0706-cam-lib',
@@ -113,13 +151,13 @@ export const projects = [
brief: 'A lightweight log viewer and server all in one',
date: 'Mar 2017 - Present',
desc: (
- <>
+ <p>
slask is designed to make remote systems debugging easy. During my time
at Forest Technology Systems (FTS), we worked on a remote weather
station based on a single board Linux computer. During the early days, I
spent large amounts of time transferring and filtering log files using a
mix of <em>scp</em>, <em>grep</em>, and <em>less</em>.
- </>
+ </p>
),
imgUrl: slask,
url: '//github.com/nvandoorn/slask'
diff --git a/src/pages/work.js b/src/pages/work.js
index 1f8266c..19cf86c 100644
--- a/src/pages/work.js
+++ b/src/pages/work.js
@@ -3,47 +3,119 @@ import React from 'react'
import Layout from '../components/layout'
import { Project } from '../components/project'
+import startupOfTheYear from '../images/startup-of-the-year.jpg'
+import brnklAppMap from '../images/brnkl-app-map-iphone.png'
+import brnklAppAlerts from '../images/brnkl-app-alerts-iphone.png'
+import brnklProduct from '../images/brnkl-product.jpg'
+import wpModule from '../images/wp-module.png'
+
export const workHistory = [
{
name: 'Lead Software Developer',
brief: 'BRNKL by Barnacle Systems',
date: 'Sept 2017 - Feb 2019',
+ projectDetails: [
+ {
+ header: 'Awards',
+ listItems: [
+ <>
+ <a href="https://sbbcawards.ca/winners/"> Best New Concept</a>,
+ Small Business BC, Feb 2019
+ </>,
+ <>
+ <a href="https://www.passagemaker.com/trawler-news/vancouver-boat-show-best-in-show-awards">
+ {' '}
+ Most Innovative (Best In Show)
+ </a>
+ , Vancouver International Boat Show, Feb 2019
+ </>,
+ <>
+ <a href="http://viatecawards.com/2018-recipients/#elementor-tab-title-6044">
+ {' '}
+ Startup of The Year
+ </a>
+ , VIATEC, June 2018
+ </>
+ ],
+ images: [
+ { imgUrl: startupOfTheYear, caption: 'VIATEC Startup of The Year' }
+ ]
+ },
+ {
+ header: <a href="https://app.brnkl.io"> App</a>,
+ listItems: [
+ 'Implemented with TypeScript, Angular, and RxJS',
+ 'Deployed on iOS, Android, and the web',
+ 'Realtime data using RxJS and Firebase Realtime Database',
+ 'Push alerts implemented over Firebase Cloud Messaging'
+ ],
+ images: [
+ {
+ imgUrl: brnklAppMap,
+ caption: 'BRNKL App Map View',
+ noShadow: true
+ },
+ {
+ imgUrl: brnklAppAlerts,
+ caption: 'BRNKL App Alert View',
+ noShadow: true
+ }
+ ]
+ },
+ {
+ header: 'Backend',
+ listItems: [
+ 'Written in TypeScript and run on Node',
+ 'Covered by unit tests and integration tests',
+ 'Deployed on Google Cloud Pubsub and Firebase Functions',
+ 'Integrated with cellular network via Sierra Wireless'
+ ]
+ },
+ {
+ header: 'Embedded',
+ listItems: [
+ <>
+ Written in C with the{' '}
+ <a href="https://legato.io">Legato Framework</a>
+ </>,
+ <>
+ Custom circuit board based on ARM chip with{' '}
+ <a href="https://www.yoctoproject.org/">Yocto Linux</a>
+ </>,
+ 'Custom drivers for hardware peripherals (userspace and kernelspace)',
+ 'Integration with backend to implement custom business logic',
+ 'Successful deploys of over the air updates to customers',
+ <>
+ Active member of <a href="https://forum.legato.io">Legato</a> and{' '}
+ <a href="https://forum.mangoh.io">mangOH</a> communities
+ </>
+ ],
+ images: [{ imgUrl: brnklProduct, caption: 'BRNKL embedded device' }]
+ },
+ {
+ header: 'Production Automation',
+ listItems: [
+ 'Test circuit boards against a suite of hardware tests',
+ 'Automate installtion of latest firmware release for hardware',
+ 'Automated delivery of diagnostic messages to factory workers',
+ 'Automation of device inventory (e.g collecting board serial numbers)'
+ ],
+ images: [
+ {
+ imgUrl: wpModule,
+ caption: 'Sierra Wireless WP85 Module (core of BRNKL)',
+ noShadow: true
+ }
+ ]
+ }
+ ],
desc: (
- <>
- <h4>Awards</h4>
- <ul>
- <li>Best New Concept, Small Business BC, Feb 2019</li>
- <li>
- Most Innovative (Best In Show), Vancouver International Boat Show,
- Feb 2019
- </li>
- <li>Startup of the Year, VIATEC, June 2018</li>
- </ul>
- <h4>App</h4>
- <ul>
- <li>Written in TypeScript with Angular</li>
- <li>Deployed on iOS, Android, and web</li>
- <li>Realtime data from Firebase Realtime Database</li>
- <li>Push alerts implemented over Firebase Cloud Messaging</li>
- </ul>
- <h4>Backend</h4>
- <ul>
- <li>Written in TypeScript and run on Node</li>
- <li>Covered by unit tests and integration tests</li>
- <li>Deployed on Google Cloud Pubsub and Firebase Functions</li>
- <li>Integrated with cellular network via Sierra Wireless</li>
- </ul>
- <h4>Embedded</h4>
- <ul>
- <li>Written in C with the Legato Framework</li>
- <li>Custom board based on ARM chip with Linux</li>
- <li>
- Custom drivers for hardware peripherals (userspace and kernelspace)
- </li>
- <li>Integration with backend to implement custom business logic</li>
- <li>Successful deploys of over the air updates to customers</li>
- </ul>
- </>
+ <p>
+ Barnacle Systems is a self bootstrapped company working on boat
+ monitoring and security. I worked as the sole implementer of the the
+ BRNKL app, backend, embedded firmware, and production automation
+ software (with thanks to many open source authors).
+ </p>
),
url: '//brnkl.io'
},
@@ -51,27 +123,43 @@ export const workHistory = [
name: 'Software Developer, Contract',
brief: 'BRNKL by Barnacle Systems',
date: 'Jul 2017 - Sept 2017',
- desc: <></>,
- imgUrl: '',
+ desc: (
+ <p>
+ One of my co-workers from Forest Technology Systems left to found their
+ own company and approached me to help with the initial version of the
+ app and backend.
+ </p>
+ ),
+ projectDetails: [
+ {
+ listItems: [
+ 'Transform mockups and prototype of app into initial commercial release',
+ 'Implement initial backend based on prototype implementation',
+ `Design infrastructure such that it is self managed (i.e "stateless" or "serverless")`,
+ 'Design and implement local test environment for backend'
+ ]
+ }
+ ],
url: '//brnkl.io'
},
{
name: 'Software Developer, Co-op',
brief: 'Forest Technology Systems',
date: 'Sept 2016 - April 2017',
+ projectDetails: [
+ {
+ listItems: [
+ 'Implement components of embedded camera product aimed at the fire weather market (FTS RAOS)',
+ 'Automate builds and installs',
+ 'Integrate with user facing software as a service product'
+ ]
+ }
+ ],
desc: (
- <ul>
- <li>
- Worked with small cross-functional team of engineers, product
- managers, and sales staff
- </li>
- <li>
- Implement components of embedded camera product aimed at the fire
- weather market (FTS RAOS)
- </li>
- <li>Automate builds and installs</li>
- <li>Integrate with user facing software as a service product</li>
- </ul>
+ <p>
+ During my time at Forest Technology Systems, I worked with a small
+ cross-functional team of engineers, product managers, and sales staff.
+ </p>
),
url: '//ftsinc.com/'
}