summaryrefslogtreecommitdiff
path: root/website.go
diff options
context:
space:
mode:
Diffstat (limited to 'website.go')
-rw-r--r--website.go285
1 files changed, 274 insertions, 11 deletions
diff --git a/website.go b/website.go
index d1cf44d..8802bd1 100644
--- a/website.go
+++ b/website.go
@@ -1,12 +1,271 @@
package main
import (
+ "encoding/json"
"fmt"
"net/http"
+ "strings"
+ "sync"
+
+ "github.com/a-h/templ"
)
+func Assert(ok bool) {
+ if !ok {
+ panic("assertion failure")
+ }
+}
+
+type Theme struct {
+ primary string
+ secondary string
+ accent string
+ extra string
+ text string
+ alt string
+ background string
+}
+
+type FontPack struct {
+ Monospace string
+ Normal string
+}
+
+type Style struct {
+ theme Theme
+ fontPack FontPack
+}
+
+var (
+ mu sync.RWMutex
+ themes = map[string]Theme{}
+ fontPacks = map[string]FontPack{}
+)
+
+func SetFontPack(name string, fontPack FontPack) {
+ mu.Lock()
+ defer mu.Unlock()
+ fontPacks[name] = fontPack
+}
+
+func GetFontPack(name string) (FontPack, bool) {
+ mu.RLock()
+ defer mu.RUnlock()
+ fontPack, ok := fontPacks[name]
+ return fontPack, ok
+}
+
+func SetTheme(name string, theme Theme) {
+ mu.Lock()
+ defer mu.Unlock()
+ themes[name] = theme
+}
+
+func GetTheme(name string) (Theme, bool) {
+ mu.RLock()
+ defer mu.RUnlock()
+ theme, ok := themes[name]
+ return theme, ok
+}
+
+func currentStyle(r *http.Request) Style {
+ theme, ok := GetTheme("default")
+ Assert(ok)
+ fontPack, ok := GetFontPack("default")
+ Assert(ok)
+ style := Style{
+ theme: theme,
+ fontPack: fontPack,
+ }
+
+ if cookie, err := r.Cookie("theme"); err == nil {
+ if theme, ok := GetTheme(cookie.Value); ok {
+ style.theme = theme
+ }
+ }
+
+ if cookie, err := r.Cookie("font-pack"); err == nil {
+ if fontPack, ok := GetFontPack(cookie.Value); ok {
+ style.fontPack = fontPack
+ }
+ }
+
+ return style
+}
+
+func (theme Theme) Vars() map[string]string {
+ return map[string]string{
+ "primary": theme.primary,
+ "secondary": theme.secondary,
+ "accent": theme.accent,
+ "extra": theme.extra,
+ "text": theme.text,
+ "alt": theme.alt,
+ "background": theme.background,
+ }
+}
+
+func (fontPack FontPack) Vars() map[string]string {
+ return map[string]string{
+ "font-mono": fontPack.Monospace,
+ "font-normal": fontPack.Normal,
+ }
+}
+
+func (style Style) Vars() map[string]string {
+ vars := style.theme.Vars()
+ for k, v := range style.fontPack.Vars() {
+ vars[k] = v
+ }
+ return vars
+}
+
+func styleToCss(style Style) templ.SafeCSS {
+ var b strings.Builder
+ for k, v := range style.Vars() {
+ fmt.Fprintf(&b, "--%s:%s;", k, v)
+ }
+ return templ.SafeCSS(b.String())
+}
+
+type Project struct {
+ Name string
+ Type string
+ Desc []string
+ Cmd string
+ Link string
+}
+
+var projects = []Project{
+ {
+ Name: "CPU vs AI",
+ Type: "Game (made with Zig)",
+ Desc: []string{
+ "A tower defense game where an AI chip on your motherboard",
+ "generates bugs! Place CPUs to destroy the bugs!",
+ "Don't let them corrupt your RAM!",
+ },
+ },
+ {
+ Name: "Eko",
+ Type: "Social Media Platform",
+ Desc: []string{
+ "A terminal-native alternative",
+ "to Discord for Terminal",
+ "nerds!",
+ },
+ },
+ {
+ Name: "Trident",
+ Type: "IntelliJ Plugin",
+ Desc: []string{
+ "A blazingly fast way to",
+ "Navigate to your mosta used",
+ "files. Minimize keystrokes",
+ "and maximize productivity!",
+ },
+ },
+ {
+ Name: "Dotfiles",
+ Type: "Configuration",
+ Desc: []string{
+ "My Linux configuration,",
+ "includes Neovim, tmux and",
+ "other programs.",
+ },
+ },
+}
+
+func styleHandler(cookie string, lookup func(string) (map[string]string, bool)) http.HandlerFunc {
+ return func(w http.ResponseWriter, r *http.Request) {
+ name := r.PathValue("name")
+ vars, ok := lookup(name)
+ if !ok {
+ http.NotFound(w, r)
+ return
+ }
+ http.SetCookie(w, &http.Cookie{
+ Name: cookie, Value: name, Path: "/",
+ MaxAge: 31536000, SameSite: http.SameSiteLaxMode,
+ })
+ w.Header().Set("Cache-Control", "no-store")
+ json.NewEncoder(w).Encode(vars)
+ }
+}
+
func main() {
- fmt.Println("foo")
+ carbonightCat := Theme{
+ primary: "#94e2d5",
+ secondary: "#b4befe",
+ accent: "#74c7ec",
+ extra: "#a6e3a1",
+ text: "#cdd6f4",
+ alt: "#585b70",
+ background: "#1e1e2e",
+ }
+ darkness := Theme{
+ primary: "#000000",
+ secondary: "#000000",
+ accent: "#000000",
+ extra: "#000000",
+ text: "#000000",
+ alt: "#000000",
+ background: "#000000",
+ }
+ dark := Theme{
+ primary: "#54d7a9",
+ secondary: "#9b7eca",
+ accent: "#7ed4fb",
+ extra: "#8fcc75",
+ text: "#ffffff",
+ alt: "#999999",
+ background: "#000000",
+ }
+ light := Theme{
+ primary: "#009399",
+ secondary: "#440b8e",
+ accent: "#177282",
+ extra: "#40a02b",
+ text: "#000000",
+ alt: "#4d4d4d",
+ background: "#ffffff",
+ }
+ banana := Theme{
+ primary: "#ffdd44",
+ secondary: "#9b7eca",
+ accent: "#7ed4fb",
+ extra: "#000000",
+ text: "#ffffff",
+ alt: "#999999",
+ background: "#000000",
+ }
+
+ jetbrains := FontPack{
+ Monospace: "JetBrains Mono",
+ Normal: `system-ui, sans-serif`,
+ }
+
+ minecraft := FontPack{
+ Monospace: `"Monocraft", "JetBrains Mono", monospace`,
+ Normal: `"Monocraft", system-ui, sans-serif`,
+ }
+
+ SetTheme("carbonight-cat", carbonightCat)
+ SetTheme("banana", banana)
+ SetTheme("black", dark)
+ SetTheme("dark", darkness)
+
+ SetTheme("light", light)
+ SetTheme("white", light)
+ SetTheme("sun", light)
+ SetTheme("sunlight", light)
+ SetTheme("flashbang", light)
+
+ SetTheme("default", carbonightCat)
+
+ SetFontPack("jetbrains", jetbrains)
+ SetFontPack("minecraft", minecraft)
+ SetFontPack("default", jetbrains)
mux := http.NewServeMux()
@@ -14,22 +273,26 @@ func main() {
mux.Handle("GET /public/", http.StripPrefix("/public/", fileServer))
mux.HandleFunc("GET /{$}", func(w http.ResponseWriter, r *http.Request) {
- HomePage().Render(r.Context(), w)
+ HomePage(currentStyle(r)).Render(r.Context(), w)
})
- mux.HandleFunc("GET /about", func(w http.ResponseWriter, r *http.Request) {
- AboutPage().Render(r.Context(), w)
+ mux.HandleFunc("GET /skills", func(w http.ResponseWriter, r *http.Request) {
+ SkillsPage(currentStyle(r)).Render(r.Context(), w)
})
- mux.HandleFunc("GET /items", func(w http.ResponseWriter, r *http.Request) {
- data := []Item{
- {Name: "Foo", Active: true},
- {Name: "Bar", Active: true},
- {Name: "Baz", Active: false},
- }
- ItemsPage(data).Render(r.Context(), w)
+ mux.HandleFunc("GET /projects", func(w http.ResponseWriter, r *http.Request) {
+ ProjectsPage(currentStyle(r), projects).Render(r.Context(), w)
})
+ mux.HandleFunc("GET /theme/{name}", styleHandler("theme", func(n string) (map[string]string, bool) {
+ theme, ok := GetTheme(n)
+ return theme.Vars(), ok
+ }))
+ mux.HandleFunc("GET /font-pack/{name}", styleHandler("font-pack", func(n string) (map[string]string, bool) {
+ fontPack, ok := GetFontPack(n)
+ return fontPack.Vars(), ok
+ }))
+
fmt.Println("Server running at http://localhost:8080")
if err := http.ListenAndServe(":8080", mux); err != nil {
panic(err)