New 70s theme
continuous-integration/drone Build is passing Details
continuous-integration/drone/promote/production Build was killed Details

master
Garrett Mills 1 year ago
parent 07167e770a
commit 17b51b82cc

@ -1,9 +1,133 @@
import { env } from '@extollo/lib'
export interface ColorPalette {
displayName: string
background: string
backgroundOffset: string
backgroundOffset2: string
hero: string
font: string
fontMuted: string
box: string
link: string
noiseSize: string
line1: string
line2: string
line3: string
}
export default {
name: env('APP_NAME', 'Garrett Mills'),
analytics: {
optOutCookie: env('ANALYTICS_OPT_OUT_COOKIE', 'analytics.opt-out'),
}
},
colors: {
lostInTheStars: {
displayName: "Lost in the Stars",
background: '#4a113c',
backgroundOffset: 'rgba(178, 127, 170, 0.1)',
backgroundOffset2: 'rgba(178, 127, 170, 0.2)',
hero: '#6ebbd5',
font: '#ffe3ff',
fontMuted: '#daa7d2',
box: '#b27faa',
link: 'var(--c-hero)',
noiseSize: '100px',
line1: 'rgba(178, 127, 170, 0.2)',
line2: 'rgba(110, 187, 213, 0.9)',
line3: 'rgba(218, 167, 210, 0.9)',
},
tanOrangeAndRed: {
displayName: "Tan, Orange, & Red",
background: '#f8e4bf',
backgroundOffset: 'rgb(243, 210, 147, 0.4)',
backgroundOffset2: 'rgb(111, 71, 46, 0.15)',
hero: '#d96a59',
font: '#6f472e',
fontMuted: '#ae7813',
box: '#e0b95d',
link: 'var(--c-hero)',
noiseSize: '100px',
line1: '#edb34f',
line2: '#f88937',
line3: '#e86c36',
},
blueAndTan: {
displayName: "Blue & Tan",
background: '#052653',
backgroundOffset: 'rgba(27, 111, 145, 0.3)',
backgroundOffset2: 'rgba(127, 167, 158, 0.15)',
hero: '#f6a56d',
font: '#f6dbb0',
fontMuted: '#dec99a',
box: '#87afa6',
link: 'var(--c-hero)',
noiseSize: '100px',
line1: '#fbad6f',
line2: '#f47139',
line3: '#de381e',
},
teals: {
displayName: "Teals",
background: '#c6c2b9',
backgroundOffset: 'rgba(150, 171, 162, 0.3)',
backgroundOffset2: 'rgba(150, 171, 162, 0.7)',
hero: '#d05a40',
font: '#3f4962',
fontMuted: '#5d6780',
box: '#96aba2',
link: 'var(--c-hero)',
noiseSize: '100px',
line1: '#dcbb8e',
line2: '#95aaa3',
line3: '#3f4962',
},
redAndGold: {
displayName: "Red & Gold",
background: '#510c00',
backgroundOffset: 'rgba(111, 42, 30, 0.4)',
backgroundOffset2: 'rgba(111, 42, 30, 1)',
hero: '#ee6156',
font: '#f2d7b4',
fontMuted: '#cb9866',
box: '#e9b1a0',
link: 'var(--c-hero)',
noiseSize: '100px',
line1: '#e9c8a0',
line2: '#f6bb4a',
line3: '#ef4c3f',
},
mashGreen: {
displayName: "M*A*S*H Green",
background: '#202318',
backgroundOffset: 'rgba(46, 41, 22, 0.5)',
backgroundOffset2: 'rgb(105, 75, 1, 0.3)',
hero: '#7a7946',
font: '#e5ddae',
fontMuted: '#cb9866',
box: '#cbc87c',
link: 'var(--c-hero)',
noiseSize: '100px',
line1: '#b5a148',
line2: '#ecb653',
line3: '#71490b',
},
purpleAndWhite: {
displayName: "Purple & White",
background: '#6669aa',
backgroundOffset: 'rgba(152, 155, 220, 0.4)',
backgroundOffset2: 'rgba(81, 84, 143, 0.6)',
hero: '#efe2df',
font: '#fff4ed',
fontMuted: '#b5b7ec',
box: '#989bdc',
link: 'var(--c-hero)',
noiseSize: '100px',
line1: '#979adb',
line2: '#b3b5f1',
line3: '#efe2df',
},
} as Record<string, ColorPalette>,
}

