Merge pull request #2 from Clortox/simple-overhaul

Claude cleaning
This commit is contained in:
Tyler Perkins
2026-01-16 23:18:01 -05:00
committed by GitHub
30 changed files with 493 additions and 505 deletions

View File

@@ -5,3 +5,52 @@ This repo contains the [Hugo](https://gohugo.io) source for my personal website,
Find the active source of this repository on my [Gitea](https://git.clortox.com/Infrastructure/tylerperkins.xyz), where I make issues to track additions, and am more active to pull requests.
Find the mirror of this repository on [Github](https://github.com/Clortox/tylerperkins.xyz).
## Writing Posts
### Sidenotes / Margin Notes
This blog supports Tufte-style sidenotes that appear in the right margin on desktop and at the bottom of posts on mobile. To add a sidenote:
```markdown
This is some text{{< sidenote >}}This is a sidenote that appears in the margin{{< /sidenote >}} with more text following.
```
**Features:**
- On desktop (≥1200px): Notes appear as cards in the right margin, aligned with where they're referenced
- On mobile (<1200px): Notes appear in a "Notes" section at the end of the post
- Automatic numbering: `[0]`, `[1]`, `[2]`, etc.
- Bidirectional links: Click the number in text to jump to the note, click the number in the note to jump back
- Supports markdown and math: `$$x = \frac{-b \pm \sqrt{b^2 - 4ac}}{2a}$$`
### Summary Breaks
Control what appears on the homepage and list pages using the `<!--more-->` separator:
```markdown
---
title: "My Post Title"
date: 2026-01-16
---
This is the introduction paragraph that will appear on list pages as the summary.
<!--more-->
Everything after this line only appears on the full post page.
```
Without `<!--more-->`, Hugo will automatically create a summary from the first ~70 words.
### Clickable Headings
All headings automatically get anchor links. Hover over any heading to see a `#` symbol appear. Click it to get a direct link to that section.
### Markdown Source Downloads
Every post automatically generates a downloadable markdown source file. At the bottom of each post page, you'll find a "Download Markdown" link that provides the original markdown source, including all shortcodes and formatting.
**Technical Details:**
- Markdown files are generated as `index.md` alongside `index.html` in each post directory
- The raw content includes front matter, shortcodes, and all original formatting
- This is configured via Hugo's custom output formats in `config.yaml`

View File

@@ -1,21 +1,19 @@
baseURL: 'http://tylerperkins.xyx'
baseURL: 'http://tylerperkins.xyz'
languageCode: 'en-us'
LanguageCode: 'en-us'
title: 'Tylers Website'
theme: "clortox"
markup:
goldmark:
extensions:
passthrough:
delimiters:
block:
- - \[
- \]
- - $$
- $$
inline:
- - \(
- \)
enable: true
params:
math: true
title: "Tyler Perkins"
outputs:
page:
- HTML
- markdown
outputFormats:
markdown:
mediaType: "text/markdown"
isPlainText: true
isHTML: false
permalinkable: false
name: "markdown"
path: ""
baseName: "index"
rel: "alternate"

View File

@@ -3,7 +3,10 @@ title: "Home"
date: 2023-06-27
---
Software engineer, aspiring polymath. I like to do a little bit of everything.
# Hi, I'm Tyler
Interested in proving correctness, embedded systems, system design, genetic engineering, microscopy,
mechanical engineering, pure math (mostly algebra, category theory, number theory), operating systems design,
security, and more.
software engineer, aspiring postmath
Open to research work and projects ([email me](mailto:hello@clortox.com))

View File

@@ -1,32 +0,0 @@
{
"Contact": [
{
"name": "Email",
"url": "mailto:hello@clortox.com"
},
{
"name": "LinkedIn",
"url": "https://www.linkedin.com/in/tyler-perkins-xyz/"
},
{
"name": "Github",
"url": "https://github.com/Clortox"
}
],
"Services": [
{
"name": "Git",
"url": "https://git.clortox.com/"
},
{
"name": "Files",
"url": "https://files.clortox.com/"
},
{
"name": "Youtube Frontend",
"url": "https://watch.clortox.com/"
}
]
}

View File

@@ -1,27 +0,0 @@
{
"LeftHandSide": [
{
"name": "Home",
"url": "/"
},
{
"name": "Resume",
"url": "/resume.pdf"
},
{
"name": "Posts",
"url": "/posts/"
}
],
"RightHandSide": [
{
"name": "PGP Key",
"url": "/me.gpg"
},
{
"name": "User Portal",
"url": "https://auth.clortox.com/"
}
]
}

View File

@@ -1,65 +0,0 @@
{
"About": {
"Content": [
{
"value": "Software developer with a passion for learning everything."
},
{
"value": "Employed as a full stack developer at Etactics Inc, with a focus on back end development and system architecture."
},
{
"value": "Aspiring polymath; Jack of all trades, master of few."
},
{
"value": "Special interest in software design and architecture, pure math, and all forms of engineering."
},
{
"value": "Currently persuing a Masters in Computer Science at Georgia Tech."
}
],
"Interests": [
{
"value": "Software Architecture"
},
{
"value": "Embedded Systems"
},
{
"value": "Computer Engineering"
},
{
"value": "Mechanical Engineering"
},
{
"value": "Control Systems"
},
{
"value": "Fabrication (Welding, Woodworking, 3D Printing, Laser Cutting)"
},
{
"value": "Cars and Small Engines"
},
{
"value": "Ham Radio (CQCQCQ KE8TIZ QRK?)"
},
{
"value": "Chemistry"
},
{
"value": "Mathematics"
},
{
"value": "Firearms"
},
{
"value": "Botany"
},
{
"value": "Homesteading"
},
{
"value": "Philosophy"
}
]
}
}

View File

@@ -1,16 +0,0 @@
{{ define "main" }}
<div class="centered top-fade" style="height:100vh">
<div class="intro-content">
<h1 data-value="command not found" data-show="error-message" class="typewriter"></h1>
<div id="error-message">
<p data-value="Page not found, sorry about that"></p>
</div>
<div class="link-block">
<a href="javascript:history.back()">&lt;--&nbsp;Go back</a>
<p>&nbsp;|&nbsp;</p>
<a href="{{ .Site.BaseURL }}">Home&nbsp;--&gt;</a>
</div>
</div>
</div>
{{ end }}

View File

@@ -1,16 +0,0 @@
{{ define "main" }}
<div class="centered top-fade" style="height:100vh">
<div class="intro-content">
<h1 data-value="kernel panic!" data-show="error-message" class="typewriter"></h1>
<div id="error-message">
<p data-value="Error on our side, my bad"></p>
</div>
<div class="link-block">
<a href="javascript:history.back()">&lt;--&nbsp;Go back</a>
<p>&nbsp;|&nbsp;</p>
<a href="{{ .Site.BaseURL }}">Home&nbsp;--&gt;</a>
</div>
</div>
</div>
{{ end }}

View File

@@ -0,0 +1,5 @@
<h{{ .Level }} id="{{ .Anchor | safeURL }}">
<a href="#{{ .Anchor | safeURL }}" class="heading-anchor">
<span class="anchor-icon">#</span>{{ .Text | safeHTML }}
</a>
</h{{ .Level }}>

View File

@@ -1 +0,0 @@
<center><img src="{{ .Destination }}" title="{{ with .Title }}{{ . }} {{ else }}{{ .Text }}{{ end }}" alt="{{ .Text }}" /></center>

View File

@@ -1 +0,0 @@
<a href="{{ .Destination }}" title="{{ .Title }}" data-value="{{ .Text | safeHTML }}" class="scramble">{{ .Text | safeHTML }}</a>

View File

@@ -0,0 +1,272 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{{ if not .IsHome }}{{ .Title }} - {{ end }}{{ .Site.Title }}</title>
<link rel="alternate" type="application/rss+xml" title="{{ .Site.Title }}" href="/index.xml">
<style>
:root {
--bg-color: #fff;
--text-color: #333;
--link-color: #0066cc;
--border-color: #ccc;
--secondary-color: #666;
--code-bg: #f4f4f4;
--code-border: #ddd;
}
[data-theme="dark"] {
--bg-color: #1a1a1a;
--text-color: #e0e0e0;
--link-color: #6ba3ff;
--border-color: #444;
--secondary-color: #999;
--code-bg: #2d2d2d;
--code-border: #444;
--shadow: 0 1px 3px rgba(0,0,0,0.4);
}
:root {
--shadow: 0 1px 3px rgba(0,0,0,0.1);
}
html {
scroll-behavior: smooth;
}
body {
font-family: Georgia, serif;
line-height: 1.6;
max-width: 650px;
margin: 40px auto;
padding: 0 20px;
color: var(--text-color);
background: var(--bg-color);
transition: background 0.3s, color 0.3s;
}
a {
color: var(--link-color);
text-decoration: none;
}
a:hover {
text-decoration: underline;
}
h1, h2, h3 {
line-height: 1.2;
}
header {
border-bottom: 1px solid var(--border-color);
padding-bottom: 10px;
margin-bottom: 30px;
display: flex;
justify-content: space-between;
align-items: center;
}
header h1 {
margin: 0;
font-size: 24px;
}
.header-right {
display: flex;
gap: 15px;
align-items: center;
}
nav a {
font-size: 14px;
}
.theme-toggle {
background: none;
border: 1px solid var(--border-color);
color: var(--text-color);
cursor: pointer;
padding: 5px 10px;
border-radius: 3px;
font-size: 14px;
}
.theme-toggle:hover {
background: var(--code-bg);
}
footer {
margin-top: 50px;
padding-top: 10px;
border-top: 1px solid var(--border-color);
font-size: 14px;
color: var(--secondary-color);
}
.date {
color: var(--secondary-color);
font-size: 14px;
}
img {
max-width: 100%;
height: auto;
display: block;
}
pre {
background: var(--code-bg);
border: 1px solid var(--code-border);
padding: 10px;
overflow-x: auto;
}
code {
background: var(--code-bg);
padding: 2px 5px;
}
pre code {
background: none;
padding: 0;
}
/* Heading anchors */
.heading-anchor {
color: var(--text-color);
text-decoration: none;
}
.heading-anchor:hover {
text-decoration: none;
}
.anchor-icon {
opacity: 0;
margin-right: 5px;
color: var(--link-color);
transition: opacity 0.2s;
}
.heading-anchor:hover .anchor-icon {
opacity: 1;
}
/* Sidenotes/Margin notes */
/* Hide sidenotes by default (except on single post pages) */
.sidenote-container {
display: none;
}
.post-content .sidenote-container {
display: inline;
}
.sidenote-ref {
color: var(--link-color);
text-decoration: none;
font-size: 0.85em;
vertical-align: super;
line-height: 0;
}
/* Mobile: sidenotes at the end */
@media (max-width: 1199px) {
.post-content .sidenote-container {
display: inline;
}
.post-content .sidenote {
display: none;
}
#footnotes-section {
margin-top: 20px;
}
#footnotes-section .sidenote {
display: block;
position: static;
margin-bottom: 15px;
font-size: 0.85em;
line-height: 1.4;
padding: 10px;
background: var(--code-bg);
border-left: 2px solid var(--link-color);
border-radius: 3px;
box-shadow: var(--shadow);
}
}
/* Desktop: sidenotes in right margin */
@media (min-width: 1200px) {
/* Only expand body width when sidenotes actually exist */
body:has(.sidenote) {
max-width: 1000px;
overflow-x: hidden;
}
.post-content {
position: relative;
}
.post-content .content-wrapper {
max-width: 650px;
position: relative;
}
.post-content .sidenote-container {
position: static;
}
.post-content .sidenote {
position: absolute;
left: 690px;
width: 250px;
font-size: 0.85em;
line-height: 1.4;
padding: 10px;
margin-top: 0;
background: var(--code-bg);
border-left: 2px solid var(--link-color);
border-radius: 3px;
box-shadow: var(--shadow);
}
#footnotes-section {
display: none;
}
#sidenotes-column {
display: none;
}
}
</style>
<script>
// Theme toggle - runs immediately to prevent flash
(function() {
const theme = localStorage.getItem('theme') || 'light';
document.documentElement.setAttribute('data-theme', theme);
})();
</script>
<script src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"></script>
<script>
window.MathJax = {
tex: {
inlineMath: [['$', '$']],
displayMath: [['$$', '$$']],
processEscapes: true
}
};
</script>
</head>
<body>
<header>
<h1><a href="/">{{ .Site.Title }}</a></h1>
<div class="header-right">
<nav>
<a href="/resume.pdf">Resume</a>
</nav>
<button class="theme-toggle" onclick="toggleTheme()" aria-label="Toggle theme">
<span class="theme-icon"></span>
</button>
</div>
</header>
<main>
{{ block "main" . }}{{ end }}
</main>
<footer>
<p>&copy; {{ now.Year }} {{ .Site.Title }} | <a href="/index.xml">RSS</a> | <a href="/me.gpg">PGP Key</a> | <a href="/resume.pdf">Resume</a></p>
</footer>
<script>
function toggleTheme() {
const html = document.documentElement;
const currentTheme = html.getAttribute('data-theme');
const newTheme = currentTheme === 'dark' ? 'light' : 'dark';
html.setAttribute('data-theme', newTheme);
localStorage.setItem('theme', newTheme);
updateThemeIcon();
}
function updateThemeIcon() {
const theme = document.documentElement.getAttribute('data-theme');
const icon = document.querySelector('.theme-icon');
icon.textContent = theme === 'dark' ? '☀️' : '🌙';
}
updateThemeIcon();
</script>
</body>
</html>

