Initial release

Signed-off-by: Marcus Noble <github@marcusnoble.co.uk>
main
Marcus Noble 2 months ago
commit cfa8450f9d
Signed by: AverageMarcus
GPG Key ID: B8F2DB8A7AEBAF78
  1. 170
      .gitignore
  2. 13
      Dockerfile
  3. 19
      LICENSE
  4. 61
      Makefile
  5. 5
      README.md
  6. 116
      data.yaml
  7. 5
      go.mod
  8. 4
      go.sum
  9. 87
      main.go
  10. BIN
      src/fonts/OrkneyBold.ttf
  11. BIN
      src/fonts/OrkneyLight.ttf
  12. BIN
      src/fonts/OrkneyRegular.ttf
  13. BIN
      src/headshot-transparent.avif
  14. BIN
      src/headshot-transparent.png
  15. BIN
      src/headshot-transparent.webp
  16. 295
      src/index.html

170
.gitignore vendored

@ -0,0 +1,170 @@
### Git ###
# Created by git for backups. To disable backups in Git:
# $ git config --global mergetool.keepBackup false
*.orig
# Created by git when using merge tools for conflicts
*.BACKUP.*
*.BASE.*
*.LOCAL.*
*.REMOTE.*
*_BACKUP_*.txt
*_BASE_*.txt
*_LOCAL_*.txt
*_REMOTE_*.txt
### Go ###
# Binaries for programs and plugins
*.exe
*.exe~
*.dll
*.so
*.dylib
# Test binary, built with `go test -c`
*.test
# Output of the go coverage tool, specifically when used with LiteIDE
*.out
# Dependency directories (remove the comment below to include it)
# vendor/
### Go Patch ###
/vendor/
/Godeps/
### Node ###
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*
# Diagnostic reports (https://nodejs.org/api/report.html)
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
*.lcov
# nyc test coverage
.nyc_output
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
bower_components
# node-waf configuration
.lock-wscript
# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules/
jspm_packages/
# TypeScript v1 declaration files
typings/
# TypeScript cache
*.tsbuildinfo
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variables file
.env
.env.test
# parcel-bundler cache (https://parceljs.org/)
.cache
# next.js build output
.next
# nuxt.js build output
.nuxt
# rollup.js default build output
dist/
# Storybook build outputs
.out
.storybook-out
# vuepress build output
.vuepress/dist
# Serverless directories
.serverless/
# FuseBox cache
.fusebox/
# DynamoDB Local files
.dynamodb/
# Temporary folders
tmp/
temp/
# VSCode
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
*.code-workspace
.history/
# MacOS
# General
.DS_Store
.AppleDouble
.LSOverride
# Thumbnails
._*
# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
.com.apple.timemachine.donotpresent
# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk

@ -0,0 +1,13 @@
FROM golang:1.17-alpine AS builder
RUN apk update && apk add --no-cache git && apk add -U --no-cache ca-certificates
WORKDIR /app/
ADD go.mod go.sum ./
RUN go mod download
ADD . .
RUN GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -ldflags="-w -s" -o marcusnoble .
FROM scratch
WORKDIR /app/
COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
COPY --from=builder /app/marcusnoble /app/marcusnoble
ENTRYPOINT ["/app/marcusnoble"]

@ -0,0 +1,19 @@
MIT License Copyright (c) 2022 - present Marcus Noble
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:
The above copyright notice and this permission notice (including the next
paragraph) shall be included in all copies or substantial portions of the
Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

@ -0,0 +1,61 @@
.DEFAULT_GOAL := default
IMAGE ?= rg.fr-par.scw.cloud/averagemarcus-private/marcusnoble:latest
.PHONY: test # Run all tests, linting and format checks
test: lint check-format run-tests
.PHONY: lint # Perform lint checks against code
lint:
@echo "⚠ 'lint' unimplemented"
.PHONY: check-format # Checks code formatting and returns a non-zero exit code if formatting errors found
check-format:
@echo "⚠ 'check-format' unimplemented"
.PHONY: format # Performs automatic format fixes on all code
format:
@echo "⚠ 'format' unimplemented"
.PHONY: run-tests # Runs all tests
run-tests:
@echo "⚠ 'run-tests' unimplemented"
.PHONY: fetch-deps # Fetch all project dependencies
fetch-deps:
@echo "⚠ 'fetch-deps' unimplemented"
.PHONY: build # Build the project
build: lint check-format fetch-deps
@echo "⚠ 'build' unimplemented"
.PHONY: docker-build # Build the docker image
docker-build:
@docker build -t $(IMAGE) .
.PHONY: docker-publish # Push the docker image to the remote registry
docker-publish:
@docker push $(IMAGE)
.PHONY: run # Run the application
run: docker-build
@docker run --rm -it -p 8080:80 -v $$(pwd)/src:/usr/share/nginx/html $(IMAGE)
.PHONY: ci # Perform CI specific tasks to perform on a pull request
ci:
@echo "⚠ 'ci' unimplemented"
.PHONY: release # Release the latest version of the application
release:
@kubectl --context scaleway --namespace marcusnoble set image deployment marcusnoble web=rg.fr-par.scw.cloud/averagemarcus-private/marcusnoble:$(SHA)
.PHONY: help # Show this list of commands
help:
@echo "marcusnoble"
@echo "Usage: make [target]"
@echo ""
@echo "target description" | expand -t20
@echo "-----------------------------------"
@grep '^.PHONY: .* #' Makefile | sed 's/\.PHONY: \(.*\) # \(.*\)/\1 \2/' | expand -t20
default: test build