@ -1,6 +1,7 @@
import {Controller, view, Injectable, Collection, Inject, Routing, plaintext} from '@extollo/lib'
import {FeedPost} from '../../models/FeedPost.model'
import * as RSSFeed from 'feed'
import {Home} from './Home.controller'
/**
* Feed Controller
@ -13,8 +14,10 @@ export class Feed extends Controller {
protected readonly routing!: Routing
public async feed(feedPosts: Collection<FeedPost>) {
const home = <Home> this.make(Home)
return view('feed', {
feedPosts: feedPosts.toArray(),
...home.getThemeCSS(),
})
}

@ -10,13 +10,14 @@ import {
file,
Application,
make,
Valid, Logging, api,
Valid, Logging, api, Session,
} from '@extollo/lib'
import {WorkItem} from '../../models/WorkItem.model'
import {FeedPost} from '../../models/FeedPost.model'
import {ContactForm} from '../../types/ContactForm.type'
import {ContactSubmission} from '../../models/ContactSubmission.model'
import {Gotify} from 'gotify'
import {ColorPalette} from '../../configs/app.config'
@Injectable()
export class Home extends Controller {
@ -35,6 +36,9 @@ export class Home extends Controller {
@Inject()
protected readonly logging!: Logging
@Inject()
protected readonly session!: Session
public async welcome(feedPosts: Collection<FeedPost>) {
const workItems = await this.getWorkItems()
@ -44,6 +48,7 @@ export class Home extends Controller {
.unique()
return view('welcome', {
...this.getThemeCSS(),
feedPosts: feedPosts.toArray(),
workItemGroups: workItems.groupBy(item => item.startDate.getFullYear()),
workItemYears: workItemYears.toArray(),
@ -56,6 +61,7 @@ export class Home extends Controller {
return view('technical', {
isOptOut,
...this.getThemeCSS(),
})
}
@ -65,6 +71,7 @@ export class Home extends Controller {
message: 'This will set a cookie to disable analytics recording in your browser on all <code>*.garrettmills.dev</code> sites. Continue?',
buttonAction: this.routing.getNamedPath('opt-out').toRemote,
buttonMethod: 'post',
...this.getThemeCSS(),
})
}
@ -84,6 +91,7 @@ export class Home extends Controller {
title: 'Analytics Opt-Out',
message: 'You have been opted-out of analytics recording.',
buttonAction: this.routing.getNamedPath('home').toRemote,
...this.getThemeCSS(),
})
}
@ -117,6 +125,7 @@ export class Home extends Controller {
title: 'Message Sent',
message: 'Your message has been sent. Thanks! I\'ll be in touch soon.',
buttonAction: this.routing.getNamedPath('home').toRemote,
...this.getThemeCSS(),
})
}
@ -145,4 +154,34 @@ export class Home extends Controller {
}).then(x => this.logging.debug(x))
.catch(e => this.logging.error(e))
}
public getThemeCSS(): any {
const themes = this.config.get('app.colors') as Record<string, ColorPalette>
const themeKeys = Object.keys(themes)
const themeName = this.session.get('theme.name')
// const themeName = this.request.safe('theme').or(themeKeys[Math.floor(Math.random()*themeKeys.length)]).in(themeKeys)
const theme = themes[themeName]
const themeCSS = `
:root {
--c-background: ${theme.background};
--c-background-offset: ${theme.backgroundOffset};
--c-background-offset-2: ${theme.backgroundOffset2};
--c-hero: ${theme.hero};
--c-font: ${theme.font};
--c-font-muted: ${theme.fontMuted};
--c-box: ${theme.box};
--c-link: ${theme.link};
--c-noise-size: ${theme.noiseSize};
--c-line-1: ${theme.line1};
--c-line-2: ${theme.line2};
--c-line-3: ${theme.line3};
}
`
return {
themeName,
themeCSS,
themeDisplayName: theme.displayName,
themeKeys,
}
}
}

@ -1,5 +1,6 @@
import {Controller, http, HTTPStatus, Inject, Injectable, Logging, view} from '@extollo/lib'
import {Snippet} from '../../models/Snippet.model'
import {Home} from './Home.controller'
/**
* Snippets Controller
@ -19,11 +20,14 @@ export class Snippets extends Controller {
await snippet.delete()
}
const home = <Home> this.make(Home)
return view('snippet', {
snippet,
needsAccessKey,
needsConfirm,
accessKey: this.request.input('accessKey'),
...home.getThemeCSS(),
})
}
}

@ -0,0 +1,37 @@
import {Middleware, Injectable, Inject, Config, Session} from '@extollo/lib'
import {ColorPalette} from '../../configs/app.config'
/**
* SiteTheme Middleware
* --------------------------------------------
* Determines the correct color theme for the request.
*/
@Injectable()
export class SiteTheme extends Middleware {
@Inject()
protected readonly config!: Config
@Inject()
protected readonly session!: Session
public async apply() {
const themes = this.config.get('app.colors') as Record<string, ColorPalette>
const themeKeys = Object.keys(themes)
const existingThemeName = this.session.get('theme.name')
const forceNewTheme = Boolean(this.request.input('forceNewTheme'))
const explicitTheme = String(this.request.input('theme') || '')
if ( explicitTheme && themeKeys.includes(explicitTheme) ) {
this.session.set('theme.name', explicitTheme)
return
}
if ( existingThemeName && !forceNewTheme ) {
return
}
const themeName = themeKeys[Math.floor(Math.random() * themeKeys.length)]
this.session.set('theme.name', themeName)
}
}

