diff --git a/.appengine/app.yaml b/.appengine/app.yaml
index 24039ac..9c6cdfb 100644
--- a/.appengine/app.yaml
+++ b/.appengine/app.yaml
@@ -38,6 +38,13 @@ handlers:
http_headers:
Content-Type: text/html; charset=utf-8
+ - url: /story/the_philosophy_of_lovers
+ static_files: .build/the_philosophy_of_lovers.html
+ upload: .build/the_philosophy_of_lovers.html
+ secure: always
+ http_headers:
+ Content-Type: text/html; charset=utf-8
+
- url: /story/bridge
static_files: .build/bridge.html
upload: .build/bridge.html
@@ -94,6 +101,13 @@ handlers:
http_headers:
Content-Type: text/html; charset=utf-8
+ - url: /kit
+ static_files: .build/kit.html
+ upload: .build/kit.html
+ secure: always
+ http_headers:
+ Content-Type: text/html; charset=utf-8
+
- url: /word/quality
static_files: .build/quality.html
upload: .build/quality.html
diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json
new file mode 100644
index 0000000..707482b
--- /dev/null
+++ b/.devcontainer/devcontainer.json
@@ -0,0 +1,51 @@
+{
+ "init": true,
+ "name": "justindfuller.com",
+ "features": {
+ "ghcr.io/devcontainers/features/go:1": {
+ "version": "1.21.4",
+ "golangciLintVersion": "1.55.2"
+ },
+ "ghcr.io/devcontainers/features/node:1": {
+ "version": "20.9.0"
+ }
+ },
+ "hostRequirements": {
+ "cpus": 1
+ },
+ "image": "mcr.microsoft.com/devcontainers/universal:2",
+ "waitFor": "onCreateCommand",
+ "updateContentCommand": "go mod download",
+ "postCreateCommand": "go install github.com/cespare/reflex@latest",
+ "postAttachCommand": {
+ "server": "make server-watch"
+ },
+ "customizations": {
+ "codespaces": {
+ "openFiles": [
+ "README"
+ ]
+ },
+ "vscode": {
+ "settings": {
+ "workbench.iconTheme": "fira-code-material-minimal",
+ "editor.fontFamily": "fira-code-nerd, FiraCode Nerd Font, Consolas, 'Courier New', monospace",
+ "editor.fontLigatures": true
+ },
+ "extensions": [
+ "golang.go",
+ "dbaeumer.vscode-eslint",
+ "ms-vscode.makefile-tools",
+ "DavidAnson.vscode-markdownlint",
+ "eamodio.gitlens",
+ "Entuent.fira-code-nerd-font"
+ ]
+ }
+ },
+ "portsAttributes": {
+ "9000": {
+ "label": "Application",
+ "onAutoForward": "openBrowserOnce"
+ }
+ }
+}
\ No newline at end of file
diff --git a/Makefile b/Makefile
index 727043c..779ca12 100644
--- a/Makefile
+++ b/Makefile
@@ -15,6 +15,9 @@ format:
@go fmt ./...;
@npm run test;
+format-watch:
+ @reflex -s -- sh -c "$(MAKE) format";
+
build:
@rm -rf ./.build;
@mkdir ./.build;
@@ -23,10 +26,12 @@ build:
@curl "http://localhost:9000/make" > ./.build/make.html;
@curl "http://localhost:9000/grass" > ./.build/grass.html;
@curl "http://localhost:9000/grass/worker.js" > ./.build/grass-service-worker.js;
+ @curl "http://localhost:9000/kit" > ./.build/kit.html;
@curl "http://localhost:9000/aphorism" > ./.build/aphorism.html;
@curl "http://localhost:9000/poem" > ./.build/poem.html;
@curl "http://localhost:9000/story" > ./.build/story.html;
@curl "http://localhost:9000/story/the_philosophy_of_trees" > ./.build/the_philosophy_of_trees.html;
+ @curl "http://localhost:9000/story/the_philosophy_of_lovers" > ./.build/the_philosophy_of_lovers.html;
@curl "http://localhost:9000/story/bridge" > ./.build/bridge.html;
@curl "http://localhost:9000/story/nothing" > ./.build/nothing.html;
@curl "http://localhost:9000/review" > ./.build/review.html;
@@ -37,3 +42,6 @@ build:
@curl "http://localhost:9000/word/equipoise" > ./.build/equipoise.html;
@curl "http://localhost:9000/word/flexible" > ./.build/flexible.html;
@cp -r ./image ./.build
+
+build-watch:
+ @reflex -s -- sh -c "$(MAKE) build";
\ No newline at end of file
diff --git a/README.md b/README.md
index b233074..08ed093 100644
--- a/README.md
+++ b/README.md
@@ -2,4 +2,4 @@
[![Build and Deploy to GAE](https://github.com/JustinDFuller/justindfuller.com/actions/workflows/deploy.yml/badge.svg?branch=main)](https://github.com/JustinDFuller/justindfuller.com/actions/workflows/deploy.yml)
-[https://www.justindfuller.com](https://www.justindfuller.com)
+[https://www.justindfuller.com](https://www.justindfuller.com)
\ No newline at end of file
diff --git a/aphorism/entries.txt b/aphorism/entries.txt
index 999667c..a3c6707 100644
--- a/aphorism/entries.txt
+++ b/aphorism/entries.txt
@@ -44,7 +44,7 @@ Truth is only an agreement.
There may be a single physical reality (or maybe not) but there is no reason to think a particular human can perfectly understand and interpret that reality.
-Truth can only be subjective and never objective. We cannot experience or interpret anything except as a subject observing and object.
+Truth can only be subjective and never objective. We cannot experience or interpret anything except as a subject observing an object.
It is wrong to approach philosophy in search of perfect truth. It is wrong to discount a philosophical argument for being imperfect. The value of philosophy may sometimes be to generate more ideas.
diff --git a/aphorism/main.css b/aphorism/main.css
index 4855f41..d64c525 100644
--- a/aphorism/main.css
+++ b/aphorism/main.css
@@ -47,3 +47,22 @@ hr {
margin-top: 30px;
margin-bottom: 50px;
}
+
+@media (prefers-color-scheme: dark) {
+ html,
+ body {
+ background-color: #020215;
+ color: white;
+ }
+
+ main > a {
+ color: white;
+ }
+
+ main > a:hover,
+ main > a:focus,
+ main > a:active {
+ background: white;
+ color: #020215;
+ }
+}
diff --git a/image/rabbit.jpg b/image/rabbit.jpg
new file mode 100644
index 0000000..58ef24e
Binary files /dev/null and b/image/rabbit.jpg differ
diff --git a/image/wizard.jpg b/image/wizard.jpg
new file mode 100644
index 0000000..5f53e5d
Binary files /dev/null and b/image/wizard.jpg differ
diff --git a/main.css b/main.css
index 68a8307..f83e9ad 100644
--- a/main.css
+++ b/main.css
@@ -36,7 +36,7 @@
}
main > a {
- color: black;
+ color: #020215;
padding: 10px 20px;
border-radius: 2px;
transition: background 500ms, color 500ms;
@@ -48,7 +48,26 @@
main > a:hover,
main > a:focus,
main > a:active {
- background: black;
+ background: #020215;
color: white;
}
+
+ @media (prefers-color-scheme: dark) {
+ html,
+ body {
+ background-color: #020215;
+ color: white;
+ }
+
+ main > a {
+ color: white;
+ }
+
+ main > a:hover,
+ main > a:focus,
+ main > a:active {
+ background: white;
+ color: #020215;
+ }
+ }
diff --git a/main.go b/main.go
index 73df68b..bf19406 100644
--- a/main.go
+++ b/main.go
@@ -228,6 +228,15 @@ func main() {
}
})
+ http.HandleFunc("/kit", func(w http.ResponseWriter, r *http.Request) {
+ if err := templates.ExecuteTemplate(w, "/make/kit.template.html", data{
+ Title: "A Game with Kit",
+ Meta: "kit",
+ }); err != nil {
+ log.Printf("template execution error=%s template=%s", err, "/make/kit.template.html")
+ }
+ })
+
http.HandleFunc("/story", func(w http.ResponseWriter, r *http.Request) {
if err := templates.ExecuteTemplate(w, "/story/main.template.html", data{
Title: "Story",
diff --git a/make/grass.css b/make/grass.css
index e3577bf..a327f3f 100644
--- a/make/grass.css
+++ b/make/grass.css
@@ -65,28 +65,28 @@ progress {
select {
width: 100%;
padding: 10px 20px;
- border: 2px solid black;
+ border: 2px solid #020215;
background: white;
- color: black;
+ color: #020215;
}
button {
padding: 10px 20px;
- border-top: 2px solid black;
- border-left: 2px solid black;
- border-right: 4px solid black;
- border-bottom: 4px solid black;
+ border-top: 2px solid #020215;
+ border-left: 2px solid #020215;
+ border-right: 4px solid #020215;
+ border-bottom: 4px solid #020215;
border-radius: 2px;
background: white;
- color: black;
+ color: #020215;
cursor: pointer;
}
button:hover {
- border-top: 3px solid black;
- border-left: 3px solid black;
- border-right: 3px solid black;
- border-bottom: 3px solid black;
+ border-top: 3px solid #020215;
+ border-left: 3px solid #020215;
+ border-right: 3px solid #020215;
+ border-bottom: 3px solid #020215;
}
select,
@@ -117,10 +117,10 @@ label {
cursor: pointer;
text-align: center;
width: 45%;
- border-top: 2px solid black;
- border-left: 2px solid black;
- border-right: 4px solid black;
- border-bottom: 4px solid black;
+ border-top: 2px solid #020215;
+ border-left: 2px solid #020215;
+ border-right: 4px solid #020215;
+ border-bottom: 4px solid #020215;
border-radius: 4px;
margin-bottom: 20px;
}
@@ -136,10 +136,10 @@ label {
}
.day:hover {
- border-right: 3px solid black;
- border-bottom: 3px solid black;
- border-left: 3px solid black;
- border-top: 3px solid black;
+ border-right: 3px solid #020215;
+ border-bottom: 3px solid #020215;
+ border-left: 3px solid #020215;
+ border-top: 3px solid #020215;
}
.day .icon {
@@ -173,3 +173,26 @@ label {
.day .temperature {
min-width: 70px;
}
+
+@media (prefers-color-scheme: dark) {
+ html,
+ body {
+ background-color: #020215;
+ color: white;
+ }
+
+ main > a {
+ color: white;
+ }
+
+ main > a:hover,
+ main > a:focus,
+ main > a:active {
+ background: white;
+ color: #020215;
+ }
+
+ .day {
+ color: #020215;
+ }
+}
diff --git a/make/kit.css b/make/kit.css
new file mode 100644
index 0000000..f0c8922
--- /dev/null
+++ b/make/kit.css
@@ -0,0 +1,145 @@
+* {
+ box-sizing: border-box;
+}
+
+html,
+body {
+ padding: 0;
+ margin: 0;
+ font-size: 18px;
+ min-height: 100vh;
+ max-height: 300px;
+ min-width: 600px;
+ font-size: 20px;
+ font-family: "Amiri", serif;
+}
+
+main {
+ padding-bottom: 20px;
+}
+
+#world,
+#root {
+ width: 600px;
+ margin: auto;
+}
+
+#root {
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ justify-content: center;
+ height: 100vh;
+ max-height: 200px;
+}
+
+.step {
+ padding: 30px;
+ border: 1px solid black;
+}
+
+.step:hover {
+ font-weight: bold;
+ color: lightblue;
+ border: 3px solid lightblue;
+}
+
+.step.selected {
+ font-weight: bold;
+ color: blue;
+ border: 3px solid blue;
+}
+
+.step.correct {
+ font-weight: bold;
+ color: green;
+ border: 2px solid green;
+}
+
+#world {
+ margin-top: 10px;
+ position: relative;
+ height: 100px;
+}
+
+#floor {
+ position: absolute;
+ top: 110px;
+ left: 0;
+ right: 0;
+ z-index: 1;
+ border-bottom: 3px solid brown;
+ width: 100%;
+ min-width: 600px;
+}
+
+@keyframes move {
+ 0% {
+ left: 0px;
+ }
+ 100% {
+ left: 433px;
+ }
+}
+
+@keyframes talk {
+ 0% {
+ visibility: hidden;
+ }
+ 100% {
+ visibility: visible;
+ }
+}
+
+#wizard {
+ position: absolute;
+ bottom: 0;
+ top: 0;
+ left: 30px;
+}
+
+#wizard p {
+ visibility: hidden;
+ position: relative;
+ left: 65px;
+ bottom: 131px;
+}
+
+#wizard.success p {
+ animation-delay: 2s;
+ animation-name: talk;
+ animation-fill-mode: forwards;
+}
+
+#wizard img {
+ transform: scaleX(-1);
+ height: 100px;
+}
+
+#wizard.success {
+ animation-duration: 2s;
+ animation-name: move;
+ animation-fill-mode: forwards;
+}
+
+#rabbit {
+ transform: scaleX(-1);
+ position: absolute;
+ height: 50px;
+ right: 50px;
+ bottom: 0;
+}
+
+blockquote {
+ width: 100vw;
+ max-width: 500px;
+ margin: auto;
+ border-left: 3px solid #020215;
+ padding: 20px;
+}
+
+@media (max-width: 500px) {
+ blockquote {
+ margin: 5px;
+ }
+}
diff --git a/make/kit.js b/make/kit.js
new file mode 100644
index 0000000..39ba8ec
--- /dev/null
+++ b/make/kit.js
@@ -0,0 +1,76 @@
+const numbers = [
+ { n: 1, selected: false },
+ { n: 6, selected: false },
+ { n: 8, selected: false },
+ { n: 7, selected: false },
+ { n: 2, selected: false },
+ { n: 3, selected: false },
+ { n: 5, selected: false },
+ { n: 4, selected: false },
+];
+const root = document.querySelector("#root");
+const wizard = document.querySelector("#wizard");
+
+function init() {
+ root.innerHTML = "";
+
+ let all = true;
+
+ for (const i in numbers) {
+ const n = numbers[i];
+
+ if (n.n - 1 !== Number(i)) {
+ all = false;
+ }
+ }
+
+ if (all) {
+ wizard.classList.add("success");
+ }
+
+ for (const i in numbers) {
+ const n = numbers[i];
+ const step = document.createElement("div");
+
+ step.id = n.n;
+ step.innerText = n.n;
+ step.classList.add("step");
+
+ if (n.n - 1 === Number(i)) {
+ step.classList.add("correct");
+ }
+
+ root.appendChild(step);
+ step.addEventListener("click", function(e) {
+ this.classList.toggle("selected");
+
+ if (n.selected) {
+ n.selected = false;
+
+ return;
+ }
+
+ n.selected = true;
+
+ for (const j in numbers) {
+ if (j === i) {
+ continue;
+ }
+
+ const n2 = numbers[j];
+
+ if (n2.selected) {
+ n.selected = false;
+ n2.selected = false;
+ numbers[j] = n;
+ numbers[i] = n2;
+ init();
+
+ break;
+ }
+ }
+ });
+ }
+}
+
+init();
diff --git a/make/kit.template.html b/make/kit.template.html
new file mode 100644
index 0000000..80bab44
--- /dev/null
+++ b/make/kit.template.html
@@ -0,0 +1,39 @@
+
+
+
+ {{ template "/meta.template.html" . }}
+
+
+
+
+
+
+
+
+
WooHoo!
+
+
+
+
+
+
+
+ Kit: Dad, Can we make a game?
+
+ Me: Sure, buddy. What kind of game?
+
+ Kit: On the computer! Let's make a game with a bunch of
+ numbers all mixed up. You have to switch the numbers to put them in
+ order. And on the left side there is a wizard who lost his rabbit. On
+ the right side is his rabbit. When you get the numbers in the right
+ order the Wizard crosses to the other side and says, "Woohoo!"
+
+
+
+
+
+
diff --git a/make/main.css b/make/main.css
index 238244d..3da0aa5 100644
--- a/make/main.css
+++ b/make/main.css
@@ -35,13 +35,13 @@ main {
}
main > a {
- color: black;
+ color: #020215;
padding: 10px 20px;
border-radius: 2px;
transition:
background 500ms,
color 500ms;
- width: 200px;
+ width: 300px;
max-width: 100%;
text-align: center;
}
@@ -49,6 +49,25 @@ main > a {
main > a:hover,
main > a:focus,
main > a:active {
- background: black;
+ background: #020215;
color: white;
}
+
+@media (prefers-color-scheme: dark) {
+ html,
+ body {
+ background-color: #020215;
+ color: white;
+ }
+
+ main > a {
+ color: white;
+ }
+
+ main > a:hover,
+ main > a:focus,
+ main > a:active {
+ background: white;
+ color: #020215;
+ }
+}
diff --git a/make/main.template.html b/make/main.template.html
index a543c2c..ecd2a70 100644
--- a/make/main.template.html
+++ b/make/main.template.html
@@ -13,6 +13,7 @@
Notes
Interviews
Grass
+ A Game with Kit