View File

@@ -0,0 +1,12 @@
{{ define "main" }}
<h1>{{ .Title }}</h1>
{{ range .Pages }}
<article style="margin-bottom: 25px;">
<h3><a href="{{ .Permalink }}">{{ .Title }}</a></h3>
<p class="date">{{ .Date.Format "January 2, 2006" }}</p>
</article>
{{ end }}
<p><a href="/">&larr; Back to home</a></p>
{{ end }}

View File

@@ -13,11 +13,11 @@
{{- printf "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\"?>" | safeHTML }}
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>Tyler's Posts</title>
<title>{{ if eq .Title .Site.Title }}{{ .Site.Title }}{{ else }}{{ with .Title }}{{.}} on {{ end }}{{ .Site.Title }}{{ end }}</title>
<link>{{ .Permalink }}</link>
<description>Silly little posts I make for no one in particular</description>
<generator>Hugo -- gohugo.io</generator>
<language>en</language>{{ with .Site.Author.email }}
<description>Recent content {{ if ne .Title .Site.Title }}{{ with .Title }}in {{.}} {{ end }}{{ end }}on {{ .Site.Title }}</description>
<generator>Hugo -- gohugo.io</generator>{{ with .Site.LanguageCode }}
<language>{{.}}</language>{{end}}{{ with .Site.Author.email }}
<managingEditor>{{.}}{{ with $.Site.Author.name }} ({{.}}){{end}}</managingEditor>{{end}}{{ with .Site.Author.email }}
<webMaster>{{.}}{{ with $.Site.Author.name }} ({{.}}){{end}}</webMaster>{{end}}{{ with .Site.Copyright }}
<copyright>{{.}}</copyright>{{end}}{{ if not .Date.IsZero }}
@@ -32,7 +32,7 @@
<pubDate>{{ .Date.Format "Mon, 02 Jan 2006 15:04:05 -0700" | safeHTML }}</pubDate>
{{ with .Site.Author.email }}<author>{{.}}{{ with $.Site.Author.name }} ({{.}}){{end}}</author>{{end}}
<guid>{{ .Permalink }}</guid>
<description>{{ .Content | html -}}</description>
<description>{{ .Summary | html }}</description>
</item>
{{ end }}
</channel>