@ -8,6 +8,7 @@ import {LoadSnippet} from '../middlewares/parameters/LoadSnippet.middleware'
import {LoadFeedPosts} from '../middlewares/parameters/LoadFeedPosts.middleware'
import {ValidContactForm} from '../middlewares/parameters/ValidContactForm.middleware'
import {RateLimit} from '../middlewares/RateLimit.middleware'
import {SiteTheme} from '../middlewares/SiteTheme.middleware'
Route.endpoint('options', '**')
.handledBy(() => api.one({}))
@ -15,6 +16,7 @@ Route.endpoint('options', '**')
Route
.group('/', () => {
Route.get('/')
.pre(SiteTheme)
.parameterMiddleware(LoadFeedPosts)
.calls<Home>(Home, home => home.welcome)
.alias('home')
@ -24,6 +26,7 @@ Route
Route.post('/contact')
.pre(RateLimit)
.pre(SiteTheme)
.parameterMiddleware(ValidContactForm)
.calls<Home>(Home, home => home.contact)
.alias('contact')
@ -38,17 +41,21 @@ Route
.calls<Home>(Home, home => home.humans)
Route.get('/technical')
.pre(SiteTheme)
.calls<Home>(Home, home => home.technical)
Route.get('/analytics/opt-out')
.pre(SiteTheme)
.calls<Home>(Home, home => home.optOutPrompt)
.alias('opt-out-prompt')
Route.post('/analytics/opt-out')
.pre(SiteTheme)
.calls<Home>(Home, home => home.optOut)
.alias('opt-out')
Route.get('/snippet/:slug')
.pre(SiteTheme)
.parameterMiddleware(LoadSnippet)
.calls<Snippets>(Snippets, snippets => snippets.viewSnippet)
@ -56,10 +63,12 @@ Route
.calls<GoLinks>(GoLinks, go => go.launch)
Route.get('/favicon.ico')
.pre(SiteTheme)
.calls<Home>(Home, home => home.favicon)
Route.group('feed', () => {
Route.get('/')
.pre(SiteTheme)
.parameterMiddleware(LoadFeedPosts, {all: true})
.calls<Feed>(Feed, feed => feed.feed)
.alias('feed')

@ -0,0 +1,93 @@
Copyright 2011 The Lora Project Authors (https://github.com/cyrealtype/Lora-Cyrillic), with Reserved Font Name "Lora".
This Font Software is licensed under the SIL Open Font License, Version 1.1.
This license is copied below, and is also available with a FAQ at:
http://scripts.sil.org/OFL
-----------------------------------------------------------
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
-----------------------------------------------------------
PREAMBLE
The goals of the Open Font License (OFL) are to stimulate worldwide
development of collaborative font projects, to support the font creation
efforts of academic and linguistic communities, and to provide a free and
open framework in which fonts may be shared and improved in partnership
with others.
The OFL allows the licensed fonts to be used, studied, modified and
redistributed freely as long as they are not sold by themselves. The
fonts, including any derivative works, can be bundled, embedded,
redistributed and/or sold with any software provided that any reserved
names are not used by derivative works. The fonts and derivatives,
however, cannot be released under any other type of license. The
requirement for fonts to remain under this license does not apply
to any document created using the fonts or their derivatives.
DEFINITIONS
"Font Software" refers to the set of files released by the Copyright
Holder(s) under this license and clearly marked as such. This may
include source files, build scripts and documentation.
"Reserved Font Name" refers to any names specified as such after the
copyright statement(s).
"Original Version" refers to the collection of Font Software components as
distributed by the Copyright Holder(s).
"Modified Version" refers to any derivative made by adding to, deleting,
or substituting -- in part or in whole -- any of the components of the
Original Version, by changing formats or by porting the Font Software to a
new environment.
"Author" refers to any designer, engineer, programmer, technical
writer or other person who contributed to the Font Software.
PERMISSION & CONDITIONS
Permission is hereby granted, free of charge, to any person obtaining
a copy of the Font Software, to use, study, copy, merge, embed, modify,
redistribute, and sell modified and unmodified copies of the Font
Software, subject to the following conditions:
1) Neither the Font Software nor any of its individual components,
in Original or Modified Versions, may be sold by itself.
2) Original or Modified Versions of the Font Software may be bundled,
redistributed and/or sold with any software, provided that each copy
contains the above copyright notice and this license. These can be
included either as stand-alone text files, human-readable headers or
in the appropriate machine-readable metadata fields within text or
binary files as long as those fields can be easily viewed by the user.
3) No Modified Version of the Font Software may use the Reserved Font
Name(s) unless explicit written permission is granted by the corresponding
Copyright Holder. This restriction only applies to the primary font name as
presented to the users.
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
Software shall not be used to promote, endorse or advertise any
Modified Version, except to acknowledge the contribution(s) of the
Copyright Holder(s) and the Author(s) or with their explicit written
permission.
5) The Font Software, modified or unmodified, in part or in whole,
must be distributed entirely under this license, and must not be
distributed under any other license. The requirement for fonts to
remain under this license does not apply to any document created
using the Font Software.
TERMINATION
This license becomes null and void if any of the above conditions are
not met.
DISCLAIMER
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
OTHER DEALINGS IN THE FONT SOFTWARE.

@ -0,0 +1,71 @@
Lora Variable Font
==================
This download contains Lora as both variable fonts and static fonts.
Lora is a variable font with this axis:
wght
This means all the styles are contained in these files:
Lora-VariableFont_wght.ttf
Lora-Italic-VariableFont_wght.ttf
If your app fully supports variable fonts, you can now pick intermediate styles
that arent available as static fonts. Not all apps support variable fonts, and
in those cases you can use the static font files for Lora:
static/Lora-Regular.ttf
static/Lora-Medium.ttf
static/Lora-SemiBold.ttf
static/Lora-Bold.ttf
static/Lora-Italic.ttf
static/Lora-MediumItalic.ttf
static/Lora-SemiBoldItalic.ttf
static/Lora-BoldItalic.ttf
Get started
-----------
1. Install the font files you want to use
2. Use your app's font picker to view the font family and all the
available styles
Learn more about variable fonts
-------------------------------
https://developers.google.com/web/fundamentals/design-and-ux/typography/variable-fonts
https://variablefonts.typenetwork.com
https://medium.com/variable-fonts
In desktop apps
https://theblog.adobe.com/can-variable-fonts-illustrator-cc
https://helpx.adobe.com/nz/photoshop/using/fonts.html#variable_fonts
Online
https://developers.google.com/fonts/docs/getting_started
https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Fonts/Variable_Fonts_Guide
https://developer.microsoft.com/en-us/microsoft-edge/testdrive/demos/variable-fonts
Installing fonts
MacOS: https://support.apple.com/en-us/HT201749
Linux: https://www.google.com/search?q=how+to+install+a+font+on+gnu%2Blinux
Windows: https://support.microsoft.com/en-us/help/314960/how-to-install-or-remove-a-font-in-windows
Android Apps
https://developers.google.com/fonts/docs/android
https://developer.android.com/guide/topics/ui/look-and-feel/downloadable-fonts
License
-------
Please read the full license text (OFL.txt) to understand the permissions,
restrictions and requirements for usage, redistribution, and modification.
You can use them in your products & projects print or digital,
commercial or otherwise.
This isn't legal advice, please consider consulting a lawyer and see the full
license for all details.

@ -0,0 +1,657 @@
@font-face {
font-family: "TheWobliy";
src: url("/assets/font/wobily/TheWobliy-rgeop.otf");
font-weight: normal;
font-display: swap;
}
@font-face {
font-family: "Lora";
src: url("/assets/font/lora/static/Lora-Regular.ttf");
font-weight: normal;
font-display: swap;
}
/* These get injected by the view template */
/* Purple & blue: */
/*:root {
--c-background: #4a113c;
--c-background-offset: rgba(178, 127, 170, 0.1);
--c-background-offset-2: rgba(178, 127, 170, 0.2);
--c-hero: #6ebbd5;
--c-font: #ffe3ff;
--c-font-muted: #daa7d2;
--c-box: #b27faa;
--c-link: var(--c-hero);
--c-noise-size: 100px;
--c-line-1: rgba(178, 127, 170, 0.2);
--c-line-2: rgba(110, 187, 213, 0.9);
--c-line-3: rgba(218, 167, 210, 0.9);
}*/
/* Tan, red, & orange */
/*:root {
--c-background: #f8e4bf;
--c-background-offset: rgb(243, 210, 147, 0.4);
--c-background-offset-2: rgb(111, 71, 46, 0.15);
--c-hero: #d96a59;
--c-font: #6f472e;
--c-font-muted: #ae7813;
--c-box: #e0b95d;
--c-link: var(--c-hero);
--c-noise-size: 100px;
--c-line-1: #edb34f;
--c-line-2: #f88937;
--c-line-3: #e86c36;
}*/
/** Blue & tan */
/*:root {
--c-background: #052653;
--c-background-offset: rgba(27, 111, 145, 0.3);
--c-background-offset-2: rgba(127, 167, 158, 0.15);
--c-hero: #f6a56d;
--c-font: #f6dbb0;
--c-font-muted: #dec99a;
--c-box: #87afa6;
--c-link: var(--c-hero);
--c-noise-size: 100px;
--c-line-1: #fbad6f;
--c-line-2: #f47139;
--c-line-3: #de381e;
}*/
/* Teal & dark blue text */
/*:root {
--c-background: #c6c2b9;
--c-background-offset: rgba(150, 171, 162, 0.3);
--c-background-offset-2: rgba(150, 171, 162, 0.7);
--c-hero: #d05a40;
--c-font: #3f4962;
--c-font-muted: #5d6780;
--c-box: #96aba2;
--c-link: var(--c-hero);
--c-noise-size: 100px;
--c-line-1: #dcbb8e;
--c-line-2: #95aaa3;
--c-line-3: #3f4962;
}*/
/* Red & gold */
/*:root {
--c-background: #510c00;
--c-background-offset: rgba(111, 42, 30, 0.4);
--c-background-offset-2: rgba(111, 42, 30, 1);
--c-hero: #ee6156;
--c-font: #f2d7b4;
--c-font-muted: #cb9866;
--c-box: #e9b1a0;
--c-link: var(--c-hero);
--c-noise-size: 100px;
--c-line-1: #e9c8a0;
--c-line-2: #f6bb4a;
--c-line-3: #ef4c3f;
}*/
/* Army green lol */
/*:root {
--c-background: #202318;
--c-background-offset: rgba(46, 41, 22, 0.5);
--c-background-offset-2: rgb(105, 75, 1, 0.3);
--c-hero: #7a7946;
--c-font: #e5ddae;
--c-font-muted: #cb9866;
--c-box: #cbc87c;
--c-link: var(--c-hero);
--c-noise-size: 100px;
--c-line-1: #b5a148;
--c-line-2: #ecb653;
--c-line-3: #71490b;
}*/
/* purple & white */
/*:root {
--c-background: #6669aa;
--c-background-offset: rgba(152, 155, 220, 0.4);
--c-background-offset-2: rgba(81, 84, 143, 0.6);
--c-hero: #efe2df;
--c-font: #fff4ed;
--c-font-muted: #b5b7ec;
--c-box: #989bdc;
--c-link: var(--c-hero);
--c-noise-size: 100px;
--c-line-3: #979adb;
--c-line-2: #b3b5f1;
--c-line-1: #efe2df;
}*/
.section-border {
width: 100vw;
position: absolute;
left: 0;
}
.section-border .section-border-inner-1 {
border-top: 15px solid var(--c-line-1);
border-bottom: 15px solid var(--c-line-3);
transform: rotate(3deg);
width: calc(100vw + 30px);
margin-left: -15px;
position: absolute;
}
.section-border.odd .section-border-inner-1 {
transform: rotate(-3deg);
}
.section-border .section-border-inner-2 {
border-top: 15px solid var(--c-line-2);
}
body {
background: var(--c-background);
color: var(--c-font);
font-family: "Lora", serif;
margin: 0;
padding: 0;
overflow-x: hidden;
}
section {
/*min-height: 100vh;*/
z-index: 100;
/*display: flex;*/
/*flex-direction: column;*/
/*justify-content: center;*/
padding-bottom: 150px;
margin-top: 100px;
}
.full-height {
min-height: 100vh;
display: flex;
flex-direction: column;
justify-content: center;
}
.text-noise {
background-image: url(data:image/png;base64,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);
background-size: var(--c-noise-size);
background-repeat: repeat;
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
-webkit-font-smoothing: antialiased;
image-rendering: crisp-edges;
image-rendering: -moz-crisp-edges; /* Firefox */
image-rendering: -o-crisp-edges; /* Opera */
image-rendering: -webkit-optimize-contrast; /* Webkit (non-standard naming)*/
-ms-interpolation-mode: nearest-neighbor; /* IE (non-standard property) */
}
.container {
display: flex;
justify-content: center;
width: 100%;
height: 100%;
text-align: left;
position: relative;
}
body:before {
content: ' ';
display: block;
position: fixed;
left: 0;
top: 0;
width: 100%;
height: 100%;
opacity: 0.3;
background-image: url(data:image/png;base64,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);
background-size: var(--c-noise-size);
image-rendering: crisp-edges;
image-rendering: -moz-crisp-edges; /* Firefox */
image-rendering: -o-crisp-edges; /* Opera */
image-rendering: -webkit-optimize-contrast; /* Webkit (non-standard naming)*/
-ms-interpolation-mode: nearest-neighbor; /* IE (non-standard property) */
}
h1, h2, h3, h4 {
/*line-height: 1.2em;*/
font-family: "TheWobliy", serif;
color: var(--c-hero);
background-color: var(--c-hero);
background-image: url(data:image/png;base64,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);
background-size: var(--c-noise-size);
background-repeat: repeat;
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
-webkit-font-smoothing: antialiased;
image-rendering: crisp-edges;
image-rendering: -moz-crisp-edges; /* Firefox */
image-rendering: -o-crisp-edges; /* Opera */
image-rendering: -webkit-optimize-contrast; /* Webkit (non-standard naming)*/
-ms-interpolation-mode: nearest-neighbor; /* IE (non-standard property) */
}
h1 {
font-size: 80pt;
margin: 0;
padding: 0;
}
h2 {
font-size: 60pt;
padding-top: 70px;
padding-bottom: 0;
margin: 0;
font-weight: 300;
}
h3 {
font-size: 24pt;
/*text-transform: lowercase;*/
margin: 0;
padding: 30px 0 0;
font-weight: 300;
}
h4 {
font-size: 18pt;
margin: 0;
padding: 40px 0 0;
font-weight: 300;
}
p {
font-size: 18pt;
font-weight: 300;
}
li {
font-size: 16pt;
font-weight: 300;
}
code {
font-size: 12pt;
background: var(--c-background-offset-2);
padding: 5px;
border-radius: 5px;
}
pre code {
display: block;
}
.inner {
padding-bottom: 10%;
max-width: min(70%, 1000px);
min-height: 100vh;
}
.theme-hide {
display: none !important;
}
button,
a.button,
a.button-small {
border: 0;
font-family: "TheWobliy", serif;
color: var(--c-hero);
background-color: var(--c-hero);
background-image: url(data:image/png;base64,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);
background-size: var(--c-noise-size);
background-repeat: repeat;
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
-webkit-font-smoothing: antialiased;
image-rendering: crisp-edges;
image-rendering: -moz-crisp-edges; /* Firefox */
image-rendering: -o-crisp-edges; /* Opera */
image-rendering: -webkit-optimize-contrast; /* Webkit (non-standard naming)*/
-ms-interpolation-mode: nearest-neighbor; /* IE (non-standard property) */
font-size: 16pt;
padding: 5px 20px;
transition: background-color 0.1s linear;
text-decoration: none;
}
button:hover,
a.button:hover,
a.button-small:hover {
cursor: pointer;
background-color: var(--c-font);
}
button:active,
a.button:active,
a.button-small:active {
background-color: var(--c-background-offset-2);
}
a {
color: var(--c-link);
}
/*a.button-small,
button.small {
padding: 1px 10px;
background: #c9d4e2;
border: none;
color: #3e4552;
margin: 5px;
}*/
/*a.button-small:hover,
button.small:hover {
color: #c9d4e2;
background: #3e4552;
}*/
.form-group {
margin: 10px;
}
.form-group label {
font-size: 14pt;
font-weight: 300;
text-transform: lowercase;
}
.form-group input,
.form-group textarea,
.form-group select {
/*border: 1px solid #3e4552;*/
border: 0;
border-bottom: 2px solid var(--c-box);
/*border-radius: 5px;*/
font-family: Lora, serif;
padding: 7px;
font-size: 16pt;
min-width: 400px;
background: rgba(0, 0, 0, 0);
color: var(--c-font);
}
.form-group input::placeholder,
.form-group textarea::placeholder,
.form-group select::placeholder {
color: var(--c-font-muted);
}
footer {
position: relative;
/*background: #3e4552;*/
background: var(--c-background-offset);
display: flex;
flex-direction: row;
justify-content: center;
padding-bottom: 50px;
}
footer ul {
list-style-type: none;
margin: 0;
padding: 50px 0 0;
}
footer ul li {
display: inline;
padding-left: 20px;
padding-right: 20px;
}
footer ul li a {
text-decoration: none;
font-size: 16pt;
font-weight: 300;
transition: all 0.5s;
color: var(--c-font);
}
footer ul li a:hover {
color: var(--c-hero);
}
footer .col {
margin: 0 30px;
}
footer .by-line {
font-family: "TheWobliy", serif;
background-color: var(--c-hero);
background-image: url(data:image/png;base64,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);
background-size: var(--c-noise-size);
background-repeat: repeat;
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
-webkit-font-smoothing: antialiased;
color: var(--c-hero);
display: flex;
flex-direction: column;
justify-content: center;
font-size: 42pt;
font-weight: 300;
text-align: right;
padding-top: 30px;
image-rendering: crisp-edges;
image-rendering: -moz-crisp-edges; /* Firefox */
image-rendering: -o-crisp-edges; /* Opera */
image-rendering: -webkit-optimize-contrast; /* Webkit (non-standard naming)*/
-ms-interpolation-mode: nearest-neighbor; /* IE (non-standard property) */
}
footer .copy {
font-size: 14pt;
font-weight: 200;
}
footer ul li {
display: block;
margin: 10px 0;
}
footer #tagline:hover {
cursor: pointer;
}
footer .auth-container {
display: flex;
flex-direction: row;
}
footer .auth-container .profile {
margin-right: 15px;
margin-top: 15px;
}
.button-links {
margin: 20px;
}
.button-links a {
margin-right: 10px;
}
@media (max-width: 480px) {
.container {
justify-content: left;
padding: 20px;
width: calc(100% - 40px);
}
.inner {
width: 100%;
max-width: unset;
}
.form-group input,
.form-group textarea,
.form-group select {
min-width: 100%;
}
footer {
flex-direction: column;
}
footer .by-line {
/*text-align: left;*/
padding: 30px;
line-height: 1.2em;
text-align: center;
}
footer .links {
padding: 20px 0 0;
}
h2 {
font-size: 48pt;
line-height: 1.2em;
}
}
.hero {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
margin-top: 150px;
}
.hero-box {
border: 2px solid var(--c-box);
padding: 0 20px;
text-align: center;
background-color: var(--c-background-offset);
}
.hero h1 {
font-weight: 300;
font-size: 9em;
line-height: 1.2em;
font-family: "TheWobliy", serif;
background-image: url(data:image/png;base64,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);
background-size: var(--c-noise-size);
background-repeat: repeat;
background-color: var(--c-hero);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
-webkit-font-smoothing: antialiased;
image-rendering: crisp-edges;
image-rendering: -moz-crisp-edges; /* Firefox */
image-rendering: -o-crisp-edges; /* Opera */
image-rendering: -webkit-optimize-contrast; /* Webkit (non-standard naming)*/
-ms-interpolation-mode: nearest-neighbor; /* IE (non-standard property) */
}
.hero h2 {
font-size: 36pt;
padding: 0;
font-weight: 300;
margin: 10px 0 0;
font-family: "TheWobliy", serif;
/*text-transform: lowercase;*/
}
.hero p {
font-size: 20pt;
font-family: "TheWobliy", serif;
background-color: var(--c-font);
background-image: url(data:image/png;base64,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);
background-size: var(--c-noise-size);
background-repeat: repeat;
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
-webkit-font-smoothing: antialiased;
image-rendering: crisp-edges;
image-rendering: -moz-crisp-edges; /* Firefox */
image-rendering: -o-crisp-edges; /* Opera */
image-rendering: -webkit-optimize-contrast; /* Webkit (non-standard naming)*/
-ms-interpolation-mode: nearest-neighbor; /* IE (non-standard property) */
}
section#about .about-container {
display: flex;
flex-direction: row;
}
section#about .img {
flex-grow: 0;
flex-shrink: 0;
}
section#about .img img {
max-width: 300px;
margin-top: 30px;
margin-right: 20px;
border-radius: 5px;
}
section#work .timeline-group .timeline-year {
font-family: "TheWobliy", serif;
font-size: 24pt;
margin-top: 40px;
background-color: var(--c-font);
background-image: url(data:image/png;base64,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);
background-size: var(--c-noise-size);
background-repeat: repeat;
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
-webkit-font-smoothing: antialiased;
image-rendering: crisp-edges;
image-rendering: -moz-crisp-edges; /* Firefox */
image-rendering: -o-crisp-edges; /* Opera */
image-rendering: -webkit-optimize-contrast; /* Webkit (non-standard naming)*/
-ms-interpolation-mode: nearest-neighbor; /* IE (non-standard property) */
}
section#work .timeline-group .timeline-content {
/*background: #3e4552;*/
padding: 20px;
/*border-radius: 5px;*/
border: 2px solid var(--c-box);
background-color: var(--c-background-offset);
margin: 20px;
}
section#work .timeline-group .timeline-content h3 {
padding: 0;
font-size: 2.5em;
}
section#work .timeline-group .timeline-content p {
margin: 0;
font-size: 16pt;
}
section#contact .contact-container {
display: flex;
flex-direction: row;
}
section#contact .contact-container .message {
text-align: right;
margin-right: 20px;
}
section#recent .feed-item {
background: var(--c-background-offset);
padding: 20px;
margin: 20px;
/*border-radius: 5px;*/
border: 2px solid var(--c-box);
}
section#recent .feed-item .feed-category {
display: flex;
}
section#recent .feed-item .feed-category .tag {
/*background: #5e6572;*/
padding: 2px 5px;
/*border-radius: 2px;*/
font-size: 14pt;
background: var(--c-background-offset-2);
}
section#recent .feed-item .bottom {
display: flex;
flex-direction: row;
justify-content: end;
}
section#recent .feed-item .bottom .stamp {
margin-left: 20px;
font-size: 14pt;
font-weight: 300;
text-align: right;
flex: 1;
}
section#recent a.button {
margin-left: 20px;
}
section#auth {
max-width: 500px;
}
section#auth h3 {
margin-bottom: 30px;
}
@media (max-width: 480px) {
.hero h1 {
font-size: 48pt;
}
section#about .about-container {
display: flex;
flex-direction: column;
}
section#work .timeline-content {
margin: 20px 0 !important;
}
section#contact .contact-container {
display: flex;
flex-direction: column;
}
section#contact .contact-container .message {
text-align: left;
}
section#recent .feed-item {
margin: 20px 0;
}
section#recent a.button {
margin-left: 0;
}
section#recent .bottom {
flex-wrap: wrap;
}
section#recent .bottom .stamp {
max-width: 100%;
white-space: pre-wrap;
word-wrap: break-word;
}
}
.theme-buttons .button {
white-space: nowrap;
}
.theme-buttons {
list-style-type: none;
margin: 0;
padding: 50px 0 0;
}
.theme-buttons li {
padding-left: 20px;
padding-right: 20px;
}
.theme-buttons li a {
text-decoration: none;
font-size: 16pt;
font-weight: 300;
transition: all 0.5s;
color: var(--c-font);
}
.theme-buttons li a:hover {
color: var(--c-hero);
}

