aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--TODO.md15
-rw-r--r--data/blog/FirstPost.html24
-rw-r--r--data/projects/CCSEntryPortfolio.html21
-rw-r--r--data/projects/CCSSophomoreInterior.html14
-rw-r--r--data/static/favicon.icobin0 -> 2238 bytes
-rw-r--r--data/static/media/DTR-232-D-Final_Board-Scerba.jpgbin0 -> 3604922 bytes
-rw-r--r--data/static/media/MKE_Skyline_Art_Museum.jpgbin0 -> 1661741 bytes
-rw-r--r--data/static/media/Sketch Portfolio early 2021/Arai_Helmet_720p.jpgbin0 -> 62151 bytes
-rw-r--r--data/static/media/Sketch Portfolio early 2021/Bernie_720p.jpgbin0 -> 45277 bytes
-rw-r--r--data/static/media/Sketch Portfolio early 2021/Dorm_Setup_720p.jpgbin0 -> 68019 bytes
-rw-r--r--data/static/media/Sketch Portfolio early 2021/Flamingo_720p.jpgbin0 -> 33120 bytes
-rw-r--r--data/static/media/Sketch Portfolio early 2021/Harley_Sportbike_Concept_720p.jpgbin0 -> 75277 bytes
-rw-r--r--data/static/media/Sketch Portfolio early 2021/Peacock_Portrait2_Zoom_720p.jpgbin0 -> 50559 bytes
-rw-r--r--data/static/media/Sketch Portfolio early 2021/Peacock_Portrait_720p.jpgbin0 -> 29568 bytes
-rw-r--r--data/static/media/Sketch Portfolio early 2021/SL350_Bobber_720p.jpgbin0 -> 43971 bytes
-rw-r--r--data/static/oldStyle.css348
-rw-r--r--data/static/script.js49
-rw-r--r--data/static/sitemap.xml42
-rw-r--r--data/static/style.css91
-rw-r--r--go.mod3
-rwxr-xr-xsitebin0 -> 9126585 bytes
-rw-r--r--site.go268
-rw-r--r--templates/about.html12
-rw-r--r--templates/blog.html15
-rw-r--r--templates/index.html19
-rw-r--r--templates/master.html38
-rw-r--r--templates/postHelp.tmpl6
-rw-r--r--templates/projects.html15
28 files changed, 980 insertions, 0 deletions
diff --git a/TODO.md b/TODO.md
new file mode 100644
index 0000000..819f64c
--- /dev/null
+++ b/TODO.md
@@ -0,0 +1,15 @@
+# TODO File
+
+## site.go
+* Re-implement filesystem.Walk() to sort tree by 'date created'
+* Chop trailing '/' from URL path
+* Simplify loadPosts() / loadPost() functions (lots of shared code)
+
+## about.html
+* Write an 'about'
+
+## Overall
+* Change misleading and false *.html extension to something custom
+* Add tag system
+* Move over some old site content
+* Add year and month header for appropriate sections in the blog \ No newline at end of file
diff --git a/data/blog/FirstPost.html b/data/blog/FirstPost.html
new file mode 100644
index 0000000..75496b2
--- /dev/null
+++ b/data/blog/FirstPost.html
@@ -0,0 +1,24 @@
+ <title>First Post</title>
+ <meta name="description" content="Blog entry">
+!@#
+ <section>
+ <p>- <a href="/blog/FirstPost">First Post</a></p>
+ </section>
+!@#
+ <h1>First Post</h1>
+ <section>
+ <p>This is my first post on the new site! I am very excited to have the new system set up and mostly functional. There is still plenty of work to be done, but this is a great start.</p>
+ <p>I have moved to Golang for all server side scripting web serving, and it's been a fun language to learn so far. I have had a lot of encouragement from my friend over at <a href="https://www.angel-castaneda.com" target="_blank" rel="noopener noreferrer">www.angel-castaneda.com</a> so go check out his page to see what he is working on.</p>
+ <p>
+ The new site structure should be as follows:
+ <ul>
+ <li>/ - Home page with featured projects and short about section.</li>
+ <li>/projects - Page with all posted industrial and automotive design projects.</li>
+ <ul><li>/projects/name - Project with title "name".</li></ul>
+ <li>/blog - Page with all blog posts &lpar;content that does not fit under "/projects".&rpar;</li>
+ <ul><li>/blog/name - Blog entry with title "name".</li></ul>
+ <li>/about - About me and this website</li>
+ </ul>
+ </p>
+ <p>I am very excited to start posting again! This site refresh has been long overdue. Feel free to send any errors, typos, or strange behavior to my listed email; there are bound to be some problems at first.</p>
+ </section>
diff --git a/data/projects/CCSEntryPortfolio.html b/data/projects/CCSEntryPortfolio.html
new file mode 100644
index 0000000..f3a98f1
--- /dev/null
+++ b/data/projects/CCSEntryPortfolio.html
@@ -0,0 +1,21 @@
+ <title>CCS Entry Portfolio</title>
+ <meta name="description" content="Project post">
+!@#
+ <section>
+ <figure>
+ <img src="/static/media/Sketch Portfolio early 2021/SL350_Bobber_720p.jpg" alt="Side view Honda SL350 bobber sketch.">
+ <figcaption><a href="/projects/CCSEntryPortfolio">My 2021 CCS Entry Portfolio</a></figcaption>
+ </figure>
+ </section>
+!@#
+ <h1>CCS Entry Portfolio early 2021</h1>
+ <section class="imgGrid">
+ <img src="/static/media/Sketch Portfolio early 2021/Arai_Helmet_720p.jpg" alt="Arai helmet sketch.">
+ <img src="/static/media/Sketch Portfolio early 2021/Bernie_720p.jpg" alt="Cat, Bernie, sketch.">
+ <img src="/static/media/Sketch Portfolio early 2021/Peacock_Portrait2_Zoom_720p.jpg" alt="Zoomed peacock sketch with feathers out.">
+ <img src="/static/media/Sketch Portfolio early 2021/Flamingo_720p.jpg" alt="Flamingo standing on one leg sketch.">
+ <img src="/static/media/Sketch Portfolio early 2021/Harley_Sportbike_Concept_720p.jpg" alt="Harley Davidson concept sportbike sketch.">
+ <img src="/static/media/Sketch Portfolio early 2021/SL350_Bobber_720p.jpg" alt="Side view Honda SL350 bobber sketch.">
+ <img src="/static/media/Sketch Portfolio early 2021/Peacock_Portrait_720p.jpg" alt="Peakcock sketch with feathers tucked.">
+ <img src="/static/media/Sketch Portfolio early 2021/Dorm_Setup_720p.jpg" alt="Sketch of my dorm setup at the Milwaukee School of Engineering.">
+ </section> \ No newline at end of file
diff --git a/data/projects/CCSSophomoreInterior.html b/data/projects/CCSSophomoreInterior.html
new file mode 100644
index 0000000..b2807d6
--- /dev/null
+++ b/data/projects/CCSSophomoreInterior.html
@@ -0,0 +1,14 @@
+ <title>CCS Sophomore Interior</title>
+ <meta name="description" content="Project post">
+!@#
+ <section>
+ <figure>
+ <img src="/static/media/DTR-232-D-Final_Board-Scerba.jpg" alt="Sophomore interior studio project HONDA S-30.">
+ <figcaption><a href="/projects/CCSSophomoreInterior">HONDA S-30 - Sophomore Interior</a></figcaption>
+ </figure>
+ </section>
+!@#
+ <h1>CCS Entry Portfolio early 2021</h1>
+ <section class="imgGrid">
+ <img src="/static/media/DTR-232-D-Final_Board-Scerba.jpg" alt="Sophomore interior studio project HONDA S-30.">
+ </section> \ No newline at end of file
diff --git a/data/static/favicon.ico b/data/static/favicon.ico
new file mode 100644
index 0000000..08ad847
--- /dev/null
+++ b/data/static/favicon.ico
Binary files differ
diff --git a/data/static/media/DTR-232-D-Final_Board-Scerba.jpg b/data/static/media/DTR-232-D-Final_Board-Scerba.jpg
new file mode 100644
index 0000000..e8fe089
--- /dev/null
+++ b/data/static/media/DTR-232-D-Final_Board-Scerba.jpg
Binary files differ
diff --git a/data/static/media/MKE_Skyline_Art_Museum.jpg b/data/static/media/MKE_Skyline_Art_Museum.jpg
new file mode 100644
index 0000000..35ec29a
--- /dev/null
+++ b/data/static/media/MKE_Skyline_Art_Museum.jpg
Binary files differ
diff --git a/data/static/media/Sketch Portfolio early 2021/Arai_Helmet_720p.jpg b/data/static/media/Sketch Portfolio early 2021/Arai_Helmet_720p.jpg
new file mode 100644
index 0000000..44aed51
--- /dev/null
+++ b/data/static/media/Sketch Portfolio early 2021/Arai_Helmet_720p.jpg
Binary files differ
diff --git a/data/static/media/Sketch Portfolio early 2021/Bernie_720p.jpg b/data/static/media/Sketch Portfolio early 2021/Bernie_720p.jpg
new file mode 100644
index 0000000..d378ddc
--- /dev/null
+++ b/data/static/media/Sketch Portfolio early 2021/Bernie_720p.jpg
Binary files differ
diff --git a/data/static/media/Sketch Portfolio early 2021/Dorm_Setup_720p.jpg b/data/static/media/Sketch Portfolio early 2021/Dorm_Setup_720p.jpg
new file mode 100644
index 0000000..699088c
--- /dev/null
+++ b/data/static/media/Sketch Portfolio early 2021/Dorm_Setup_720p.jpg
Binary files differ
diff --git a/data/static/media/Sketch Portfolio early 2021/Flamingo_720p.jpg b/data/static/media/Sketch Portfolio early 2021/Flamingo_720p.jpg
new file mode 100644
index 0000000..b1ece50
--- /dev/null
+++ b/data/static/media/Sketch Portfolio early 2021/Flamingo_720p.jpg
Binary files differ
diff --git a/data/static/media/Sketch Portfolio early 2021/Harley_Sportbike_Concept_720p.jpg b/data/static/media/Sketch Portfolio early 2021/Harley_Sportbike_Concept_720p.jpg
new file mode 100644
index 0000000..89fcb4d
--- /dev/null
+++ b/data/static/media/Sketch Portfolio early 2021/Harley_Sportbike_Concept_720p.jpg
Binary files differ
diff --git a/data/static/media/Sketch Portfolio early 2021/Peacock_Portrait2_Zoom_720p.jpg b/data/static/media/Sketch Portfolio early 2021/Peacock_Portrait2_Zoom_720p.jpg
new file mode 100644
index 0000000..f61d05f
--- /dev/null
+++ b/data/static/media/Sketch Portfolio early 2021/Peacock_Portrait2_Zoom_720p.jpg
Binary files differ
diff --git a/data/static/media/Sketch Portfolio early 2021/Peacock_Portrait_720p.jpg b/data/static/media/Sketch Portfolio early 2021/Peacock_Portrait_720p.jpg
new file mode 100644
index 0000000..2886e96
--- /dev/null
+++ b/data/static/media/Sketch Portfolio early 2021/Peacock_Portrait_720p.jpg
Binary files differ
diff --git a/data/static/media/Sketch Portfolio early 2021/SL350_Bobber_720p.jpg b/data/static/media/Sketch Portfolio early 2021/SL350_Bobber_720p.jpg
new file mode 100644
index 0000000..6e87840
--- /dev/null
+++ b/data/static/media/Sketch Portfolio early 2021/SL350_Bobber_720p.jpg
Binary files differ
diff --git a/data/static/oldStyle.css b/data/static/oldStyle.css
new file mode 100644
index 0000000..73a4838
--- /dev/null
+++ b/data/static/oldStyle.css
@@ -0,0 +1,348 @@
+/*@import url('https://fonts.googleapis.com/css?family=Roboto');*/
+
+
+/* Standard elements */
+* {
+ box-sizing: border-box;
+}
+
+html {
+ scroll-behavior: smooth;
+}
+
+/* Header */
+
+header {
+ padding: 30px;
+ text-align: center;
+ background: rgba(0,0,0,0.1);
+}
+
+.header.sticky {
+ padding-bottom: 99px;
+}
+
+#name {
+ font-weight: bold;
+ font-size: 250%;
+}
+
+/* Navigation */
+
+.nav.sticky {
+ display: inline-block;
+ position: fixed;
+ min-width: 100%;
+ top: 0;
+ left: 0;
+}
+
+.action {
+ margin: 0;
+ padding: 0;
+ background-color: #333;
+}
+
+.action ul {
+ display: flex;
+ justify-content: space-around;
+ list-style: none;
+ margin: 0;
+ padding: 0;
+}
+
+.action ul li a {
+ margin: 0;
+ padding: 20px;
+ color: white;
+ text-decoration: none;
+ display: inline-block;
+}
+
+.action ul li {
+ margin: 5px;
+ border-radius: 15px;
+}
+
+.action ul li:hover {
+ background-color: #ddd;
+}
+
+.action ul li a:hover {
+ color: #333;
+}
+
+.action span {
+ display: none;
+}
+
+#side-navigation {
+ padding: 20px;
+ flex: 25%;
+}
+
+#side-nav-scroll-box {
+ margin: 10px 0;
+ padding: 5px;
+ border: 2px #333 solid;
+ border-radius: 6px;
+ background-color: rgba(0,0,0,0.1);
+}
+
+::-webkit-scrollbar-track {
+ background: rgba(0,0,0,0.1);
+}
+
+#outline-navigation {
+ max-height: 50vh;
+ overflow: auto;
+ margin: 0;
+ padding: 0 0 0 25px;
+}
+
+#outline-navigation li {
+ margin: 10px;
+}
+
+/* Main content containers */
+
+#root-article {
+ flex: 75%;
+}
+
+#main-wo-aside {
+ padding: 20px 20%;
+}
+
+#main-w-aside {
+ display: flex;
+ flex-wrap: wrap;
+ padding: 20px 0;
+ padding-right: 20%;
+}
+
+/* Body and standard tags */
+
+body {
+ /*font-family: 'Roboto', sans-serif;
+ font-size: 100%;*/
+ font-family: Arial, Helvetica, sans-serif;
+ margin: 0px;
+}
+
+main h1 {
+ text-align: center;
+}
+
+/* main h1, h2, h3, h4, h5, h6 {
+ font-family: 'Arial';
+} */
+
+main p {
+ text-align: justify;
+}
+
+main p a {
+ text-decoration: underline;
+}
+
+main a {
+ color: black;
+ text-decoration: none;
+}
+
+main ul {
+ padding-left: 20px;
+}
+
+main img {
+ border-radius: 6px;
+ max-width: 100%;
+}
+
+main figure {
+ margin: auto;
+ /*margin: 10px;*/
+ border: 2px #333 solid;
+ border-radius: 6px;
+ padding: 20px 20px 5px 20px;
+ max-width: 50%;
+}
+
+blockquote {
+ font-style: italic;
+}
+
+/* Special classes */
+
+.head-bar {
+ border: 2px black solid;
+}
+
+.framed-article {
+ margin: 25px;
+ padding: 5px 25px;
+ border: 2px #333 solid;
+ border-radius: 6px;
+ max-width: 100%;
+}
+
+.framed-article-half {
+ flex: 50%;
+ padding: 5px 25px;
+ border: 2px #333 solid;
+ border-radius: 6px;
+ max-width: 100%;
+}
+
+.tile {
+ display: flex;
+ flex-wrap: wrap;
+ padding: 25px;
+}
+
+.tile article {
+ flex: 40%;
+ max-width: auto;
+ padding: 0px 15px 0px 15px;
+ border: 2px gray solid;
+ border-radius: 6px;
+ margin: 5px;
+}
+
+.tile figure {
+ flex: 40%;
+ max-width: auto;
+ padding: 15px;
+ border: 2px gray solid;
+ border-radius: 6px;
+ margin: 5px;
+}
+
+/* Footer */
+
+footer {
+ margin: 0;
+ padding: 5px;
+ text-align: center;
+ color: white;
+ background-color: #333;
+}
+
+footer a {
+ color: rgb(189, 212, 255);
+ padding: 0;
+}
+
+/* Figure resize at 1500px */
+
+@media screen and
+(max-width: 1500px) {
+ figure {
+ max-width: 60%;
+ }
+ .tile figure {
+ max-width: auto;
+ }
+}
+
+/* Flex side nav to top of screen and resize figure */
+
+@media screen and
+(max-width: 1200px) {
+ header, #main-w-aside{
+ flex-direction: column;
+ }
+ #main-w-aside, #main-wo-aside {
+ padding-left: 10%;
+ padding-right: 10%;
+ }
+ figure {
+ max-width: 70%;
+ }
+ .tile figure {
+ max-width: auto;
+ }
+}
+
+/* Mobile View */
+
+@media only screen
+and (max-width: 510px) {
+ main figure {
+ max-width: 100%;
+ }
+ .tile {
+ flex-direction: column;
+ }
+ .tile article {
+ max-width: 100%;
+ }
+ .tile figure {
+ max-width: 100%;
+ }
+ #side-navigation {
+ padding: 20px 10%;
+ }
+
+ main a {
+ text-decoration: none;
+ }
+
+ .action {
+ position: fixed;
+ bottom: 25px;
+ left: 25px;
+ width: 50px;
+ height: 50px;
+ cursor: pointer;
+ background: #333;
+ border-radius: 50%;
+ box-shadow: 0 5px 5px rgba(0,0,0,0.1);
+ }
+ .action span {
+ position: relative;
+ width: 100%;
+ height: 100%;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ color: white;
+ font-size: 2em;
+ transition: 0.3s ease-in-out
+ }
+ .action.active span {
+ transform: rotate(135deg);
+ }
+ .action ul {
+ position: absolute;
+ bottom: 25px;
+ background: #333;
+ min-width: 150px;
+ padding: 0;
+ border-radius: 20px;
+ opacity: 0;
+ display: inline;
+ visibility: hidden;
+ transition: 0.3s;
+ }
+ .action.active ul {
+ bottom: 70px;
+ opacity: 1;
+ visibility: visible;
+ transition: 0.3s;
+ }
+ .action ul li {
+ list-style: none;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ border-radius: 15px;
+ padding: 0;
+ margin: 5px;
+ }
+
+ #outline-navigation {
+ max-height: 25vh;
+ }
+} \ No newline at end of file
diff --git a/data/static/script.js b/data/static/script.js
new file mode 100644
index 0000000..a7323f3
--- /dev/null
+++ b/data/static/script.js
@@ -0,0 +1,49 @@
+function stickyTopNav() {
+ var nav = document.querySelector('.nav');
+ var header = document.querySelector('.header');
+ if (document.body.scrollTop > 194 || document.documentElement.scrollTop > 194) {
+ if (document.querySelector('.sticky') == null) {
+ nav.classList.toggle('sticky');
+ header.classList.toggle('sticky');
+ }
+ } else {
+ if (document.querySelector('.sticky') != null) {
+ nav.classList.toggle('sticky');
+ header.classList.toggle('sticky');
+ }
+ }
+};
+
+window.onscroll = function() {
+ stickyTopNav();
+};
+
+window.onload = function() {
+ stickyTopNav();
+};
+
+function actionToggle() {
+ var action = document.querySelector('.action');
+ action.classList.toggle('active')
+}
+
+/*// https://stackoverflow.com/questions/17534661/make-anchor-link-go-some-pixels-above-where-its-linked-to
+
+// The function actually applying the offset
+function offsetAnchor() {
+ if (location.hash.length !== 0) {
+ window.scrollTo(window.scrollX, window.scrollY - 69);
+ }
+}
+
+// Captures click events of all <a> elements with href starting with #
+document.addEventListener('click', 'a[href^="#"]', function(event) {
+ // Click events are captured before hashchanges. Timeout
+ // causes offsetAnchor to be called after the page jump.
+ window.setTimeout(function() {
+ offsetAnchor();
+ }, 0);
+});
+
+// Set the offset when entering page with hash present in the url
+window.setTimeout(offsetAnchor, 0);*/ \ No newline at end of file
diff --git a/data/static/sitemap.xml b/data/static/sitemap.xml
new file mode 100644
index 0000000..1f568c3
--- /dev/null
+++ b/data/static/sitemap.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<urlset
+ xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9
+ http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd">
+<!-- created with Free Online Sitemap Generator www.xml-sitemaps.com -->
+
+
+<url>
+ <loc>https://alexscerba.com/</loc>
+ <lastmod>2023-06-15T04:44:23+00:00</lastmod>
+ <priority>1.00</priority>
+</url>
+<url>
+ <loc>https://alexscerba.com/projects/</loc>
+ <lastmod>2023-06-15T04:44:23+00:00</lastmod>
+ <priority>0.80</priority>
+</url>
+<url>
+ <loc>https://alexscerba.com/blog/</loc>
+ <lastmod>2023-06-15T04:44:23+00:00</lastmod>
+ <priority>0.80</priority>
+</url>
+<url>
+ <loc>https://alexscerba.com/about/</loc>
+ <lastmod>2023-06-15T04:44:23+00:00</lastmod>
+ <priority>0.80</priority>
+</url>
+<url>
+ <loc>https://alexscerba.com/projects/CCSEntryPortfolio</loc>
+ <lastmod>2023-06-15T04:44:23+00:00</lastmod>
+ <priority>0.80</priority>
+</url>
+<url>
+ <loc>https://alexscerba.com/blog/FirstPost</loc>
+ <lastmod>2023-06-15T04:44:23+00:00</lastmod>
+ <priority>0.64</priority>
+</url>
+
+
+</urlset> \ No newline at end of file
diff --git a/data/static/style.css b/data/static/style.css
new file mode 100644
index 0000000..28eda95
--- /dev/null
+++ b/data/static/style.css
@@ -0,0 +1,91 @@
+* {
+ box-sizing: border-box;
+}
+
+html {
+ scroll-behavior: smooth;
+}
+
+body {
+ font-family: Arial, Helvetica, sans-serif;
+ max-width: 500px;
+ margin: 0 auto;
+ padding: 0;
+}
+
+nav {
+ margin-top: 8px;
+ text-align: center;
+ border-radius: 6px;
+ background-color: rgb(228, 228, 228);
+}
+
+nav ul {
+ list-style: none;
+ margin: 0;
+ padding: 0;
+}
+
+nav li {
+ display: inline-block;
+ margin: 10px;
+}
+
+a {
+ font-weight: bold;
+ color: black;
+ text-decoration: none;
+ border-bottom: 1px dotted black;
+}
+
+h1 {
+ margin: 60px 0 0 0;
+}
+
+.subtitle {
+ margin: 8px 0 60px 12px;
+}
+
+figure {
+ margin: 20px 0;
+}
+
+img {
+ max-width: 100%;
+}
+
+.imgGrid {
+ margin: 20px auto;
+ line-height: 0;
+ column-count: 2;
+ column-gap: 0px;
+}
+
+.imgGrid img {
+ width: 100% !important;
+ height: auto !important;
+}
+
+footer {
+ text-align: center;
+ background-color: rgb(228, 228, 228);
+ border-radius: 6px;
+}
+
+footer p {
+ padding: 8px 0;
+}
+
+@media only screen
+and (max-width: 520px) {
+ body {
+ max-width: 400px;
+ }
+}
+
+@media only screen
+and (max-width: 410px) {
+ body {
+ max-width: 375px;
+ }
+} \ No newline at end of file
diff --git a/go.mod b/go.mod
new file mode 100644
index 0000000..1891586
--- /dev/null
+++ b/go.mod
@@ -0,0 +1,3 @@
+module alexscerba.com/website
+
+go 1.20
diff --git a/site b/site
new file mode 100755
index 0000000..c802f64
--- /dev/null
+++ b/site
Binary files differ
diff --git a/site.go b/site.go
new file mode 100644
index 0000000..ab1d850
--- /dev/null
+++ b/site.go
@@ -0,0 +1,268 @@
+package main
+
+import (
+ "bufio"
+ "fmt"
+ "log"
+ "net/http"
+ "os"
+ "path/filepath"
+ "regexp"
+ "strings"
+ "text/template"
+)
+
+type Post struct {
+ Meta []byte
+ Thumbnail []byte
+ Content []byte
+}
+
+type Posts struct {
+ Contents []*Post
+}
+
+func trimLeftChars(s string, n int) string {
+ m := 0
+ for i := range s {
+ if m >= n {
+ return s[i:]
+ }
+ m++
+ }
+ return s[:0]
+}
+
+func loadPost(path string) (p *Posts, err error) {
+
+ var section = 0
+ var tmp *Post = new(Post)
+
+ file, err := os.Open(path + ".html")
+ if err != nil {
+ file.Close()
+ var tmpPosts []*Post
+ tmpPosts = append(tmpPosts, tmp)
+ return &Posts{Contents: tmpPosts}, err
+ }
+
+ scanner := bufio.NewScanner(file)
+
+LineLoop:
+ for scanner.Scan() {
+ var line = scanner.Text()
+ var lineByte = []byte(line + "\n")
+
+ if line == "!@#" {
+ section++
+ goto LineLoop
+ }
+
+ switch section {
+ case 0:
+ tmp.Meta = append(tmp.Meta, lineByte...)
+ case 1:
+ tmp.Thumbnail = append(tmp.Thumbnail, lineByte...)
+ case 2:
+ tmp.Content = append(tmp.Content, lineByte...)
+ }
+ }
+
+ if err := scanner.Err(); err != nil {
+ log.Fatal(err)
+ }
+
+ file.Close()
+
+ if err != nil {
+ return nil, err
+ }
+
+ var tmpPosts []*Post
+ tmpPosts = append(tmpPosts, tmp)
+
+ return &Posts{Contents: tmpPosts}, nil
+}
+
+func loadPosts(location string, postCount int) (p *Posts, err error) {
+ if postCount == 0 || postCount < -1 {
+ return nil, os.ErrInvalid
+ }
+
+ var tmpPosts []*Post
+ var depthCount = 0
+
+ // TODO - Use less computationally heavy opperation for scalability
+ err = filepath.Walk(location, func(path string, _ os.FileInfo, _ error) error {
+ var directory, err = regexp.MatchString("^data/(projects|blog)$", path)
+ if err != nil {
+ return err
+ }
+
+ if directory {
+ depthCount++
+ } else if postCount == -1 || depthCount < postCount+1 {
+ file, err := os.Open(path)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ scanner := bufio.NewScanner(file)
+
+ var section = 0
+ var tmp *Post = new(Post)
+
+ LineLoop:
+ for scanner.Scan() {
+ var line = scanner.Text()
+ var lineByte = []byte(line + "\n")
+
+ if line == "!@#" {
+ section++
+ goto LineLoop
+ }
+
+ switch section {
+ case 0:
+ tmp.Meta = append(tmp.Meta, lineByte...)
+ case 1:
+ tmp.Thumbnail = append(tmp.Thumbnail, lineByte...)
+ case 2:
+ tmp.Content = append(tmp.Content, lineByte...)
+ }
+ }
+
+ if err := scanner.Err(); err != nil {
+ log.Fatal(err)
+ }
+
+ file.Close()
+
+ tmpPosts = append(tmpPosts, tmp)
+ depthCount++
+
+ } else {
+ depthCount++
+ }
+
+ return nil
+ })
+
+ if err != nil {
+ return nil, err
+ }
+
+ return &Posts{Contents: tmpPosts}, nil
+}
+
+func renderTemplate(w http.ResponseWriter, tmpl string, p *Posts) {
+ if tmpl == "post" {
+ t, err := template.ParseFiles("templates/master.html", "templates/postHelp.tmpl")
+ if err != nil {
+ http.Error(w, err.Error(), http.StatusInternalServerError)
+ return
+ }
+ err = t.Execute(w, p.Contents[0])
+ if err != nil {
+ http.Error(w, err.Error(), http.StatusInternalServerError)
+ }
+ } else {
+ t, err := template.ParseFiles("templates/master.html", "templates/"+tmpl+".html")
+ if err != nil {
+ http.Error(w, err.Error(), http.StatusInternalServerError)
+ return
+ }
+ err = t.Execute(w, p)
+ if err != nil {
+ http.Error(w, err.Error(), http.StatusInternalServerError)
+ }
+ }
+}
+
+func rootHandler(w http.ResponseWriter, r *http.Request) {
+ path := strings.Split(r.URL.Path, "/")
+ if path[1] != "" {
+ http.NotFound(w, r)
+ } else {
+ p, err := loadPosts("data/projects", 3)
+ if err != nil {
+ http.NotFound(w, r)
+ }
+
+ renderTemplate(w, "index", p)
+ }
+}
+
+func aboutHandler(w http.ResponseWriter, r *http.Request) {
+ renderTemplate(w, "about", nil)
+}
+
+func agHandler(w http.ResponseWriter, r *http.Request) {
+ p, err := loadPosts("data"+strings.TrimSuffix(r.URL.Path, "/"), -1)
+ if err != nil {
+ http.NotFound(w, r)
+ }
+
+ renderTemplate(w, trimLeftChars(strings.TrimSuffix(r.URL.Path, "/"), 1), p)
+}
+
+func postHandler(w http.ResponseWriter, r *http.Request) {
+ path := strings.Split(r.URL.Path, "/")
+ if path[2] == "" {
+ agHandler(w, r)
+ } else {
+ p, err := loadPost("data/" + path[1] + "/" + path[2])
+ if p == nil || err != nil {
+ http.NotFound(w, r)
+ } else {
+ renderTemplate(w, "post", p)
+ }
+ }
+}
+
+func fileHandler(w http.ResponseWriter, r *http.Request) {
+ body, _ := os.ReadFile("data/www/" + r.URL.Path)
+
+ w.Header().Set("Content-Type", "text/css; charset=utf-8")
+ fmt.Fprintf(w, "%s", body)
+}
+
+func makeHandler(fn func(http.ResponseWriter, *http.Request)) http.HandlerFunc {
+ return func(w http.ResponseWriter, r *http.Request) {
+ fn(w, r)
+ }
+}
+
+func httpsRedirect(w http.ResponseWriter, req *http.Request) {
+ // remove/add not default ports from req.Host
+ target := "https://" + req.Host + req.URL.Path
+ if len(req.URL.RawQuery) > 0 {
+ target += "?" + req.URL.RawQuery
+ }
+ log.Printf("redirect to: %s", target)
+ http.Redirect(w, req, target,
+ // see comments below and consider the codes 308, 302, or 301
+ http.StatusMovedPermanently)
+}
+
+func main() {
+ /* hostValid, _ := regexp.MatchString("^alexscerba.com$", r.URL.Path)
+ if !hostValid {
+ req, _ := http.NewRequest(r.Method, "alexscerba.com"+r.URL.Path, r.Body)
+ redirect(w, req)
+ } */
+
+ fs := http.FileServer(http.Dir("./data/static"))
+ http.Handle("/static/", http.StripPrefix("/static/", fs))
+
+ http.HandleFunc("/projects/", postHandler)
+ http.HandleFunc("/blog/", postHandler)
+ http.HandleFunc("/about/", aboutHandler)
+ http.HandleFunc("/", rootHandler)
+
+ go http.ListenAndServe(":80", http.HandlerFunc(httpsRedirect))
+ log.Fatal(http.ListenAndServe(":443", nil))
+
+ //http.Handle("/", http.FileServer(http.Dir("/data/www")))
+ //log.Fatal(http.ListenAndServe(":8080", nil))
+}
diff --git a/templates/about.html b/templates/about.html
new file mode 100644
index 0000000..265e626
--- /dev/null
+++ b/templates/about.html
@@ -0,0 +1,12 @@
+{{ define "meta" }}
+ <title>About</title>
+ <meta name="description" content="About me, Alex Scerba">
+{{ end }}
+{{ define "main" }}
+ <h1>About</h1>
+ <p class="subtitle">Me and my site.</p>
+ <hr>
+ <p>My name is Alex Scerba. For as long as I remember, I've been surrounded by people who tinkered and had a knack for repair and fixing. When the washing machine would go out, or the car started making a noise, we wouldn't call a repair man or go to the dealer. "It's just a machine, open it up and see what wrong" has been a part of my vocabulary for a long time and has been a major influence on how I lead my life.</p>
+ <p>In late elementary school, I was put into astronomy and tech camps at our local observatory. I attended them until highschool, at which point I started helping with the same camps and working on projects under another program they offered. The instructors were NASA engineers, astronomers, and science educators. This was my intro to the land of computers and engineering. Already surrounded by people that liked to fix stuff around the house, observing the kinds of things possible and being encouraged to build and program new things that would further our knowlegde of the universe lead me on my path to enrolling in the Milwaukee School of Engineering for a degree in computer science. It was at this time I built my website. It was out of jealousy actually... ; &rpar;. Another student posted his website in the "introduce yourself to the class" section. The site was fine enough. I sure didn't have one, but I had already written a webpage for a highschool presentation &lpar;That's another story&rpar; and felt I could do it bigger and better. With my vision in mind, I learned the basics of local web hosting and multipage development and eventually got a site deployed before the school year &lpar;I didn't end up posting it on the intro board&rpar;. My time at MSOE was pretty good, but it was less than a year after the start of Covid, so it was far from the standard college experience. I enjoyed my courses well enough and was learning a lot, but I started to feel that it wasn't for me. I took sketching and drawing back up as a hobby early in the year, and by the time the third trimester came around, I decided that I was done. I wasn't really sure what to do, though. I knew that I liked drawing but knew I needed to get better and I liked working on motorcycles and had hopes for a while of starting up a small business making aftermarket parts or doing builds &lpar;This was definitely a pipe dream at the time, but I needed something to go on&rpar;. Someone had to be behind the design of cars and motorcycles, so I did a search for schools that taught automotive design. Two schools showed up. CCS in Michigan and Art Center in California. CCS was cheaper, closer, and still looked like a great school, so I scrambled to put together a <a href="/projects/CCSEntryPortfolio">sketch portfolio</a> to apply with, and I was accepted for the upcoming year.</p>
+ <p>CCS was an eye opener and intimidating. No longer did I have a leg up in the curriculum. Most of my classmates had been drawing for a decent portion of their lives or had been thinking about automotive design and cars, so they had a lot of interesting ideas. I had no clue what I was doing, other than I knew I liked motorcycles, computers, and building stuff.</p>
+{{ end }} \ No newline at end of file
diff --git a/templates/blog.html b/templates/blog.html
new file mode 100644
index 0000000..d90c19e
--- /dev/null
+++ b/templates/blog.html
@@ -0,0 +1,15 @@
+{{ define "meta"}}
+ <title>Blog</title>
+ <meta name="description" content="Site blog featuring personal and project updates as well as anything random I want to share.">
+{{ end }}
+{{ define "main" }}
+ <h1>Blog</h1>
+ <p class="subtitle">Personal and site updates.</p>
+ <hr>
+
+{{ range .Contents }}
+{{ printf "%s" .Thumbnail }}
+{{ end }}
+
+ <a href="/blog">Top</a>
+{{ end }} \ No newline at end of file
diff --git a/templates/index.html b/templates/index.html
new file mode 100644
index 0000000..491bd55
--- /dev/null
+++ b/templates/index.html
@@ -0,0 +1,19 @@
+{{ define "meta" }}
+ <title>Alex Scerba</title>
+ <meta name="description" content="Homepage">
+{{ end }}
+{{ define "main" }}
+ <h1>Alex Scerba</h1>
+ <p class="subtitle">Designer. Maker.</p>
+ <hr>
+ <p>Student at College for Creative Studies in Detroit, MI. Love for tinkering, making, and building.</p>
+
+ <h2>Featured Projects</h2>
+ <hr>
+
+{{ range .Contents }}
+{{ printf "%s" .Thumbnail }}
+{{ end }}
+
+ <a href="/projects">See More Projects</a>
+{{ end }} \ No newline at end of file
diff --git a/templates/master.html b/templates/master.html
new file mode 100644
index 0000000..d0f3a8f
--- /dev/null
+++ b/templates/master.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<html lang="en-US">
+
+ <head>
+
+ <meta charset="utf-8" />
+ <meta name="author" content="Alexander Rees Scerba" />
+{{ template "meta" . }}
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
+ <link rel="stylesheet" href="/static/style.css" />
+ <link rel="shortcut icon" href="/static/favicon.ico" type="image/x-icon" />
+
+ </head>
+
+ <body>
+
+ <nav aria-labelledby="global-navigation" class="nav">
+ <ul>
+ <li><a href="/">Home</a></li>
+ <li><a href="/projects">Projects</a></li>
+ <li><a href="/blog">Blog</a></li>
+ <li><a href="/about">About</a></li>
+ </ul>
+ </nav>
+
+ <main>
+
+{{ template "main" . }}
+
+ </main>
+
+ <footer>
+ <p>Contact: <a href="mailto:a.scerba02@gmail.com">ascerba@collegeforcreativestudies.edu</a></p>
+ </footer>
+
+ </body>
+
+</html>
diff --git a/templates/postHelp.tmpl b/templates/postHelp.tmpl
new file mode 100644
index 0000000..ca2e319
--- /dev/null
+++ b/templates/postHelp.tmpl
@@ -0,0 +1,6 @@
+{{ define "meta" }}
+{{ printf "%s" .Meta }}
+{{ end }}
+{{ define "main" }}
+{{ printf "%s" .Content }}
+{{ end }}
diff --git a/templates/projects.html b/templates/projects.html
new file mode 100644
index 0000000..9c7f12d
--- /dev/null
+++ b/templates/projects.html
@@ -0,0 +1,15 @@
+{{ define "meta"}}
+ <title>Projects</title>
+ <meta name="description" content="Site blog featuring personal and project updates as well as anything random I want to share.">
+{{ end }}
+{{ define "main" }}
+ <h1>Projects</h1>
+ <p class="subtitle">Current posted industrial and automotive design projects.</p>
+ <hr>
+
+{{ range .Contents }}
+{{ printf "%s" .Thumbnail }}
+{{ end }}
+
+ <a href="/projects">Top</a>
+{{ end }} \ No newline at end of file