View File

@@ -0,0 +1,98 @@
{{ define "main" }}
<article class="post-content">
<div class="content-wrapper">
<h1>{{ .Title }}</h1>
<p class="date">{{ .Date.Format "January 2, 2006" }}</p>
{{ .Content }}
<div id="footnotes-section"></div>
</div>
</article>
<p>
<a href="/">&larr; Back to home</a>
{{ with .OutputFormats.Get "markdown" }}
| <a href="{{ .RelPermalink }}" download>Download Markdown</a>
{{ end }}
</p>
<script>
// On mobile, collect sidenotes and display at the end
let sidenotesOrganized = false;
function positionSidenotes() {
if (window.innerWidth < 1200) return;
const contentWrapper = document.querySelector('.content-wrapper');
if (!contentWrapper) return;
const sidenotes = Array.from(document.querySelectorAll('.sidenote'));
const containers = Array.from(document.querySelectorAll('.sidenote-container'));
// Position each sidenote relative to its reference point
containers.forEach((container, index) => {
const sidenote = container.querySelector('.sidenote');
if (!sidenote) return;
const containerRect = container.getBoundingClientRect();
const wrapperRect = contentWrapper.getBoundingClientRect();
// Calculate position relative to content-wrapper
const topPosition = containerRect.top - wrapperRect.top;
sidenote.style.top = topPosition + 'px';
});
// Now check for overlaps and adjust
for (let i = 0; i < sidenotes.length - 1; i++) {
const current = sidenotes[i];
const next = sidenotes[i + 1];
const currentRect = current.getBoundingClientRect();
const nextRect = next.getBoundingClientRect();
// If next sidenote overlaps with current, push it down
if (nextRect.top < currentRect.bottom + 10) {
const currentTop = parseFloat(current.style.top) || 0;
const currentHeight = currentRect.height;
next.style.top = (currentTop + currentHeight + 10) + 'px';
}
}
}
function organizeSidenotes() {
const sidenotes = document.querySelectorAll('.sidenote');
const footnotesSection = document.getElementById('footnotes-section');
if (!footnotesSection) return;
if (window.innerWidth < 1200) {
// Mobile: show at bottom
if (!sidenotesOrganized) {
footnotesSection.innerHTML = '<hr style="margin-top: 40px; border: none; border-top: 1px solid var(--border-color);"><h3>Notes</h3>';
sidenotes.forEach((sidenote) => {
const clone = sidenote.cloneNode(true);
clone.style.display = 'block';
clone.style.position = 'static';
clone.style.width = 'auto';
clone.style.marginBottom = '15px';
footnotesSection.appendChild(clone);
});
sidenotesOrganized = true;
}
} else {
// Desktop: clear footnotes section and position sidenotes
if (sidenotesOrganized) {
footnotesSection.innerHTML = '';
sidenotesOrganized = false;
}
setTimeout(positionSidenotes, 100);
}
}
organizeSidenotes();
window.addEventListener('resize', organizeSidenotes);
window.addEventListener('load', positionSidenotes);
</script>
{{ end }}