@ -3,18 +3,20 @@ window.glmdev = window.glmdev || {}
window.glmdev.taglines = [
'...is proud that this site is Google-free',
'...is a supporter of FLOSS',
'...prefers JavaScript, but Python will do',
'...prefers TypeScript, but C++ will do',
'...occasionally rants about dependency injection',
'...loves GNU/Linux',
'(or as I\'ve recently taken to calling it, GNU+Linux)',
'...uses spaces, not tabs',
'...self-hosts all the things',
'...uses the Oxford comma',
'...occasionally does contract work',
'...reads the terms and conditions',
'...enjoys r/sysadmin',
'...is an RSS nerd',
'...just lost the game',
'...listens to indie music',
'...is running out of tag-line ideas',
`copyright &copy; ${(new Date()).getFullYear()} garrett mills`,
`copyright &copy; ${(new Date()).getFullYear()}`,
]
document.querySelector('#tagline')

@ -1,10 +1,11 @@
extends template_raj
extends template_70s
block content
.container#top
.inner
.hero
h1 garrettmills
.hero-box
h1 Garrett Mills
section#recent
h2 posts & updates
.button-links

@ -1,4 +1,4 @@
extends template_raj
extends template_70s
block content
.container#home

@ -1,4 +1,4 @@
extends template_raj
extends template_70s
block append style
link(rel='stylesheet' data-name='vs/editor/editor.main' href=asset('monaco/package/min/vs/editor/editor.main.css'))
@ -7,7 +7,8 @@ block content
.container#home
if needsAccessKey
.inner
h2 Snippet: #{snippet.slug}
h2 Snippet
h3 #{snippet.slug}
p This snippet is protected by an access key. Please enter it to view:
form(method='get')
.form-group
@ -15,7 +16,8 @@ block content
button View
else if needsConfirm
.inner
h2 Snippet: #{snippet.slug}
h2 Snippet
h3 #{snippet.slug}
p This snippet is single-access only. Once you view it, it will be permanently deleted. Continue?
form(method='get')
if accessKey
@ -24,7 +26,8 @@ block content
button Continue
else
.inner(style='width: 100%')
h2 Snippet: #{snippet.slug}
h2 Snippet
h3 #{snippet.slug}
#monaco-container(style="width: 100%; height: 100%")
block append script