@ -0,0 +1,5 @@
# Marcus Noble
Personal profile of Marcus Noble
Available at https://marcusnoble.com

@ -0,0 +1,116 @@
intro: |
I'm a <strong>platform engineer</strong> working at <a href="https://giantswarm.io">Giant Swarm</a> working on building managed Kubernetes solutions and related projects. My area of focus in recent years has been around Go, ⎈ Kubernetes, containers and DevOps but originally started out as a <em>web developer</em> and <em>JavaScript enthusiast</em>. I'm a “tinkerer” and like to dabble with 3D printing and experimenting with smart home tech.
social:
- url: https://marcusnoble.co.uk
title: My articles on my Blog
content: |
<svg height="32" viewBox="0 0 512 512">
<style>.st0{fill:#fff}.st1{fill:#ededed}.st4{fill:#333}.st8{fill:#f96363}.st9{fill:#fdd267}</style><path class="st0" d="M508 82.9v394.2c0 17-13.8 30.9-30.8 30.9H34.8C17.8 508 4 494.2 4 477.1V82.9h504z"/><path class="st1" d="M508 82.9v394.2c0 17-13.8 30.9-30.8 30.9h-28.6a31 31 0 0 0 30.9-30.9V82.9H508z"/><path d="M508 82.9v-48c0-17-13.8-30.8-30.8-30.8H34.9A30.7 30.7 0 0 0 4 34.9v48h504z" fill="#d3d9d9"/><path class="st1" d="M63.5 4c-17 0-30.9 13.8-30.9 30.8v48.1H4V34.8C4 17.8 17.8 4 34.8 4h28.7z"/><path d="M508 34.8v48.1h-28.6V34.8c0-17-13.8-30.8-30.9-30.8h28.7c17 0 30.8 13.8 30.8 30.8z" fill="#a8b2b4"/><path class="st4" d="M512 34.8A34.8 34.8 0 0 0 477.2 0H34.9A34.8 34.8 0 0 0 0 34.8v442.3A35 35 0 0 0 34.8 512h442.3a34.8 34.8 0 0 0 34.8-34.9l.1-442.3zm-504 0A26.9 26.9 0 0 1 34.9 8h442.3C492 8 504 20 504 34.8v44H8v-44zm496 442.3c0 14.8-12 26.9-26.8 26.9H34.8A26.9 26.9 0 0 1 8 477.1V86.9h496v390.2z"/><circle cx="50.6" cy="43.5" r="14" fill="#fc8a8a"/><circle cx="100.5" cy="43.5" r="14" fill="#fedd8e"/><circle cx="150.3" cy="43.5" r="14" fill="#7bde9e"/><path class="st8" d="M64.6 43.4a14 14 0 0 1-27.2 4.7 14 14 0 0 0 18-18c5.3 2.2 9.2 7.3 9.2 13.3z"/><path class="st9" d="M114.4 43.4a14 14 0 0 1-27.2 4.7 14 14 0 0 0 18-18c5.4 2.2 9.2 7.3 9.2 13.3z"/><path d="M164.3 43.4a14 14 0 0 1-27.2 4.7 14 14 0 0 0 17.8-18c5.5 2.2 9.4 7.3 9.4 13.3z" fill="#50d27e"/><path class="st4" d="M50.6 61.5c-9.9 0-18-8.1-18-18s8.1-18 18-18 18 8.1 18 18-8.1 18-18 18zm0-28c-5.5 0-10 4.5-10 10s4.5 10 10 10 10-4.5 10-10-4.5-10-10-10zm49.9 28c-9.9 0-18-8.1-18-18s8.1-18 18-18 18 8.1 18 18-8.1 18-18 18zm0-28c-5.5 0-10 4.5-10 10s4.5 10 10 10 10-4.5 10-10-4.5-10-10-10zm49.8 28c-9.9 0-18-8.1-18-18s8.1-18 18-18 18 8.1 18 18-8.1 18-18 18zm0-28c-5.5 0-10 4.5-10 10s4.5 10 10 10 10-4.5 10-10-4.5-10-10-10z"/><path class="st0" d="M475.4 43.4a14 14 0 0 1-14 14H229.7a14 14 0 1 1 0-28h231.7a14 14 0 0 1 14 14z"/><path class="st1" d="M475.4 43.4a14 14 0 0 1-14 14H229.7a14 14 0 0 1-14-13.3c2 1.1 4.3 1.7 6.7 1.7h231.7a14 14 0 0 0 14-14v-.6a14 14 0 0 1 7.3 12.2z"/><path class="st4" d="M461.4 61.4H229.7c-9.9 0-18-8.1-18-18s8.1-18 18-18h231.7c9.9 0 18 8.1 18 18s-8.1 18-18 18zm-231.7-28c-5.5 0-10 4.5-10 10s4.5 10 10 10h231.7c5.5 0 10-4.5 10-10s-4.5-10-10-10H229.7z"/><path d="M455.6 123.2v98.2H56.4v-98.2h399.2z" fill="#fb8a8a"/><path d="M455.6 123.2v21.7H56.4v-21.7h399.2z" fill="#fcb1b1"/><path class="st8" d="M56.4 199.7h399.2v21.6H56.4z"/><path class="st4" d="M455.6 225.3H56.4a4 4 0 0 1-4-4v-98.2a4 4 0 0 1 4-4h399.2a4 4 0 0 1 4 4v98.2a4 4 0 0 1-4 4zm-395.2-8h391.2v-90.2H60.4v90.2zm395.2 48.3H56.4c-2.2 0-4-1.8-4-4s1.8-4 4-4h399.2c2.2 0 4 1.8 4 4s-1.8 4-4 4zm0 206.1H56.4c-2.2 0-4-1.8-4-4s1.8-4 4-4h399.2c2.2 0 4 1.8 4 4s-1.8 4-4 4zm0-40.3H268.9c-2.2 0-4-1.8-4-4s1.8-4 4-4h186.7c2.2 0 4 1.8 4 4s-1.8 4-4 4zm0-41.8H268.9c-2.2 0-4-1.8-4-4s1.8-4 4-4h186.7c2.2 0 4 1.8 4 4s-1.8 4-4 4zm0-41.9H268.9c-2.2 0-4-1.8-4-4s1.8-4 4-4h186.7c2.2 0 4 1.8 4 4s-1.8 4-4 4zm0-41.9H268.9c-2.2 0-4-1.8-4-4s1.8-4 4-4h186.7c2.2 0 4 1.8 4 4s-1.8 4-4 4z"/><path fill="#fddd8d" d="M56.4 301.8h160.1v125.6H56.4z"/><path fill="#fee8b3" d="M56.4 301.8h160v26.1h-160z"/><path class="st9" d="M56.4 401.4h160v26.1h-160z"/><path class="st4" d="M216.4 431.4h-160a4 4 0 0 1-4-4V301.8a4 4 0 0 1 4-4h160.1a4 4 0 0 1 4 4v125.6a4 4 0 0 1-4.1 4zm-156-8h152.1V305.8H60.4v117.6z"/>
</svg>
Blog
- url: https://marcusnoble.co.uk
title: My articles on my Blog
content: |
<svg viewBox="0 0 60 60" height="32"><path d="M39 0H6.4v60h47V14.6L38.9 0zm.5 3.4L50.1 14H39.5V3.4zM8.5 58V2h29v14h14v42h-43z"/><path d="M34.5 37a1 1 0 1 0 0-2h-17a1 1 0 1 0 0 2h17zm10-7h-7a1 1 0 1 0 0 2h7a1 1 0 1 0 0-2zm-23 1c0 .6.4 1 1 1h10a1 1 0 1 0 0-2h-10a1 1 0 0 0-1 1zm-4.7-.7a1 1 0 0 0-.3.7 1 1 0 0 0 1 1c.3 0 .5-.1.7-.3.2-.2.3-.4.3-.7a1 1 0 0 0-.3-.7 1 1 0 0 0-1.4 0zm22 5a1 1 0 0 0-.3.7 1 1 0 0 0 1 1c.3 0 .5-.1.7-.3.2-.2.3-.4.3-.7a1 1 0 0 0-.3-.7 1 1 0 0 0-1.4 0zm5 0a1 1 0 0 0-.3.7 1 1 0 0 0 1 1c.3 0 .5-.1.7-.3.2-.2.3-.4.3-.7a1 1 0 0 0-.3-.7 1 1 0 0 0-1.4 0zM23 40.2c-2.2 1.1-2.9 3.3-3.2 5.5l-1.2-1c-1-.8-2.4.6-1.4 1.4l2.8 2.4c.6.5 1.7.2 1.7-.7 0-2.2.2-4.8 2.3-6 1.2-.5.2-2.2-1-1.6zm13.5 3.9c-1.5 0-3.6 2.2-4.8.2a1 1 0 0 0-1.3-.4c-1.4.9-3.3 2.1-4.8.5-.9-1-2.3.5-1.4 1.4 1.9 2 4.3 1.4 6.4.3.5.5 1 .9 1.8 1 .8.2 4-1 4.2-.8.8 1 2.5 0 1.8-1-.6-.8-1-1.1-2-1.2zM28.7 24l.6-.5-.3-.8c-.3-.6-.8-1.2-1.5-1.5l-2-1c.9-.7 1.6-1.6 2-2.9.7-.4 1.1-1.1 1.1-2v-.6c0-.7-.3-1.3-.8-1.8-.3-1.9-1.6-4-5.5-4h-.4a3 3 0 0 1-2-.4l-.5-.4c-.3-.4-.9-.6-1.3-.4a1 1 0 0 0-.7 1.2 11.2 11.2 0 0 0 .2 1.5l-.1.2-.3.6-.5 1.7c-.4.5-.7 1.1-.7 1.8v.6c0 .9.4 1.6 1 2a5.2 5.2 0 0 0 2.2 2.8L17 21.2a3 3 0 0 0-1.4 1.5l-.3.8.6.4a11 11 0 0 0 12.8 0zM18 23l2.5-1.3c.5-.3.8-.8.8-1.4V19l-.6-.2c-1-.4-1.5-1.2-1.8-2.4l-.2-.5-.5-.2a.3.3 0 0 1-.2-.3v-.6c0-.2 0-.3.2-.3l.4-.3v-.5l.5-1.6.2-.5.3-.9a5.3 5.3 0 0 0 2.7.4c3 0 3.5 1.3 3.6 2.6v.5l.6.3.1.3v.6c0 .2 0 .3-.2.3l-.5.2-.2.5c-.3 1.2-.9 2-1.8 2.4l-.6.2v1.5c0 .5.3 1 .8 1.3l2.4 1.2a9 9 0 0 1-8.5 0z"/></svg>
C.V.
- url: https://www.github.com/AverageMarcus
title: AverageMarcus on GitHubBlog
content: |
<svg viewBox="0 0 16 16" height="32"><path d="M7.999,0.431c-4.285,0-7.76,3.474-7.76,7.761 c0,3.428,2.223,6.337,5.307,7.363c0.388,0.071,0.53-0.168,0.53-0.374c0-0.184-0.007-0.672-0.01-1.32 c-2.159,0.469-2.614-1.04-2.614-1.04c-0.353-0.896-0.862-1.135-0.862-1.135c-0.705-0.481,0.053-0.472,0.053-0.472 c0.779,0.055,1.189,0.8,1.189,0.8c0.692,1.186,1.816,0.843,2.258,0.645c0.071-0.502,0.271-0.843,0.493-1.037 C4.86,11.425,3.049,10.76,3.049,7.786c0-0.847,0.302-1.54,0.799-2.082C3.768,5.507,3.501,4.718,3.924,3.65 c0,0,0.652-0.209,2.134,0.796C6.677,4.273,7.34,4.187,8,4.184c0.659,0.003,1.323,0.089,1.943,0.261 c1.482-1.004,2.132-0.796,2.132-0.796c0.423,1.068,0.157,1.857,0.077,2.054c0.497,0.542,0.798,1.235,0.798,2.082 c0,2.981-1.814,3.637-3.543,3.829c0.279,0.24,0.527,0.713,0.527,1.437c0,1.037-0.01,1.874-0.01,2.129 c0,0.208,0.14,0.449,0.534,0.373c3.081-1.028,5.302-3.935,5.302-7.362C15.76,3.906,12.285,0.431,7.999,0.431z"></path></svg>
GitHub
- url: https://twitter.com/Marcus_Noble_
title: "@Marcus_Noble_ on TwitterBlog"
content: |
<svg viewBox="0 0 16 16" height="32"><path d="M15.969,3.058c-0.586,0.26-1.217,0.436-1.878,0.515c0.675-0.405,1.194-1.045,1.438-1.809c-0.632,0.375-1.332,0.647-2.076,0.793c-0.596-0.636-1.446-1.033-2.387-1.033c-1.806,0-3.27,1.464-3.27,3.27 c0,0.256,0.029,0.506,0.085,0.745C5.163,5.404,2.753,4.102,1.14,2.124C0.859,2.607,0.698,3.168,0.698,3.767 c0,1.134,0.577,2.135,1.455,2.722C1.616,6.472,1.112,6.325,0.671,6.08c0,0.014,0,0.027,0,0.041c0,1.584,1.127,2.906,2.623,3.206 C3.02,9.402,2.731,9.442,2.433,9.442c-0.211,0-0.416-0.021-0.615-0.059c0.416,1.299,1.624,2.245,3.055,2.271 c-1.119,0.877-2.529,1.4-4.061,1.4c-0.264,0-0.524-0.015-0.78-0.046c1.447,0.928,3.166,1.469,5.013,1.469 c6.015,0,9.304-4.983,9.304-9.304c0-0.142-0.003-0.283-0.009-0.423C14.976,4.29,15.531,3.714,15.969,3.058z"></path></svg>
Twitter
- url: https://k8s.social/@Marcus
title: "@marcus@k8s.social on MastodonBlog"
content: |
<svg xmlns="http://www.w3.org/2000/svg" height="32" viewBox="80 80 360 360">
<path d="m409 290c-5 24-43 50-85 56-86 11-137-6-137-6 3 13-4 54 70 52 31 0 58-7 58-7l2 27c-51 24-107 15-140 6-67-17-79-90-81-162v-59c0-74 49-96 49-96 50-24 180-22 222 0 0 0 49 22 49 96 0 0 1 55-7 93"></path>
<path d="m358 202v91h-35v-88c0-18-8-27-23-27-18 0-27 11-27 33v47h-34v-47c0-22-9-33-27-33-15 0-23 9-23 27v88h-35v-91c0-18 5-60 52-60 39 0 50 37 50 37s10-37 50-37c45 0 52 42 52 60" fill="#3088d4"></path>
</svg>
Mastodon
- url: https://www.linkedin.com/in/marcusnoble/
title: Connect with me on LinkedinBlog
content: |
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" height="32">
<rect width="512" height="512" rx="15%"></rect>
<circle cx="142" cy="138" r="37" fill="#0077b5"></circle>
<path stroke="#0077b5" stroke-width="66" d="M244 194v198M142 194v198"></path>
<path fill="#0077b5" d="M276 282c0-20 13-40 36-40 24 0 33 18 33 45v105h66V279c0-61-32-89-76-89-34 0-51 19-59 32"></path>
</svg>
LinkedIn
- url: https://noti.st/averagemarcus
title: View my previous talks on NotistBlog
content: |
<svg height="32" viewBox="0 -20 520 218">
<path d="M127.7 127.6a47 47 0 0 1-36.5 18.8c-16.4 0-26.4-9.8-26.4-22.1 0-17.6 9.2-29.1 9.2-40.4 0-4.6-2.6-8-6.7-8-4.9 0-11.8 4.9-18.1 17.5A146.2 146.2 0 0 0 36.8 139c0 4.8-2 6-6.3 6-8.7 0-19.9 1.4-24.2 1.4-3.8 0-6-1.4-6-6.3 0-10.7 12-49.5 12-65 0-5-2-5.6-2-9.3 0-6.3 15.6-10.7 32.3-10.7 6.3 0 9.8 2.6 9.8 7.5 0 4.6-2.3 13-2.3 13C55.2 69.3 72.2 55 89.2 55c15.9 0 22.2 7.2 22.2 18.2 0 13.2-8 27.6-8 39.4 0 7.5 4 10.4 9.2 10.4 4.9 0 7.2-2.3 10.9-6l.7-.8a44 44 0 0 1-.4-6.4c0-28 22.2-56 61.6-56 21.3 0 36 14 36 33.8 0 32.2-20.4 59.9-55.8 59.9-18 0-31.6-7.4-37.9-20zM291.2 113c2.2-15.1 8.7-29.4 8.7-38 0-4.9-1.7-5.5-1.7-9.2 0-6.3 15.3-10.7 32-10.7 6.3 0 9.8 2.6 9.8 7.5 0 11.6-9.3 29.7-9.3 48.7 0 7.5 4.4 11.8 9.5 11.8 3.8 0 6-1.3 8.6-3.7 1-7.7 7-12.1 13-12.1 7.8 0 12.4 3.7 12.4 10.6 0 7.2 2.6 12.1 7.8 12.1 4 0 6.3-2.6 6.3-7.8 0-17-28.5-19.5-28.5-41.1 0-18.2 18.2-27.4 39.8-27.4 21 0 30.5 8 30.5 19.9 0 7.8-4 14.7-13.5 14.7-5.5 0-10.4-4.4-10.4-9.8 0-4.3 2.3-6 2.3-8.7 0-2.8-2.3-4-5.5-4-3.7 0-8.3 4-8.3 9.5 0 17 31.7 19.3 31.7 40.3 0 18.7-15 31.4-40.4 31.4-16.3 0-29.3-5.4-34.7-14.8a45.4 45.4 0 0 1-32.4 14.2c-16.8 0-26.2-8.3-28.1-19.5-9.3 9.2-24.2 19.5-38.4 19.5-20.7 0-29.7-12.3-29.7-27.6 0-18.4 9-32.8 9-47.2 0-3.8-7.8-1.5-7.8-6.7 0-2.8 1.7-8.3 4.9-8.3 15.3 0 29.4-15 36.9-27 2.8-4.7 5.1-6.4 7.7-6.4 3.2 0 4.6 2.3 4.6 4.6 0 6.3-4 18.1-4 23 0 3.8 1.2 5.8 9.8 5.8 2.3 0 4 .8 4 3.2 0 5.7-3.1 9.7-6.6 9.7-7.2 0-10.4 2.3-12.4 9.3-2.3 8.3-6 23-6 32.5 0 8.6 4.3 11.8 11.2 11.8 5.8 0 11.5-5.5 16.1-9.2l1-.9zm200.1-43.5c-7.2 0-10.3 2.3-12.4 9.3-2.3 8.3-6 23-6 32.5 0 8.6 4.3 11.8 11.2 11.8 5.8 0 11.5-5.5 16.2-9.2 2-1.7 3.4-2.9 5.1-2.9 2.3 0 3.8 1.7 3.8 3.5a10 10 0 0 1-2.3 5.7c-7.5 9.8-26.5 26.2-44.4 26.2-20.7 0-29.6-12.3-29.6-27.6 0-18.4 8.9-32.8 8.9-47.2 0-3.8-7.8-1.5-7.8-6.7 0-2.8 1.7-8.3 5-8.3 15.2 0 29.3-15 36.8-27 2.9-4.7 5.2-6.4 7.8-6.4 3.1 0 4.6 2.3 4.6 4.6 0 6.3-4 18.1-4 23 0 3.8 1 5.8 9.7 5.8 2.3 0 4 .8 4 3.2 0 5.7-3.1 9.7-6.6 9.7zM356 120.8c0 2.6 2.2 4.7 4.9 4.7 3.3 0 6.4-3.8 6.4-7.3 0-2.6-1.7-4.6-4.8-4.6-3.4 0-6.5 3.7-6.5 7.2zm-48.6-96.5c0-11.5 10.4-23.6 21.3-23.6C339.1.7 345 7.3 345 16c0 11.5-10.4 23.9-21.4 23.9-8.9 0-16-7-16-15.6zm-107.3 80.4c0-5-1.7-9.2-5.7-11-9-3.4-11.6-6.6-11.6-11.8 0-7.2 4.4-9.5 4.4-11.2 0-1.4-1-2.3-2.6-2.3-1.2 0-4 .9-8.1 4a40.6 40.6 0 0 0-14.1 32.9c0 13 7.5 21.3 18.7 21.3 11.5 0 19-11.8 19-22z" />
</svg>
Notist
- url: https://youtube.com/playlist?list=PLT41C0Ggz5wa66-AU5xapbOuzkUKUPLzi
title: My appearances on YouTubeBlog
content: |
<svg viewBox="0 0 490 490" height="32"><path d="M480 180v130a100 100 0 0 1-100 100H110A100 100 0 0 1 10 310V180A100 100 0 0 1 110 80h270a100 100 0 0 1 100 100z" fill="#ea4640"/><path fill="#fff" d="m320 245-120 50V195z"/><g fill="#231f20"><path d="M380 70H110A110 110 0 0 0 0 180v130a110 110 0 0 0 110 110h270a110 110 0 0 0 110-110V180A110 110 0 0 0 380 70zm90 240c0 49.6-40.4 90-90 90H110c-49.6 0-90-40.4-90-90V180c0-49.6 40.4-90 90-90h270c49.6 0 90 40.4 90 90v130z"/><path d="m323.8 235.8-120-50A10 10 0 0 0 190 195v100a10 10 0 0 0 13.8 9.2l120-50a10 10 0 0 0 0-18.4zM210 280v-70l84 35-84 35z"/></g></svg>
YouTube
projects:
- url: https://github.com/AverageMarcus/kube-image-prefetch
name: kube-image-prefetch
description: Pre-pull all images, on all nodes, within a Kubernetes cluster
languages:
- color: "#00ADD8"
name: Go
- url: https://github.com/AverageMarcus/tweetsvg
name: tweetsvg
description: Generate an SVG for a given Tweet ID
languages:
- color: "#e34c26"
name: HTML
- color: "#00ADD8"
name: Go
- url: https://github.com/AverageMarcus/opengraph-image-gen
name: opengraph-image-gen
description: Dynamically generate OpenGraph social share images
languages:
- color: "#e34c26"
name: HTML
- color: "#00ADD8"
name: Go
- url: https://github.com/AverageMarcus/speedtest-exporter
name: speedtest-exporter
description: A prometheus exporter for Speedtest.net results
languages:
- color: "#00ADD8"
name: Go
- url: https://github.com/AverageMarcus/feed-fetcher
name: feed-fetcher
description: Returns the RSS feed associated with the given URL
languages:
- color: "#e34c26"
name: HTML
- color: "#00ADD8"
name: Go
events:
- date: "2022-09-27"
humanDate: "September 27, 2022"
url: https://www.meetup.com/DevOps-Notts/
eventName: DevOpsNotts
details:
- name: The Wonders and Woes of Webhooks
type: Meetup Talk
- date: "2022-09-29"
humanDate: "September 29 - 30, 2022"
url: https://devopsdays.org/events/2022-london/welcome/
eventName: DevOpsDays London 2022
details:
- name: What DragonBall can teach us about being engineers
type: Ignite Talk
- date: "2022-10-03"
humanDate: "October 3 - 4, 2022"
url: https://kubehuddle.com/2022/
eventName: KubeHuddle 2022
details:
- name: The Wonders and Woes of Webhooks
type: Presentation
- name: What DragonBall can teach us about being engineers
type: Lightning Talk

@ -0,0 +1,5 @@
module marcusnoble
go 1.17
require gopkg.in/yaml.v2 v2.4.0

@ -0,0 +1,4 @@
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=

@ -0,0 +1,87 @@
package main
import (
"embed"
"fmt"
"html/template"
"log"
"net/http"
"os"
"strings"
"gopkg.in/yaml.v2"
)
var (
//go:embed src data.yaml
res embed.FS
port string
)
func init() {
var ok bool
if port, ok = os.LookupEnv("PORT"); !ok {
port = "8080"
}
}
func main() {
dataBytes, err := res.ReadFile("data.yaml")
if err != nil {
panic(err)
}
var data map[string]interface{}
if err := yaml.Unmarshal(dataBytes, &data); err != nil {
panic(err)
}
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
page := "src" + r.URL.Path
if strings.HasSuffix(page, "/") {
page = page + "index.html"
}
if strings.HasSuffix(page, ".html") {
tpl, err := template.ParseFS(res, page)
if err != nil {
log.Printf("page %s (%s) not found...", r.RequestURI, page)
w.WriteHeader(http.StatusInternalServerError)
return
}
w.WriteHeader(http.StatusOK)
tpl.Funcs(template.FuncMap(map[string]interface{}{
"html": func(str string) template.HTML {
return template.HTML(str)
},
}))
if err := tpl.Execute(w, data); err != nil {
return
}
} else {
// Serve up the best file format for image
if strings.Contains(page, "headshot-transparent.png") {
if strings.Contains(r.Header.Get("Accept"), "image/avif") {
page = strings.Replace(page, ".png", ".avif", 1)
} else if strings.Contains(r.Header.Get("Accept"), "image/webp") {
page = strings.Replace(page, ".png", ".webp", 1)
}
}
body, err := res.ReadFile(page)
if err != nil {
log.Printf("file %s (%s) not found...", r.RequestURI, page)
w.WriteHeader(http.StatusInternalServerError)
return
}
w.Write(body)
return
}
})
// http.FileServer(http.FS(res))
fmt.Println("Server started at port " + port)
log.Fatal(http.ListenAndServe(":"+port, nil))
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