View File

@@ -0,0 +1,7 @@
---
title: "{{ .Title }}"
date: {{ .Date.Format "2006-01-02" }}
{{ if .Draft }}draft: true{{ end }}
---
{{ .RawContent }}

View File

@@ -1,32 +1,17 @@
{{ define "main" }}
<div class="centered top-fade">
<div class="intro-content">
<h1 data-value="Hi, I'm Tyler" data-show="intro-tagline" class="typewriter"></h1>
<div id="intro-tagline">
<p data-value="Software engineer, aspiring polymath"></p>
</div>
</div>
</div>
<div class="homepage-card">
<div>
<h4 data-show="about-description" data-value="uname -a" class="typewriter card-title">~ $&nbsp;</h1>
<br/>
<small>About me</small>
</div>
<div class="about-grid">
<div id="about-description" class="about-description">
{{ range .Site.Data.index.About.Content }}
<p data-value="{{ .value }}"></p>
{{ end }}
</div>
<div class="mini-terminal">
<p data-show="about-interests" data-value="cat interests.txt | less" class="typewriter">~ $&nbsp;</p>
<div id="about-interests" class="terminal-contents">
{{ range .Site.Data.index.About.Interests }}
<p class="terminal-text" data-value="{{ .value }}"></p>
{{ end }}
</div>
</div>
</div>
</div>
{{ .Content }}
<h2>Recent Posts</h2>
{{ range first 10 (where .Site.RegularPages "Type" "posts") }}
<article style="margin-bottom: 30px;">
<h3><a href="{{ .Permalink }}">{{ .Title }}</a></h3>
<p class="date">{{ .Date.Format "January 2, 2006" }}</p>
{{ if .Summary }}
<p>{{ .Summary }}</p>
{{ end }}
</article>
{{ end }}
<p><a href="/posts/">View all posts &rarr;</a></p>
{{ end }}