@ -1,15 +1,29 @@
extends template_raj
extends template_70s
block content
.container#top
.inner
.hero
h1 garrettmills
.hero-box
h1 Garrett Mills
section#technical
h2 technical details for nerds
h2(style="font-size: 48pt") technical details for nerds
.fira-p
p This page contains a smattering of technical information that I think some people might find interesting, but not enough people for it to be included on the main page.
h3 Website Theme
p I was going for a retro/70s aesthetic for this site. The CSS theme is fully-parameterized over a set of color variables.
p The first time you visit the homepage, the server randomly selects a theme for your browser to use across the site.
p I'm using a combination of <a href="https://creativemarket.com/storytypefont/6695985-The-Wobliy-Retro-Serif-Font" target="_blank">The Wobliy</a> as a display font and <a href="http://cyreal.org/fonts/lora" target="_blank">Lora</a> as a body font.
p For the curious, you can change the theme using the buttons below:
ul.theme-buttons
each key in themeKeys
li
a.button(href=`../technical?theme=${key}`) #{config(`app.colors.${key}.displayName`)}#{key === themeName ? ' (current)' : ''}
br
br
h3 Source Code & Licensing
a(href='https://creativecommons.org/licenses/by-nc-sa/4.0/' target='_blank' style='margin-top: 15px')
img(src=asset('cc-by-nc-sa.png'))

