Compare commits

...

10 Commits

67 changed files with 678 additions and 8195 deletions

124
.gitignore vendored
View File

@ -1,16 +1,114 @@
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
.DS_Store
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
coverage
node_modules
build
.env.local
.env.development.local
.env.test.local
.env.production.local
# C extensions
*.so
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
*.egg-info/
.installed.cfg
*.egg
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
.hypothesis/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
target/
# Jupyter Notebook
.ipynb_checkpoints
# pyenv
.python-version
# celery beat schedule file
celerybeat-schedule
# SageMath parsed files
*.sage.py
# Environments
.env
.venv
env/
venv/
ENV/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
# Editor
*.swp
*.swo
# DB
db.sqlite3
# Test mount
test/
# VS Code
.vscode/
output/

View File

@ -1 +0,0 @@
My personal website.

View File

@ -0,0 +1,28 @@
Title: Hand of Ozymandias
Date: 2012-03-23
Category: Projects
Summary: A withered hand I welded out of scrap metal.
I was visiting my cousins in Radium, BC and decided to learn stick welding at
their shop. I wanted to create a sculpture, so with pieces of scrap metal I
welded together this hand. The beads are far from perfect. Working with small
pieces of rusted metal made it difficult.
![a rusted metalic hand]({static}/images/hand-of-ozymandias/hand1.jpg)
## The Name
One of my favourite poems is [Ozymandias](https://en.wikipedia.org/wiki/Ozymandias)
by Percy Bysshe Shelley. It's about the inevitable complete decline of all
rulers and the empires they build, however mighty in their time. This is the
hand of Ozymandias sticking out from the sand, grasping for life after he has
been reduced to dust.
## Construction
I eyeballed the joint angles and my cousin cut them to spec with an angle
grinder. It was made in a machine shop with no real planning done ahead of time.
In between welds, I used my own hand as a reference. Below is a picture of me
adding a bead to it.
![me welding the hand causing a very bright light]({static}/images/hand-of-ozymandias/hand2.jpg)

Binary file not shown.

After

Width:  |  Height:  |  Size: 198 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 74 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 82 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 88 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 145 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 154 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 131 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 130 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 116 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 163 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 295 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 350 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 160 KiB

30
content/led-dress.md Normal file
View File

@ -0,0 +1,30 @@
Title: LED Dress
Date: 2016-03-18
Category: Projects
Summary: A dress made out of LEDs that twinkle like stars.
A friend of mine was attending a stars and constellations themed ball. She
wanted to wear a dress that was lit up with LEDs acting as twinkling stars.
Seven of the 28 stars are aligned to resemble the Big Dipper constellation and
twinkle differently than the rest, which twinkle in a random pattern.
![a blue dress with a number of LEDs shining through the fabric]({static}/images/dress/dress1.jpg)
## Construction
The LEDs came from that strip that was cut up and soldered together with very
small wires. Each of the LEDs can be controlled individually.
![the controller circuit board on the left, and the soldered together LEDs on the right]({static}/images/dress/dress2.jpg)
21 of the stars are light magenta in color and twinkle by fading randomly. The
seven LEDs that form the Big Dipper continually scroll through a gradient of
three colors. Instead of calculating the values of each color in the gradient as
the program runs, a lookup table is used.
<center>
<video autoplay muted loop>
<source src="{static}/videos/dress/dress3.mp4" type="video/mp4">
Your browser does not support the video tag.
</video>
</center>

30
content/light-switch.md Normal file
View File

@ -0,0 +1,30 @@
Title: Remote Control Light Switch
Date: 2014-10-09
Category: Projects
Summary: A device to toggle my lights remotely.
I wanted the ability to toggle my bedroom light remotely for convenience. I
designed a circuit that allows me to control my light with any
device that can load a webpage.
I still wanted to be able to control the light manually, so I bought a metallic
face-plate and turned it into a capacitive touch sensor. The slightest touch
anywhere on the plate is enough to toggle the light. I had to electrically
isolate the metal screws from it because they screw into a grounded switch box.
![a rusted metalic hand]({static}/images/light-switch/light1.jpg)
## Function
I have a Raspberry Pi ($35 computer) on my home network that runs a web server.
When you connect to it in your web browser, a page loads with buttons to turn
the light on or off. When you press a button, the server executes a command that
sends a message over Bluetooth to the light switch. The Bluetooth module in the
wall receives this message and forwards it to the microcontroller, which
processes it and toggles the relay. The whole circuit is also powered from mains
by an AC-DC converter.
This entire process happens quicker than half a second, so it feels instant.
![a rusted metalic hand]({static}/images/light-switch/light2.jpg)
![a rusted metalic hand]({static}/images/light-switch/light3.jpg)

40
content/painting.md Normal file
View File

@ -0,0 +1,40 @@
Title: Mans Reach Exceeds His Grasp
Date: 2012-04-11
Category: Projects
Summary: My first attempt at painting with acrylic.
The painting is called “Mans Reach Exceeds His Grasp”. I've always wanted to
try painting and thought I had a good idea, so after a couple of drawings I
attempted to paint it. I eventually got it framed at Michaels. Many thanks to my
friend Laura for the opportunity to do this, I couldn't have done it without her
help.
![a painting of water pouring out of a vase and into a hand]({static}/images/painting/painting1.jpg)
## The Meaning
Its hard to see in the photo, but the moment the water touches his hand it
turns into sand and is taken by the slight breeze. The title is a quote from
Andrea del Sarto, a poem by Robert Browning. It is also said by Nikola Teslas
character in my favourite movie, [The Prestige](https://www.imdb.com/title/tt0482571/).
“I, painting from myself and to myself,
Know what I do, am unmoved by mens blame
Or their praise either. Somebody remarks
Morello's outline there is wrongly traced,
His hue mistaken; what of that? or else,
Rightly traced and well ordered; what of that?
Speak as they please, what does the mountain care?
Ah, but a mans reach should exceed his grasp,
Or whats a heaven for?”
Robert Browning from *Andrea del Sarto*
## Creation
I started with the background, trying to make it blurry and out of focus, then
slowly progressed to the foreground. The hands were drawn in pencil and painted
in. It was quite difficult to get the blending and shadows perfect, but I had
Laura to tell me when things didn't look right. Below I am trying to figure out
what a hand looks like in a mirror.
![me looking at my own hand in the mirror]({static}/images/painting/painting2.jpg)

39
content/plant-waterer.md Normal file
View File

@ -0,0 +1,39 @@
Title: Automatic Plant Waterer
Date: 2014-06-05
Category: Projects
Summary: A device that automatically waters plants.
One day I decided watering my one plant was too much work, so I automated it.
It's also great for when I'm on vacation. The plant is a year old now and
doesn't look as good as it used to (kinda like you). So this machine is like its
life support.
Update: this plant died long ago.
![the device and pump on a 2L pop bottle with a tube running to a flowerpot]({static}/images/plant-waterer/waterer1.jpg)
## First Attempt
The design was very simple and soldered together on perf board. A
microcontroller turns the pump on for 20 seconds, then waits 24 hours and
restarts. The pump ran way too fast so it was slowed down to 10% power.
This design suffered from a fatal problem. After running, there was a chance
that the tube would stay full of fluid. If the water level in the pop bottle was
too high, it could siphon out. I woke up with a flower pot overflowing with
water a couple of times.
![a new version feeding into a different plant]({static}/images/plant-waterer/waterer2.jpg)
## Second Attempt
I liked the idea so much that I made a second iteration. This one used a custom
printed circuit board with a lot more features. The pumping duration could be
adjusted with a screwdriver. This was useful as the plant (now a
[Ming aralia](https://en.wikipedia.org/wiki/Polyscias_fruticosa)) grew.
Another feature was the ability to run the pump backwards. This completely
eliminated the siphoning problem from before. After pumping for a set duration,
it would run backwards until the tube was cleared of water.
![the new version beside a big Min aralia plant]({static}/images/plant-waterer/waterer3.jpg)

23
content/solar-car.md Normal file
View File

@ -0,0 +1,23 @@
Title: Solar Car
Date: 2013-04-27
Category: Projects
Summary: About my time volunteering with the University of Calgary Solar Car Team, where I designed a maximum power point tracker.
I joined the University of Calgary Solar Car Team in my first semester for a
chance to learn things, gain practical experience, and meet people that share my
interests. The car was the top Canadian team in a 3000 km race from Darwin to
Adelaide, Australia in 2011. We met up at a shop on campus every Saturday
morning to work on the new Generation IV of the solar car.
![the MPPT device, a printed circuit board with components]({static}/images/solar-car/solar1.jpg)
## The Helianthus MPPT
I was in charge of designing and assembling the MPPTs (maximum power point
trackers) for the new generation solar car. An MPPT extracts as much power out
of the solar cells as possible. The solar array operates less efficiently
without them. The Generation IV car, Schulich Delta (pictured below) uses seven
of them: one per section of solar cells with similar lighting conditions. Andrei
and I designed the MPPT above.
![our team of 30 standing behind the solar car which is covered in sponsor logos]({static}/images/solar-car/solar2.jpg)

Binary file not shown.

View File

@ -1,18 +0,0 @@
{
"name": "my-razzle-app",
"version": "2.0.0-alpha.8",
"license": "MIT",
"scripts": {
"start": "razzle start",
"build": "razzle build",
"test": "razzle test --env=jsdom",
"start:prod": "NODE_ENV=production node build/server.js"
},
"dependencies": {
"express": "^4.16.3",
"razzle": "^2.2.0",
"react": "^16.4.1",
"react-dom": "^16.4.1",
"react-router-dom": "^4.3.1"
}
}

40
pelicanconf.py Normal file
View File

@ -0,0 +1,40 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*- #
from __future__ import unicode_literals
AUTHOR = 'Tanner'
SITENAME = 'Tanner Collin'
SITEURL = ''
PATH = 'content'
TIMEZONE = 'Canada/Mountain'
DEFAULT_LANG = 'en'
# Feed generation is usually not desired when developing
FEED_ALL_ATOM = None
CATEGORY_FEED_ATOM = None
TRANSLATION_FEED_ATOM = None
AUTHOR_FEED_ATOM = None
AUTHOR_FEED_RSS = None
DEFAULT_PAGINATION = False
MARKDOWN = {
'extension_configs': {
'markdown.extensions.codehilite': {'css_class': 'highlight'},
'markdown.extensions.extra': {},
'markdown.extensions.meta': {},
'markdown.extensions.toc': {
'toc_depth': '2-3',
'anchorlink': True,
},
},
'output_format': 'html5',
}
# Uncomment following line if you want document-relative URLs when developing
#RELATIVE_URLS = True
THEME = 'themes/theme'

Binary file not shown.

Before

Width:  |  Height:  |  Size: 32 KiB

View File

@ -1,48 +0,0 @@
/* http://meyerweb.com/eric/tools/css/reset/
v2.0 | 20110126
License: none (public domain)
*/
html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
b, u, i, center,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td,
article, aside, canvas, details, embed,
figure, figcaption, footer, header, hgroup,
menu, nav, output, ruby, section, summary,
time, mark, audio, video {
margin: 0;
padding: 0;
border: 0;
font-size: 100%;
font: inherit;
vertical-align: baseline;
}
/* HTML5 display-role reset for older browsers */
article, aside, details, figcaption, figure,
footer, header, hgroup, menu, nav, section {
display: block;
}
body {
line-height: 1;
}
ol, ul {
list-style: none;
}
blockquote, q {
quotes: none;
}
blockquote:before, blockquote:after,
q:before, q:after {
content: '';
content: none;
}
table {
border-collapse: collapse;
border-spacing: 0;
}

View File

@ -1,2 +0,0 @@
User-agent: *

25
publishconf.py Normal file
View File

@ -0,0 +1,25 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*- #
from __future__ import unicode_literals
# This file is only used if you use `make publish` or
# explicitly specify it as your config file.
import os
import sys
sys.path.append(os.curdir)
from pelicanconf import *
# If your site is available via HTTPS, make sure SITEURL begins with https://
SITEURL = ''
RELATIVE_URLS = False
FEED_ALL_ATOM = 'feeds/all.atom.xml'
CATEGORY_FEED_ATOM = 'feeds/{slug}.atom.xml'
DELETE_OUTPUT_DIRECTORY = True
# Following items are often useful when publishing
#DISQUS_SITENAME = ""
#GOOGLE_ANALYTICS = ""

View File

@ -1,10 +0,0 @@
* {
box-sizing: border-box;
}
body {
line-height: 1.6;
font-size: 1.125rem;
color: #333;
background-color: #F9F9F9;
}

View File

@ -1,13 +0,0 @@
import React from 'react';
import Route from 'react-router-dom/Route';
import Switch from 'react-router-dom/Switch';
import Home from './Home';
import './App.css';
const App = () => (
<Switch>
<Route exact path='/' component={Home} />
</Switch>
);
export default App;

View File

@ -1,191 +0,0 @@
.grid-container {
background: #bad4ff;
max-width: 120rem;
margin: 0 auto;
}
.grid-item {
//background: linear-gradient(135deg, #87e0fd 0%,#53cbf1 40%,#05abe0 100%);
position: relative;
float: left;
width: 30rem;
min-width: 25rem;
min-height: 25rem;
padding-bottom: 30rem;
}
.grid-item-content {
position: absolute;
width: 100%;
height: 100%;
padding: 1rem;
}
.menu {
display: flex;
flex-flow: column;
}
.menu .logo {
object-fit: contain;
padding-top: 1em;
min-height: 5rem;
}
.menu section {
min-height: 0;
flex: 1;
}
.menu section aside {
position: relative;
top: 50%;
transform: translateY(-50%);
text-align: right;
}
.menu section img {
height: 100%;
float: right;
padding: 2rem;
}
.project {
display: flex;
flex-flow: column;
}
.project header {
font-size: 2.25rem;
line-height: 1.2;
}
.project section {
min-height: 0;
flex: 1;
}
.project.bottom section {
flex-flow: column;
display: flex;
}
.project.left section p {
position: relative;
top: 50%;
transform: translateY(-50%);
}
.project.left section img {
height: 100%;
float: right;
padding: 1rem;
}
.project.bottom section p {
margin-bottom: 1rem;
}
.project.bottom section img {
object-fit: contain;
min-height: 0;
padding: 1rem;
}
.project footer {
display: flex;
justify-content: space-between;
margin: 0 1em;
font-size: 1rem;
font-family: monospace;
}
.photo a {
display: block;
position: relative;
height: 100%;
}
.photo header, .photo footer {
display: none;
position: absolute;
width: 100%;
z-index: 2;
background: rgba(0, 0, 0, 0.4);
color: white;
}
.photo header {
top: 0;
font-size: 1.5rem;
padding: 0.5rem;
}
.photo footer {
bottom: 0;
justify-content: space-between;
padding: 0 1em;
font-size: 1rem;
font-family: monospace;
}
.photo a:hover header {
display: block;
}
.photo a:hover footer {
display: flex;
}
.photo img {
position: absolute;
height: 100%;
left: 0;
}
@media all and (max-width: 120rem) {
.grid-item {
width: 25%;
padding-bottom: 25%
}
}
@media all and (max-width: 102rem) {
.grid-item {
width: 33.33%;
padding-bottom: 33.33%;
}
}
@media all and (max-width: 76.5rem) {
.grid-container {
max-width: 68rem;
}
.grid-item {
width: 50%;
padding-bottom: 50%;
}
}
@media all and (max-width: 51rem) {
.grid-container {
max-width: 34rem;
}
.grid-item {
width: 100%;
padding-bottom: 100%;
margin-bottom: 1rem;
}
.grid-item-content.photo {
padding: 0;
}
.photo a header {
display: block;
}
.photo a footer {
display: flex;
}
}

View File

@ -1,125 +0,0 @@
import React from 'react';
import './Grid.css';
import logo from './logo.png';
import GridItem from './GridItem';
import tanner from './tanner.jpg';
import dress1 from './dress1.jpg';
import switch1 from './switch1.jpg';
import pump1 from './pump1.jpg';
import hand1 from './hand1.jpg';
import banff1 from './banff1.jpg';
import bee1 from './bee1.jpg';
import canmore1 from './canmore1.jpg';
import carshow1 from './carshow1.jpg';
//function importAll(r) {
// return r.keys().map(x => r(x));
//}
//const images = importAll(require.context('./images'));
class Grid extends React.Component {
render() {
return (
<div className='grid-container'>
<GridItem type='menu'>
<img src={logo} className='logo' alt='' />
<section>
<img src={tanner} alt='' />
<aside>
<p>Home</p>
<p>Projects</p>
<p>Photograhy</p>
<p>Art</p>
<p>About</p>
<p>Contact</p>
</aside>
</section>
<footer>More info or a .onion link.</footer>
</GridItem>
<GridItem type='project left'>
<header>LED Dress</header>
<section>
<img src={dress1} alt='' />
<p>A dress lit up with LEDs that act as twinkling stars. Seven act as The Big Dipper, and the rest twinkle randomly.</p>
</section>
<footer>
<p>Project (Hardware)</p><p>2018-10-11</p>
</footer>
</GridItem>
<GridItem type='photo'>
<a>
<header>Thorncliffe Car Show</header>
<img src={carshow1} alt='' />
<footer>
<p>Photography</p><p>2018-10-11</p>
</footer>
</a>
</GridItem>
<GridItem type='project bottom'>
<header>Remote Control Lightswitch</header>
<section>
<img src={switch1} alt='' />
<p>Custom circuit that lets me control a ceiling light over Wifi.</p>
</section>
<footer>
<p>Project (Hardware)</p><p>2018-10-11</p>
</footer>
</GridItem>
<GridItem type='project bottom'>
<header>Plant Waterer</header>
<section>
<img src={pump1} alt='' />
<p>Controller that waters my plant automatically every day.</p>
</section>
<footer>
<p>Project (Hardware)</p><p>2018-10-11</p>
</footer>
</GridItem>
<GridItem type='photo'>
<a>
<header>Prince's Island Park</header>
<img src={bee1} alt='' />
<footer>
<p>Photography</p><p>2018-10-11</p>
</footer>
</a>
</GridItem>
<GridItem type='photo'>
<a>
<header>Johnston Creek, Banff</header>
<img src={banff1} alt='' />
<footer>
<p>Photography</p><p>2018-10-11</p>
</footer>
</a>
</GridItem>
<GridItem type='project left'>
<header>Hand of Ozymandias</header>
<section>
<img src={hand1} alt='' />
<p>Sculpture welded together out of scrap metal for practice.</p>
</section>
<footer>
<p>Project (Hardware)</p><p>2018-10-11</p>
</footer>
</GridItem>
<GridItem type='photo'>
<a>
<header>VW Van in Canmore</header>
<img src={canmore1} alt='' />
<footer>
<p>Photography</p><p>2018-10-11</p>
</footer>
</a>
</GridItem>
</div>
);
}
}
export default Grid;

View File

@ -1,15 +0,0 @@
import React from 'react';
class GridItem extends React.Component {
render() {
return (
<div className='grid-item'>
<div className={'grid-item-content ' + this.props.type}>
{this.props.children}
</div>
</div>
);
}
}
export default GridItem;

View File

@ -1,3 +0,0 @@
.Home {
text-align: center;
}

View File

@ -1,16 +0,0 @@
import React from 'react';
import './Home.css';
import Grid from './Grid';
class Home extends React.Component {
render() {
return (
<div className='Home'>
<Grid />
</div>
);
}
}
export default Home;

Binary file not shown.

Before

Width:  |  Height:  |  Size: 565 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 220 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 301 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 371 KiB

View File

@ -1,15 +0,0 @@
import App from './App';
import BrowserRouter from 'react-router-dom/BrowserRouter';
import React from 'react';
import { hydrate } from 'react-dom';
hydrate(
<BrowserRouter>
<App />
</BrowserRouter>,
document.getElementById('root')
);
if (module.hot) {
module.hot.accept();
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 MiB

View File

@ -1,26 +0,0 @@
import app from './server';
import http from 'http';
const server = http.createServer(app);
let currentApp = app;
server.listen(process.env.PORT || 3000, error => {
if (error) {
console.log(error);
}
console.log('🚀 started');
});
if (module.hot) {
console.log('✅ Server-side HMR Enabled!');
module.hot.accept('./server', () => {
console.log('🔁 HMR Reloading `./server`...');
server.removeListener('request', currentApp);
const newApp = require('./server').default;
server.on('request', newApp);
currentApp = newApp;
});
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 MiB

View File

@ -1,52 +0,0 @@
import App from './App';
import React from 'react';
import { StaticRouter } from 'react-router-dom';
import express from 'express';
import { renderToString } from 'react-dom/server';
const assets = require(process.env.RAZZLE_ASSETS_MANIFEST);
const server = express();
server
.disable('x-powered-by')
.use(express.static(process.env.RAZZLE_PUBLIC_DIR))
.get('/*', (req, res) => {
const context = {};
const markup = renderToString(
<StaticRouter context={context} location={req.url}>
<App />
</StaticRouter>
);
if (context.url) {
res.redirect(context.url);
} else {
res.status(200).send(
`<!doctype html>
<html lang="">
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta charset="utf-8" />
<title>Tanner Collin</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="reset.css">
${
assets.client.css
? `<link rel="stylesheet" href="${assets.client.css}">`
: ''
}
${
process.env.NODE_ENV === 'production'
? `<script src="${assets.client.js}" defer></script>`
: `<script src="${assets.client.js}" defer crossorigin></script>`
}
</head>
<body>
<div id="root">${markup}</div>
</body>
</html>`
);
}
});
export default server;

Binary file not shown.

Before

Width:  |  Height:  |  Size: 848 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 324 KiB

File diff suppressed because one or more lines are too long

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,59 @@
@font-face {
font-family: 'Apparatus SIL';
src: url('AppSILR.ttf') format('truetype');
font-display: swap;
}
@font-face {
font-family: 'Apparatus SIL';
font-style: italic;
src: url('AppSILI.ttf') format('truetype');
font-display: swap;
}
@font-face {
font-family: 'Apparatus SIL';
font-weight: bold;
src: url('AppSILB.ttf') format('truetype');
font-display: swap;
}
@font-face {
font-family: 'Apparatus SIL';
font-weight: bold;
font-style: italic;
src: url('AppSILBI.ttf') format('truetype');
font-display: swap;
}
@font-face {
font-family: 'Lato';
font-style: italic;
font-weight: 400;
src: local('Lato Italic'), local('Lato-Italic'), url('Lato-Italic.ttf') format('truetype');
font-display: swap;
}
@font-face {
font-family: 'Lato';
font-style: italic;
font-weight: 700;
src: local('Lato Bold Italic'), local('Lato-BoldItalic'), url('Lato-BoldItalic.ttf') format('truetype');
font-display: swap;
}
@font-face {
font-family: 'Lato';
font-style: normal;
font-weight: 400;
src: local('Lato Regular'), local('Lato-Regular'), url('Lato-Regular.ttf') format('truetype');
font-display: swap;
}
@font-face {
font-family: 'Lato';
font-style: normal;
font-weight: 700;
src: local('Lato Bold'), local('Lato-Bold'), url('Lato-Bold.ttf') format('truetype');
font-display: swap;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

BIN
themes/theme/static/me.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 124 KiB

View File

@ -0,0 +1,21 @@
{% extends "base.html" %}
{% block content %}
<p><a href="/">← Return to Home</a></p>
<header>
<h1>{{ article.title }}</h1>
<div class="summary">
{{ article.summary }}
</div>
<p class="metadata">
{{ article.locale_date }}
{% if article.modified %}
— updated {{ article.locale_modified }}
{% endif %}
</p>
</header>
<hr />
<article>
{{ article.content }}
</article>
{% endblock %}

View File

@ -0,0 +1,48 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta charset="utf-8"/>
<style>
{% include 'style.css' %}
</style>
<link rel="stylesheet" type="text/css" href="/theme/fonts/fonts.css" />
<title>Tanner Collin</title>
</head>
<body>
<div class="container">
<div class="sidebar">
<img src="/theme/me.jpg" alt="A picture of me smiling" />
<p>
Tanner Collin
</p>
</div>
<div class="content">
<div class="topbar">
<p>
<img src="/theme/logo.png" alt="My name in handwriting" />
</p>
</div>
{% block content %}
{% endblock %}
</div>
</div>
<script src="/theme/darkmode-js.min.js"></script>
<script>
const options = {
bottom: '16px',
right: '16px',
buttonColorDark: '#666',
buttonColorLight: '#aaa',
label: '🌙',
};
new Darkmode(options).showWidget();
</script>
</body>
</html>

View File

@ -0,0 +1,42 @@
{% extends "base.html" %}
{% block content %}
<p>
Hi, I'm Tanner! I do firmware design and web development.
</p>
<h2>Contact Info</h2>
<p>
Email: <a href="mailto:site@tannercollin.com">site@tannercollin.com</a> <br />
Telegram: <a href="https://t.me/tannercollin" target="_blank">@tannercollin</a>
</p>
<h2>Resume</h2>
<ul>
<li>Firmware Engineer at <a href="https://cabanablockchain.com" target="_blank">Cabana Blockchain</a>, 2018</li>
<li>Lead Hardware Engineer at <a href="https://criticalcontrol.com/" target="_blank">Critical Control</a>, 20162018</li>
<li>Electrical Engineer at <a href="https://www.opener.aero/" target="_blank">Opener Aero</a>, 20162016</li>
<li>Electrical Engineer Intern at <a href="https://www.pason.com/" target="_blank">Pason Systems</a>, 20142015</li>
<li>BSc. Electrical Engineering from University of Calgary</li>
</ul>
<h2>Projects</h2>
<p>
My main hobby is working on technical projects. I typically design websites or
build tools that make my life easier. Sometimes art.
</p>
<p>
You can find my code on <a href="https://github.com/tannercollin" target="_blank">GitHub</a>.
</p>
{% for article in articles_page.object_list %}
<h3><a href="{{ article.url }}">{{ article.title }}</a></h3>
<div class="summary">
{{ article.summary }}
</div>
{% endfor %}
{% endblock %}

View File

@ -0,0 +1,141 @@
html {
overflow-y: scroll;
}
body {
text-rendering: optimizeLegibility;
font: 1.2rem/1.0 Lato,sans-serif;
background-color: rgb(245, 245, 245);
background-color: white;
}
a {
color: #000000;
text-decoration: none;
outline: none;
border-bottom: 1px solid #000;
}
pre {
font-size: 1rem;
background-color: #eee;
padding: 1rem;
}
.container {
max-width: 56rem;
margin: 2rem auto 0 auto;
}
.sidebar {
margin-top: 2px;
float: left;
width: 8rem;
text-align: right;
}
.sidebar img {
width: 100%;
display: block;
}
.sidebar p {
margin-top: 2rem;
}
.topbar {
text-align: center;
margin-bottom: 1.5rem;
}
.content .topbar img {
filter: invert(100%);
width: 14rem;
height: auto;
}
.toc {
float: right;
background-color: #eee;
padding: 0.75rem;
padding-top: 0;
}
.toc ul {
padding-left: 1.2rem;
margin: 0;
}
.toc li {
margin-top: 0.75rem;
}
.content p.metadata {
color: #555;
font: 1rem/1.0 Apparatus SIL,serif;
font-style: italic;
}
.content div.summary p {
margin-top: -0.5rem;
margin-left: 1rem;
font-style: italic;
}
.content {
max-width: 36rem;
}
.content p {
font: 1.2rem/1.5 Apparatus SIL,serif;
}
.content ul {
padding-left: 1.1rem;
}
.content li {
font: 1.2rem/1.5 Apparatus SIL,serif;
}
.content img {
width: 100%;
height: auto;
}
.toclink:not(:hover)::after {
visibility: hidden;
}
.toclink::after {
color: #999;
content: "\00B6";
margin-left: 0.5rem;
}
@media screen and (min-width:36rem) {
.content {
margin-left: 10rem;
}
.topbar {
display: none;
}
}
@media screen and (max-width:36rem) {
.sidebar {
display: none;
}
}
.darkmode-toggle {
z-index: 500;
}
.darkmode--activated .content img {
filter: brightness(75%);
}
.darkmode--activated video {
mix-blend-mode: difference;
}

7647
yarn.lock

File diff suppressed because it is too large Load Diff