View File

@@ -1,21 +0,0 @@
<script id="MathJax-script" async src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-chtml.js"></script>
<script>
MathJax = {
tex: {
displayMath: [['\\[', '\\]'], ['$$', '$$']], // block
inlineMath: [['\\(', '\\)']] // inline
},
macros: {
vect: ["\\boldsymbol{#1}", 1]
},
chtml: {
scale: 1.2
}
};
</script>
<style>
.MathJax, .mjx-math {
color: white;
}
</style>

View File

@@ -0,0 +1,7 @@
{{- $id := .Ordinal -}}
<span class="sidenote-container">
<a href="#sn-{{ $id }}" id="snref-{{ $id }}" class="sidenote-ref">[{{ $id }}]</a>
<span id="sn-{{ $id }}" class="sidenote">
<a href="#snref-{{ $id }}" class="sidenote-ref">[{{ $id }}]</a> {{ .Inner | markdownify }}
</span>
</span>

View File

@@ -1,20 +0,0 @@
The MIT License (MIT)
Copyright (c) 2023 YOUR_NAME_HERE
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 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.

View File

@@ -1,2 +0,0 @@
+++
+++

View File

@@ -1,12 +0,0 @@
<!DOCTYPE html>
<html>
{{- partial "head.html" . -}}
<body>
{{- partial "header.html" . -}}
<div id="content">
<div class="parallax background" style="overflow-y: none;"></div>
{{- block "main" . }}{{- end }}
</div>
{{- partial "footer.html" . -}}
</body>
</html>