@ -0,0 +1,295 @@
<!DOCTYPE html>
<html lang="en-us">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>Marcus Noble</title>
<style>
@font-face {
font-family: 'Orkney';
src: url('/fonts/OrkneyRegular.ttf') format('truetype');
}
@font-face {
font-family: 'Orkney';
src: url('/fonts/OrkneyBold.ttf') format('truetype');
font-weight: bold;
}
@font-face {
font-family: 'Orkney';
src: url('/fonts/OrkneyLight.ttf') format('truetype');
font-weight: lighter;
}
</style>
<style>
* {
box-sizing: border-box;
}
html, body {
margin: 0;
padding: 0;
width: 100%;
height: 100vh;
}
body {
background: #11191f;
color: #ededed;
display: grid;
grid-template: 100vh / 40% 60%;
font-family: 'Orkney', system-ui, -apple-system, "Segoe UI", "Roboto", "Ubuntu",
"Cantarell", "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji",
"Segoe UI Symbol", "Noto Color Emoji";
font-size: 1.5em;
}
a {
color: #fd7e0b;
}
header {
height: 100vh;
background-image: url('headshot-transparent.png');
background-repeat: no-repeat;
background-position: bottom right;
background-size: cover;
}
@media only screen and (min-width: 3700px) {
header {
background-position: top right;
background-size: contain;
}
}
main {
padding: 8em;
overflow-y: auto;
}
main h1 {
font-size: 2.5em;
}
main p {
line-height: 1.4em;
}
/* Social links */
.social-links {
list-style: none;
margin: 0;
padding: 0;
display: flex;
flex-direction: row;
flex-wrap: wrap;
}
.social-links li {
margin-right: .8em;
margin-bottom: .6em;
}
.social-links li a {
display: flex;
flex-direction: row;
align-items: flex-end;
text-decoration: none;
}
.social-links svg {
fill: #fff;
margin: 0 6px;
}
/* Projects */
.projects {
list-style: none;
margin: 0;
padding: 0;
display: flex;
flex-direction: row;
flex-wrap: wrap;
font-size: .8em;
}
.projects li {
width: 400px;
max-width: 100%;
border: 2px solid;
border-radius: 6px;
padding: 10px;
margin: 6px;
cursor: pointer;
}
.projects li a {
text-decoration: none;
color: unset;
}
.projects blockquote {
background: none;
margin: 4px 0;
padding-left: 4px;
border-left: 4px solid;
font-size: .8em;
}
.repo-language-color {
display: inline-block;
width: 12px;
height: 12px;
border-radius: 50%;
}
/* Events */
.events {
list-style: none;
margin: 0;
padding: 0;
display: flex;
flex-direction: column;
font-size: .8em;
}
.events li {
margin-bottom: 1em;
}
.events time {
font-size: .9em;
}
.events li .details {
display: flex;
flex-direction: column;
line-height: 1.4em;
padding-left: 10px;
margin-left: 2px;
border-left: 4px solid;
margin-top: .6em;
}
.events li .details > div {
margin-bottom: 6px;
}
.events .tag {
font-size: 0.7em;
background: #ededed;
color: #11191f;
padding: 4px 7px;
border-radius: 10em;
display: inline-block;
font-weight: lighter;
line-height: 1.2em;
}
@media only screen and (max-width: 1700px) {
body {
grid-template: 20vh 80vh / 100%;
}
header {
height: 100%;
background-position: bottom center;
background-size: contain
}
main {
padding: .5em 4em;
overflow-y: unset;
}
}
@media only screen and (max-width: 1050px) {
.projects li {
width: 100%;
}
}
</style>
</head>
<body>
<header></header>
<main>
<section id="intro">
<h1>Hi 👋, I'm Marcus</h1>
<p>
{{ .intro | html }}
</p>
</section>
<section id="links">
<h2>Find me around the web 🌐</h2>
<ul class="social-links">
{{ range .social }}
<li>
<a href="{{ .url }}" rel="me" title="{{ .title }}">
{{ .content | html }}
</a>
</li>
{{ end }}
</ul>
</section>
<section id="projects">
<h2>My Open Source Projects 💻</h2>
<p>
All my Open Source projects can be find on my <a href="https://github.com/AverageMarcus">GitHub</a> profile <small>(as well as my personal <a href="https://git.cluster.fun">Gitea</a> instance, <a href="https://gitlab.com/AverageMarcus">GitLab</a>, <a href="https://codeberg.org/AverageMarcus">Codeberg</a> and <a href="https://bitbucket.org/AverageMarcus/workspace/projects/PROJ">BitBucket</a>)</small>. Below are a selection of highlights.
</p>
<ul class="projects">
{{ range .projects }}
<li>
<a href="{{ .url }}">
<strong>{{ .name }}</strong>
<blockquote>{{ .description }}</blockquote>
<div>
{{ range .languages }}
<span class="repo-language-color" style="background-color: {{ .color }}"></span> {{ .name }}
{{ end }}
</div>
</a>
</li>
{{ end }}
</ul>
</section>
<section id="events">
<h2>Upcoming Events 🗓</h2>
<ul class="events">
{{ range .events }}
<li>
<time datetime="{{ .date }}">{{ .humanDate }}</time>
<div class="details">
<strong><a href="{{ .url }}">{{ .eventName }}</a></strong>
{{ range .details }}
<div>
<span>{{ .name }}</span>
<span class="tag">{{ .type }}</span>
</div>
{{ end }}
</div>
</li>
{{ end }}
</ul>
</section>
</main>
</body>
</html>
Loading…
Cancel
Save