@ -0,0 +1,77 @@
doctype html
head
block meta
meta(charset='utf-8')
meta(name='viewport' content='width=device-width, initial-scale=1, shrink-to-fit=no')
meta(http-equiv='x-ua-compatible' content='ie=edge')
meta(name='description' content='Hi, there! My name is Garrett. I am a computer scientist, software engineer, and speaker.')
meta(name='keywords' content='garrett mills glmdev developer speaker flitter extollo student')
meta(name='author' content=config('app.name', 'Garrett Mills'))
meta(name='robots' content='index, follow')
block title
title #{config('app.name', 'Garrett Mills')} | Developer, Speaker, Designer
block style
style !{themeCSS}
link(rel='stylesheet' href=asset('main-70s.css'))
link(rel='author' href='/humans.txt')
link(rel="alternate" href="/feed/atom.xml" title="Garrett Mills - Posts & Updates" type="application/atom+xml")
link(rel="alternate" href="/feed/rss.xml" title="Garrett Mills - Posts & Updates" type="application/rss+xml")
link(rel="alternate" href="/feed/json.json" title="Garrett Mills - Posts & Updates" type="application/feed+json")
link(rel='apple-touch-icon' sizes='180x180' href=asset('favicon/apple-touch-icon.png'))
link(rel='manifest' href=asset('favicon/site.webmanifest'))
link(rel='icon' type='image/png' sizes='32x32' href=asset('favicon/favicon-32x32.png'))
link(rel='icon' type='image/png' sizes='16x16' href=asset('favicon/favicon-16x16.png'))
link(rel='shortcut icon' href=asset('favicon/favicon.ico'))
body
block content
footer
.ff-tag(style="margin-right: 80px")
a(href="https://www.mozilla.org/en-US/firefox/browsers/" target="_blank")
img(src=asset('ffox.png') width="75" style="margin-top: -1px")
.by-line Garrett Mills
.copy#tagline(title="my, aren't you curious...") copyright &copy; #{(new Date()).getFullYear()}
.copyright(style='display: flex; justify-content: right')
a(style='display: flex; padding-top: 10px' href='https://creativecommons.org/licenses/by-nc-sa/4.0/' target='_blank')
img(src=asset('cc-by-nc-sa-small.png') title='This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License')
if user()
div.auth-container(style="justify-content: end")
if user().profileUrl
div.profile
img(src=user().profileUrl width=50 style="border-radius: 50%")
p(style="font-family: Lora, serif") Welcome, #{user().getDisplay()}!&nbsp;&nbsp;|&nbsp;&nbsp;<a href="#{named('@auth:coreid:logout')}">Log out</a>
.col
ul.links
li
a(href='/#home') home
li
a(href='/#about') about me
li
a(href='/#work') what I'm working on
li
a(href='/#contact') get in touch
li
a(href='/#recent') latest updates
.col
ul.links
li
a(href='https://static.garrettmills.dev/Resume.pdf' target='_blank') résumé
li
a(href='/blog') blog
li
a(href='https://code.garrettmills.dev/garrettmills' target='_blank') my code
li
a(href='/technical') technical info
li
a(href='?forceNewTheme=true') random theme
if user()
li
a(href='/dash') dashboard
block script
script(src=asset('welcome.js'))