View File

@@ -1,26 +0,0 @@
{{ define "main" }}
<div class="page-header">
<h1 data-value="Posts" class="typewriter scramble"></h1>
<p>Ideas, projects, and other musings.</p>
</div>
{{ range.Pages }}
<article style="margin-left: 10vw; margin-right: 10vw;">
<a href="{{ .Permalink }}">
{{ if .Params.banner }}
<div class="post-list-body-container">
{{ else }}
<div class="post-list-body-container full-width">
{{ end }}
<h4 data-value="{{ .Title }}" id="{{ .Title | anchorize }}" class="post-list-title">{{ .Title }}</h4>
<small class="post-list-date">{{ .Date.Format "January 2, 2006" }}</small>
<p>{{ .Summary }}</p>
</div>
{{ if .Params.banner }}
<div class="post-list-image-container">
<img src="{{ .Params.banner }}" alt="{{ .Title }}" class="post-list-image" />
</div>
{{ end }}
</a>
</article>
{{ end }}
{{ end }}

View File

@@ -1,11 +0,0 @@
{{ define "main" }}
<div class="page-header">
<h1 data-value="{{ .Title }}" class="scramble">{{ .Title }}</h1>
<small class="post-list-date">{{ .Date.Format "January 2, 2006" }}</small>
</div>
<article>
<div class="post clearfix">
{{ .Content }}
</div>
</article>
{{ end }}

