aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Ashby <martin@ashbysoft.com>2022-10-14 22:57:09 +0100
committerMartin Ashby <martin@ashbysoft.com>2022-10-14 22:57:09 +0100
commitf9c72b3d8f047b107449a7c6db8a602fd5535438 (patch)
treea5d32ab6a993411203ddd77abb865a70b2e2fb6c
downloadblogsite-main.tar.gz
blogsite-main.tar.bz2
blogsite-main.tar.xz
blogsite-main.zip
Initial commitmain
-rw-r--r--Caddyfile6
-rw-r--r--README.md21
-rw-r--r--content/landing.html1
-rw-r--r--content/posts/1-hello-new-blog.html2
-rw-r--r--content/posts/2-second-post.html1
-rw-r--r--index.html87
-rw-r--r--routes.json14
7 files changed, 132 insertions, 0 deletions
diff --git a/Caddyfile b/Caddyfile
new file mode 100644
index 0000000..02ba6af
--- /dev/null
+++ b/Caddyfile
@@ -0,0 +1,6 @@
+localhost {
+ encode gzip
+ root * .
+ try_files {path} /index.html
+ file_server
+} \ No newline at end of file
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..be7aeaf
--- /dev/null
+++ b/README.md
@@ -0,0 +1,21 @@
+# spa
+
+Example SPA approach to a simple blog website.
+
+## prerequisites
+- [caddy web server](https://caddywebserver.com)
+
+## run
+launch with `caddy run` and open the browser to http://localhost
+
+## how it works
+
+caddy tries to load from files, and falls back to index.html by default if no file matches.
+
+[index.html](./index.html) has a plain page template and uses javascript to dynamically create navigation and load the content.
+
+[routes.json](./routes.json) file contains the metadata for website pages (currently just title and content location)
+
+content/* files are HTML content to be embedded in the page template.
+
+assets/* files are just plain files to be served direct. \ No newline at end of file
diff --git a/content/landing.html b/content/landing.html
new file mode 100644
index 0000000..95688d5
--- /dev/null
+++ b/content/landing.html
@@ -0,0 +1 @@
+Welcome to Martin's Blog! \ No newline at end of file
diff --git a/content/posts/1-hello-new-blog.html b/content/posts/1-hello-new-blog.html
new file mode 100644
index 0000000..8776c33
--- /dev/null
+++ b/content/posts/1-hello-new-blog.html
@@ -0,0 +1,2 @@
+Hello there, here's the content of the first post of my new blog
+<b> here's something blahh</b> \ No newline at end of file
diff --git a/content/posts/2-second-post.html b/content/posts/2-second-post.html
new file mode 100644
index 0000000..8f83954
--- /dev/null
+++ b/content/posts/2-second-post.html
@@ -0,0 +1 @@
+And here's the second \ No newline at end of file
diff --git a/index.html b/index.html
new file mode 100644
index 0000000..eba968c
--- /dev/null
+++ b/index.html
@@ -0,0 +1,87 @@
+<!doctype HTML>
+<html>
+<head>
+ <style>
+ /* CSS taken from https://perfectmotherfuckingwebsite.com/ */
+ body{
+ max-width:650px;
+ margin:40px auto;
+ padding:0 10px;
+ font:18px/1.5 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
+ color:#444
+ }
+ h1,h2,h3{
+ line-height:1.2
+ }
+ @media (prefers-color-scheme: dark){
+ body{
+ color:#c9d1d9;
+ background:#0d1117
+ }
+ a:link{
+ color:#58a6ff
+ }
+ a:visited{
+ color:#8e96f0
+ }
+ }
+ </style>
+ <script type="text/javascript">
+ let routes = {};
+ async function loadNav() {
+ let resp = await fetch("/routes.json");
+ routes = await resp.json();
+ let lis = Object.entries(routes).map(([key,route]) => {
+ let li = document.createElement("li");
+ let a = document.createElement("a");
+ let tn = document.createTextNode(route.title);
+ a.replaceChildren(tn);
+ a.href = "/"+key;
+ a.onclick = function(e) {
+ goto(key).then(() => {});
+ e.preventDefault();
+ };
+ li.replaceChildren(a);
+ return li;
+ })
+ let nav = document.getElementsByTagName("nav")[0];
+ nav.children[0].replaceChildren(...lis);
+ }
+ async function goto(key) {
+ let nextURL = new URL(window.location);
+ nextURL.pathname = "/"+key;
+ const nextTitle = routes[key].title;
+ const nextState = { additionalInformation: 'Updated the URL with JS' };
+ window.history.pushState(nextState, nextTitle, nextURL);
+ // Manually fire popstate :shrug:
+ // https://stackoverflow.com/questions/10940837/history-pushstate-does-not-trigger-popstate-event
+ let popStateEvent = new PopStateEvent('popstate', { state: nextState, title: nextTitle, location: nextURL });
+ dispatchEvent(popStateEvent);
+ }
+ async function loadContent() {
+ let key = window.location.pathname.substring(1);
+ let contentElem = document.getElementsByTagName("content")[0];
+ let head = document.getElementsByTagName("h1")[0];
+ let route = routes[key] ?? routes[""];
+ let contentFile = route.content;
+ head.innerHTML = route.title;
+ let resp = await fetch(contentFile);
+ let content = await resp.text();
+ contentElem.innerHTML = content;
+ }
+ window.addEventListener('popstate', async (event) => {
+ await loadContent();
+ });
+ window.addEventListener('load', async (event) => {
+ await loadNav();
+ await loadContent();
+ });
+ </script>
+ <title>Martin's Blog!</title>
+</head>
+<body>
+ <h1></h1>
+ <nav><ol></ol></nav>
+ <content></content>
+</body>
+</html> \ No newline at end of file
diff --git a/routes.json b/routes.json
new file mode 100644
index 0000000..9b02008
--- /dev/null
+++ b/routes.json
@@ -0,0 +1,14 @@
+{
+ "": {
+ "title": "Home",
+ "content": "/content/landing.html"
+ },
+ "1-hello-new-blog": {
+ "title": "Hello New Blog",
+ "content": "/content/posts/1-hello-new-blog.html"
+ },
+ "2-second-blog": {
+ "title": "Second Blog Post",
+ "content": "/content/posts/2-second-post.html"
+ }
+} \ No newline at end of file