commit a159cd335f909cc75789df32bbd2cbab016bfbcf
Author: Immanuel Onyeka <immanuel@onyeka.ca>
Date:   Tue Sep 27 16:30:23 2022 -0400

    Setup page rendering

diff --git a/skouter.go b/skouter.go
new file mode 100644
index 0000000..4fbf1ef
--- /dev/null
+++ b/skouter.go
@@ -0,0 +1,87 @@
+package main
+
+import (
+		"net/http"
+		"log"
+		"sync"
+		"regexp"
+		"html/template"
+)
+
+type Page struct {
+	tpl *template.Template
+	Title string
+	Name string
+}
+
+var (
+    regexen = make(map[string]*regexp.Regexp)
+    relock  sync.Mutex
+	address = "127.0.0.1:8080"
+)
+
+var paths = map[string]string {
+	"home": "home.tpl",
+	"terms": "terms.tpl",
+}
+
+var pages = map[string]Page {
+	"home": cache("home", "Home"),
+	"terms": cache("terms", "Terms and Conditions"),
+}
+
+func cache(name string, title string) Page {
+	var p = []string{"master.tpl", paths[name]}
+	tpl := template.Must(template.ParseFiles(p...))
+	return Page{tpl: tpl,
+				Title: title,
+				Name: name,
+				}
+}
+
+func (page Page) Render(w http.ResponseWriter) {
+	err := page.tpl.Execute(w, page)
+	if err != nil {
+		log.Print(err)
+	}
+}
+
+func match(path, pattern string, args *[]string) bool {
+	relock.Lock()
+	defer relock.Unlock()
+	regex := regexen[pattern]
+	if regex == nil {
+		regex = regexp.MustCompile("^" + pattern + "$")
+		regexen[pattern] = regex
+	}
+	matches := regex.FindStringSubmatch(path)
+	if len(matches) <= 0 {
+		return false
+	}
+	*args = matches[1:]
+	return true
+}
+
+func route(w http.ResponseWriter, r *http.Request) {
+    var page Page
+	var args []string
+
+    p := r.URL.Path
+    switch {
+    case r.Method == "GET" && match(p, "/", &args):
+        page = pages[ "home" ]
+    case match(p, "/terms", &args):
+        page = pages[ "terms" ]
+    default:
+        http.NotFound(w, r)
+        return
+    }
+
+    page.Render(w)
+}
+
+func main() {
+	http.HandleFunc("/", route)
+	log.Fatal(http.ListenAndServe(address, nil))
+}
+