View File

@@ -1,25 +0,0 @@
<footer>
<div class="footer-sections">
<div class="footer-list" style="width: 85%">
<h4 id="contact" class="footer-header" style="margin-bottom: 5px">Contact</h4>
{{ range .Site.Data.footer.Contact }}
<a data-value="{{ .name }}" class="scramble" href="{{ .url }}">{{ .name }}</a>
{{ end }}
</div>
<div class="footer-list" style="width: 85%"></div>
<div class="footer-list" style="width: 85%">
<h4 class="footer-header" style="margin-bottom: 5px">Services</h4>
{{ range .Site.Data.footer.Services }}
<a data-value="{{ .name }}" class="scramble" href="{{ .url }}">{{ .name }}</a>
{{ end }}
</div>
</div>
<p style="margin: 0px;">
<small>
Copyleft <span style="display: inline-block; transform: rotate(180deg);">&copy;</span> {{ now.Year }}.
<a style="font-size: 0.8em;" href="https://github.com/Clortox/tylerperkins.xyz">Free open source software.</a>
</small>
</p>
</footer>

View File

@@ -1,37 +0,0 @@
<head>
<link rel="stylesheet" href="{{ "css/styles.css" | relURL }}">
<link rel="stylesheet" href="{{ "css/header.css" | relURL }}">
<link rel="stylesheet" href="{{ "css/footer.css" | relURL }}">
<link rel="stylesheet" href="{{ "css/background.css" | relURL }}">
<script src="{{ "js/script.js" | relURL }}"></script>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script async src="https://ackee.clortox.com/tracker.js" data-ackee-server="https://ackee.clortox.com" data-ackee-domain-id="8e41f517-df44-41cb-970d-208872712ed6"></script>
{{ range .AlternativeOutputFormats -}}
{{ printf `<link rel="%s" type="%s" href="%s" title="%s" />` .Rel .MediaType.Type .Permalink $.Site.Title | safeHTML }}
{{ end -}}
{{ if .Param "math" }}
{{ partialCached "math.html" . }}
{{ end }}
<
<meta name="description" content="Software Engineer, aspiring polymath"/>
<meta property="og:title" content="{{ if .Title }}{{ .Title }}{{ else }}Tylers Perkins - Software Engineer{{ end }}" />
<meta property="og:type" content="website" />
<meta property="og:url" content="{{ .Permalink }}" />
<meta property="og:image" content="https://opengraph.b-cdn.net/production/images/d8998659-0129-4808-b73c-67797d3fe7ac.jpg?token=X4ji3MDnTCq9oofsKJXYRPV4nIaynTNQmWu0UpE8vaE&height=460&width=460&expires=33281091161">
<meta property="og:description" content="Software Engineer, aspiring polymath" />
<meta property="og:site_name" content="Tylers Perkins" />
<meta property="og:locale" content="en_US" />
<meta property="twitter:card" content="summary_large_image" />
<meta property="twitter:title" content="{{ if .Title }}{{ .Title }}{{ else }}Tylers Perkins - Software Engineer{{ end }}" />
<meta property="twitter:description" content="Software Engineer, aspiring polymath" />
<meta name="twitter:image" content="https://opengraph.b-cdn.net/production/images/d8998659-0129-4808-b73c-67797d3fe7ac.jpg?token=X4ji3MDnTCq9oofsKJXYRPV4nIaynTNQmWu0UpE8vaE&height=460&width=460&expires=33281091161">
<meta property="twitter:image:alt" content="Tylers Perkins Profile Picture">
<meta property="twitter:url" content="{{ .Permalink }}" />
<title>Tylers Perkins - Software Engineer</title>
</head>