@ -1,10 +1,15 @@
extends template_raj
extends template_70s
block content
.container#home
.inner
.hero
h1 garrettmills
p Hi, there. My name is Garrett, and I'm a computer scientist, software engineer, and speaker.
section.hero.full-height
.hero-box
h1 Garrett Mills
p Software engineer, computer scientist, and nerd.
//p Hi, there. My name is Garrett, and I'm a computer scientist, software engineer, and speaker.
.section-border
.section-border-inner-1
.section-border-inner-2
section#about
h2 about me
.about-container
@ -13,7 +18,9 @@ block content
.about
p Hi! My name is Garrett. Welcome to my corner of the internet. I'm a computer scientist, software engineer, and speaker. I like to build software to improve the developer/user experience. I created the <a href="https://extollo.garrettmills.dev" target="_blank">Extollo</a> framework, <a href="https://code.garrettmills.dev/Noded" target="_blank">Noded</a>, <a href="https://code.garrettmills.dev/starship/coreid" target="_blank">CoreID</a> authentication server, and a couple other projects. I love to communicate my work, and help others pursue their projects. I write <a href="/blog" target="_blank">blog posts</a>, hold talks, and publish code from my projects in the hope that others will find it useful. I also do a bit of <a href="https://glmdev.tech" target="_blank">consulting</a>.
p A bit more background: I grew up in the rural mid-west, and I got started by teaching myself everything I know. I'm a big fan of learning to code this way. I completed a bachelor of science in computer science at the University of Kansas, and I'm currently a graduate student studying programming languages and formal methods at KU.
.section-border.odd
.section-border-inner-1
.section-border-inner-2
if workItemYears && workItemYears.length
section#work
h2 what I'm working on
@ -32,7 +39,9 @@ block content
p !{item.description}
.work-container
button#timeline-view-all show past work
.section-border
.section-border-inner-1
.section-border-inner-2
section#contact
h2 get in touch
.contact-container
@ -50,7 +59,9 @@ block content
textarea.form-control#contactMessage(name='message' placeholder='Message' required rows=6)
.form-group
button Send
.section-border.odd
.section-border-inner-1
.section-border-inner-2
section#recent
h2 latest updates
each item in feedPosts

Loading…
Cancel
Save