View File

@@ -1,10 +0,0 @@
<header class="navbar sticky">
{{ range .Site.Data.header.LeftHandSide }}
<a data-value="{{ .name }}" class="scramble header-item" href="{{ .url | relURL }}">{{ .name }}</a>
{{ end }}
<div class="navbar-right">
{{ range .Site.Data.header.RightHandSide }}
<a data-value="{{ .name }}" class="scramble header-item" href="{{ .url }}">{{ .name }}</a>
{{ end }}
</div>
</header>

View File

@@ -1,105 +0,0 @@
const letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
const typeWriterSpeed = 60;
window.onload = function() {
document.querySelectorAll(".scramble").forEach(item => {
item.addEventListener("mouseover", scramble);
});
window.addEventListener('scroll', function() {
let parallax = document.querySelector('.parallax')
let scrollPosition = window.pageYOffset;
let newSize = (document.querySelector('#content').offsetHeight * 0.8);
if(newSize < window.innerHeight)
newSize = window.innerHeight;
parallax.style.height = newSize + "px";
parallax.style.transform = 'translateY(' + scrollPosition * .5 + 'px)';
})
document.querySelectorAll(".typewriter").forEach(item => {
observer.observe(item);
});
}
function sleep(milliseconds) {
return new Promise(resolve => setTimeout(resolve, milliseconds));
}
function replaceSpacesWithNbsp(string) {
if (string == null) return;
return string.replace(/ /g, "\xa0");
}
function scramble(event){
scrambleLetters(event.target);
}
function scrambleLetters(element) {
let iterations = 0;
const originalValue = element.dataset.value;
let interval = setInterval(() => {
element.innerText = element.innerText.split("")
.map((letter, index) => {
if(index < iterations){
return originalValue[index];
}
return letters[Math.floor(Math.random() * letters.length)];
}).join("")
iterations += 1 / 3;
if(iterations > originalValue.length){
clearInterval(interval);
element.innerText = originalValue;
}
}, 30);
}
async function typeWriter(element) {
let typeWriterText = element.getAttribute("data-value");
let output = element.innerText;
// write the main text
for(let i = 0; i < typeWriterText.length; ++i){
output += typeWriterText.charAt(i);
// sleep for typeWriterSpeed milliseconds
await sleep(typeWriterSpeed);
element.innerText = output;
}
//try and do the paragraphs associated
let hiddenElementId = element.getAttribute("data-show");
if(hiddenElementId == null) return;
let hiddenElement = document.getElementById(hiddenElementId);
let hiddenElementSpeed = 5;
let paragraphs = hiddenElement.querySelectorAll("p");
for (let p of paragraphs){
let hiddenElementText = p.getAttribute("data-value");
//hiddenElementText = replaceSpacesWithNbsp(hiddenElementText);
p.innerHtml = "";
output = "";
for (let i = 0; i < hiddenElementText.length; ++i){
output += hiddenElementText.charAt(i);
await sleep(hiddenElementSpeed);
p.innerText = output;
}
await sleep(50);
}
}
let observer = new IntersectionObserver(function(entries) {
for (let entry of entries){
// If the element is visible, start the animation
if(entry.isIntersecting) {
typeWriter(entry.target);
observer.unobserve(entry.target);
}
}
}, { threshold: 0.7 });

View File

@@ -1,21 +0,0 @@
# theme.toml template for a Hugo theme
# See https://github.com/gohugoio/hugoThemes#themetoml for an example
name = "Clortox"
license = "MIT"
licenselink = "https://github.com/yourname/yourtheme/blob/master/LICENSE"
description = ""
homepage = "http://example.com/"
tags = []
features = []
min_version = "0.41.0"
[author]
name = ""
homepage = ""
# If porting an existing theme
[original]
name = ""
homepage = ""
repo = ""