From 81d9e315a0fdd02b6fd93152554b8d7eda1bbf5e Mon Sep 17 00:00:00 2001
From: DutchEllie <personal@quenten.nl>
Date: Tue, 15 Mar 2022 12:48:47 +0100
Subject: [PATCH] Major refactor

---
 Dockerfile                            |   4 +-
 Makefile                              |   8 +-
 components/content-view.go            |  23 ------
 components/homepage.go                |  67 -----------------
 {components => src}/aboutpage.go      |  17 +++--
 {components => src}/bannerpanel.go    |   2 +-
 src/block.go                          |  74 +++++++++++++++++++
 {components => src}/galaxiespage.go   |  18 +++--
 {components => src}/guestbookform.go  |   2 +-
 {components => src}/guestbookpanel.go |  18 +++--
 {components => src}/header.go         |   2 +-
 src/homepage.go                       | 101 ++++++++++++++++++++++++++
 {components => src}/homepanel.go      |   2 +-
 src/html-doc.go                       |  75 +++++++++++++++++++
 src/html.go                           |  63 ++++++++++++++++
 src/http.go                           |  41 +++++++++++
 main.go => src/main.go                |   9 ++-
 {components => src}/modal.go          |   2 +-
 {components => src}/navbar.go         |   2 +-
 src/page.go                           |  61 ++++++++++++++++
 {components => src}/updater.go        |   2 +-
 web/blocks/about.html                 |  22 ++++++
 web/blocks/galaxies.html              |  46 ++++++++++++
 web/blocks/intro.html                 |  18 +++++
 web/static/style.css                  |  21 ++++++
 25 files changed, 572 insertions(+), 128 deletions(-)
 delete mode 100644 components/content-view.go
 delete mode 100644 components/homepage.go
 rename {components => src}/aboutpage.go (90%)
 rename {components => src}/bannerpanel.go (90%)
 create mode 100644 src/block.go
 rename {components => src}/galaxiespage.go (94%)
 rename {components => src}/guestbookform.go (99%)
 rename {components => src}/guestbookpanel.go (89%)
 rename {components => src}/header.go (91%)
 create mode 100644 src/homepage.go
 rename {components => src}/homepanel.go (99%)
 create mode 100644 src/html-doc.go
 create mode 100644 src/html.go
 create mode 100644 src/http.go
 rename main.go => src/main.go (92%)
 rename {components => src}/modal.go (97%)
 rename {components => src}/navbar.go (95%)
 create mode 100644 src/page.go
 rename {components => src}/updater.go (97%)
 create mode 100644 web/blocks/about.html
 create mode 100644 web/blocks/galaxies.html
 create mode 100644 web/blocks/intro.html

diff --git a/Dockerfile b/Dockerfile
index 743ce8b..9f9281a 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -3,8 +3,8 @@ ARG APIURL
 WORKDIR /project
 ADD . /project/
 RUN go mod tidy
-RUN GOARCH=wasm GOOS=js go build -ldflags="-X 'dutchellie.nl/DutchEllie/proper-website-2/components.ApiURL=$APIURL'" -o web/app.wasm
-RUN	go build -ldflags="-X 'dutchellie.nl/DutchEllie/proper-website-2/components.ApiURL=$APIURL'" -o app
+RUN GOARCH=wasm GOOS=js go build -o web/app.wasm -ldflags="-X 'main.ApiURL=$APIURL'" ./src
+RUN	go build -o app -ldflags="-X 'main.ApiURL=$APIURL'" ./src
 
 FROM alpine:latest AS staging
 RUN apk --no-cache add ca-certificates
diff --git a/Makefile b/Makefile
index a300193..7b71ece 100644
--- a/Makefile
+++ b/Makefile
@@ -2,12 +2,12 @@ APIURL_prod := https://api.nicecock.eu/api/comment
 APIURL_staging := https://api.nicecock.eu/api/testingcomment
 
 build:
-	GOARCH=wasm GOOS=js go build -ldflags="-X 'dutchellie.nl/DutchEllie/proper-website-2/components.ApiURL=${APIURL_staging}'" -o web/app.wasm
-	go build -ldflags="-X 'dutchellie.nl/DutchEllie/proper-website-2/components.ApiURL=${APIURL_staging}'" -o app
+	GOARCH=wasm GOOS=js go build -o web/app.wasm -ldflags="-X 'main.ApiURL=${APIURL_staging}'"  ./src
+	go build -o app -ldflags="-X 'main.ApiURL=${APIURL_staging}'" ./src
 
 build-prod:
-	GOARCH=wasm GOOS=js go build -ldflags="-X 'dutchellie.nl/DutchEllie/proper-website-2/components.ApiURL=${APIURL_prod}'" -o web/app.wasm
-	go build -ldflags="-X 'dutchellie.nl/DutchEllie/proper-website-2/components.ApiURL=${APIURL_prod}'" -o app
+	GOARCH=wasm GOOS=js go build -o web/app.wasm -ldflags="-X 'main.ApiURL=${APIURL_prod}'" ./src
+	go build -o app -ldflags="-X 'main.ApiURL=${APIURL_prod}'" ./src
 
 run: build
 	./app
diff --git a/components/content-view.go b/components/content-view.go
deleted file mode 100644
index 790248d..0000000
--- a/components/content-view.go
+++ /dev/null
@@ -1,23 +0,0 @@
-package components
-
-import (
-	"github.com/maxence-charriere/go-app/v9/pkg/app"
-)
-
-type contentView struct {
-	app.Compo
-
-	panels []app.UI
-}
-
-func newContentView(panels ...app.UI) *contentView {
-	return &contentView{panels: panels}
-}
-
-func (c *contentView) Render() app.UI {
-	return app.Div().Body(
-		app.Range(c.panels).Slice(func(i int) app.UI {
-			return c.panels[i]
-		}),
-	)
-}
diff --git a/components/homepage.go b/components/homepage.go
deleted file mode 100644
index dec570d..0000000
--- a/components/homepage.go
+++ /dev/null
@@ -1,67 +0,0 @@
-package components
-
-import (
-	"bytes"
-	"encoding/json"
-	"fmt"
-	"net/http"
-
-	"dutchellie.nl/DutchEllie/proper-website-2/entity"
-	"github.com/maxence-charriere/go-app/v9/pkg/app"
-)
-
-var (
-	ApiURL string
-)
-
-type Homepage struct {
-	app.Compo
-
-	showGuestbook bool
-
-	page string
-}
-
-func NewHomepage() *Homepage {
-	return &Homepage{showGuestbook: true, page: "home"}
-}
-
-func (p *Homepage) Render() app.UI {
-	gbp := newGuestbookPanel()
-	return app.Div().Body(
-		&header{},
-		&navbar{},
-		&homePanel{
-			onShowClick: func() {
-				p.showGuestbook = !p.showGuestbook
-			},
-		},
-		&bannerPanel{},
-		&guestbookForm{
-			OnSubmit: func(name, message string) {
-				var comment entity.Comment
-				comment.Name = name
-				comment.Message = message
-
-				jsondata, err := json.Marshal(comment)
-				if err != nil {
-					fmt.Printf("err: %v\n", err)
-					return
-				}
-				url := ApiURL
-
-				req, err := http.Post(url, "application/json", bytes.NewBuffer(jsondata))
-				if err != nil {
-					fmt.Printf("err: %v\n", err)
-					return
-				}
-				if req.StatusCode == 200 {
-					p.Update()
-				}
-				defer req.Body.Close()
-			},
-		},
-		//app.If(p.showGuestbook, gbp),
-		gbp.Render(),
-	).Class("main")
-}
diff --git a/components/aboutpage.go b/src/aboutpage.go
similarity index 90%
rename from components/aboutpage.go
rename to src/aboutpage.go
index 31347be..ce0bdaf 100644
--- a/components/aboutpage.go
+++ b/src/aboutpage.go
@@ -1,4 +1,4 @@
-package components
+package main
 
 import (
 	"github.com/maxence-charriere/go-app/v9/pkg/app"
@@ -13,11 +13,16 @@ func NewAboutPage() *AboutPage {
 }
 
 func (a *AboutPage) Render() app.UI {
-	return app.Div().Body(
-		&header{},
-		&navbar{},
-		&aboutPanel{},
-	)
+	return newPage().
+		Title("About me").
+		LeftBar(
+			&bannerPanel{},
+		).
+		Main(
+			newHTMLBlock().
+				Class("right").
+				Src("/web/blocks/about.html"),
+		)
 }
 
 type aboutPanel struct {
diff --git a/components/bannerpanel.go b/src/bannerpanel.go
similarity index 90%
rename from components/bannerpanel.go
rename to src/bannerpanel.go
index 848ed8a..8ed8fc1 100644
--- a/components/bannerpanel.go
+++ b/src/bannerpanel.go
@@ -1,4 +1,4 @@
-package components
+package main
 
 import "github.com/maxence-charriere/go-app/v9/pkg/app"
 
diff --git a/src/block.go b/src/block.go
new file mode 100644
index 0000000..ecb25f1
--- /dev/null
+++ b/src/block.go
@@ -0,0 +1,74 @@
+package main
+
+import (
+	"github.com/maxence-charriere/go-app/v9/pkg/app"
+)
+
+type htmlBlock struct {
+	app.Compo
+
+	Iclass string
+	Isrc   string // HTML document source
+
+	// TODO: implement invisibility for other background functions
+}
+
+func newHTMLBlock() *htmlBlock {
+	return &htmlBlock{}
+}
+
+func (b *htmlBlock) Class(v string) *htmlBlock {
+	b.Iclass = app.AppendClass(b.Iclass, v)
+	return b
+}
+
+func (b *htmlBlock) Src(v string) *htmlBlock {
+	b.Isrc = v
+	return b
+}
+
+func (b *htmlBlock) Render() app.UI {
+	return app.Div().
+		Class("block").
+		Class(b.Iclass).
+		Body(
+			newRemoteHTMLDoc().
+				Src(b.Isrc),
+		)
+}
+
+// ==================
+// UI element block
+// ==================
+
+type uiBlock struct {
+	app.Compo
+
+	Iclass string
+	Iui    []app.UI
+}
+
+func newUIBlock() *uiBlock {
+	return &uiBlock{}
+}
+
+func (b *uiBlock) Class(v string) *uiBlock {
+	b.Iclass = app.AppendClass(b.Iclass, v)
+	return b
+}
+
+func (b *uiBlock) UI(v ...app.UI) *uiBlock {
+	b.Iui = app.FilterUIElems(v...)
+	return b
+}
+
+func (b *uiBlock) Render() app.UI {
+	return app.Div().
+		Class("block").
+		Class(b.Iclass).
+		Body(
+			app.Range(b.Iui).Slice(func(i int) app.UI {
+				return b.Iui[i]
+			}),
+		)
+}
diff --git a/components/galaxiespage.go b/src/galaxiespage.go
similarity index 94%
rename from components/galaxiespage.go
rename to src/galaxiespage.go
index 9963fa5..623dd30 100644
--- a/components/galaxiespage.go
+++ b/src/galaxiespage.go
@@ -1,4 +1,4 @@
-package components
+package main
 
 import "github.com/maxence-charriere/go-app/v9/pkg/app"
 
@@ -11,12 +11,16 @@ func NewGalaxiesPage() *GalaxiesPage {
 }
 
 func (f *GalaxiesPage) Render() app.UI {
-	return app.Div().Body(
-		&header{},
-		&navbar{},
-		&galaxiesPanel{},
-		&bannerPanel{},
-	).Class("main")
+	return newPage().
+		Title("Galaxies").
+		LeftBar(
+			&bannerPanel{},
+		).
+		Main(
+			newHTMLBlock().
+				Class("right").
+				Src("/web/blocks/galaxies.html"),
+		)
 }
 
 type galaxiesPanel struct {
diff --git a/components/guestbookform.go b/src/guestbookform.go
similarity index 99%
rename from components/guestbookform.go
rename to src/guestbookform.go
index c029c0c..f27a840 100644
--- a/components/guestbookform.go
+++ b/src/guestbookform.go
@@ -1,4 +1,4 @@
-package components
+package main
 
 import (
 	"fmt"
diff --git a/components/guestbookpanel.go b/src/guestbookpanel.go
similarity index 89%
rename from components/guestbookpanel.go
rename to src/guestbookpanel.go
index d08b88c..9605c1c 100644
--- a/components/guestbookpanel.go
+++ b/src/guestbookpanel.go
@@ -1,4 +1,4 @@
-package components
+package main
 
 import (
 	"encoding/json"
@@ -35,13 +35,15 @@ func newGuestbookPanel() *guestbookPanel {
 }
 
 func (g *guestbookPanel) Render() app.UI {
-	return app.Div().Body(
-		app.Range(g.comments).Slice(func(i int) app.UI {
-			return &guestbookComment{
-				Comment: g.comments[i],
-			}
-		}),
-	).Class("content gbp")
+	return newUIBlock().
+		Class("right").
+		UI(
+			app.Range(g.comments).Slice(func(i int) app.UI {
+				return &guestbookComment{
+					Comment: g.comments[i],
+				}
+			}),
+		)
 }
 
 func (g *guestbookPanel) LoadComments() {
diff --git a/components/header.go b/src/header.go
similarity index 91%
rename from components/header.go
rename to src/header.go
index c0d23c7..af6edd7 100644
--- a/components/header.go
+++ b/src/header.go
@@ -1,4 +1,4 @@
-package components
+package main
 
 import "github.com/maxence-charriere/go-app/v9/pkg/app"
 
diff --git a/src/homepage.go b/src/homepage.go
new file mode 100644
index 0000000..2488ac9
--- /dev/null
+++ b/src/homepage.go
@@ -0,0 +1,101 @@
+package main
+
+import (
+	"bytes"
+	"encoding/json"
+	"fmt"
+	"net/http"
+
+	"dutchellie.nl/DutchEllie/proper-website-2/entity"
+	"github.com/maxence-charriere/go-app/v9/pkg/app"
+)
+
+var (
+	ApiURL string
+)
+
+type Homepage struct {
+	app.Compo
+
+	showGuestbook bool
+}
+
+func NewHomepage() *Homepage {
+	return &Homepage{}
+}
+
+func (p *Homepage) Render() app.UI {
+	gbp := newGuestbookPanel()
+	return newPage().
+		Title("Homepage").
+		LeftBar(
+			&bannerPanel{},
+		).
+		Main(
+			newHTMLBlock().
+				Class("right").
+				Src("/web/blocks/intro.html"),
+			&guestbookForm{
+				OnSubmit: func(name, message string) {
+					var comment entity.Comment
+					comment.Name = name
+					comment.Message = message
+
+					jsondata, err := json.Marshal(comment)
+					if err != nil {
+						fmt.Printf("err: %v\n", err)
+						return
+					}
+					url := ApiURL
+
+					req, err := http.Post(url, "application/json", bytes.NewBuffer(jsondata))
+					if err != nil {
+						fmt.Printf("err: %v\n", err)
+						return
+					}
+					if req.StatusCode == 200 {
+						p.Update()
+					}
+					defer req.Body.Close()
+				},
+			},
+			gbp.Render(),
+		)
+	/*
+		return app.Div().Body(
+			&header{},
+			&navbar{},
+			&homePanel{
+				onShowClick: func() {
+					p.showGuestbook = !p.showGuestbook
+				},
+			},
+			&bannerPanel{},
+			&guestbookForm{
+				OnSubmit: func(name, message string) {
+					var comment entity.Comment
+					comment.Name = name
+					comment.Message = message
+
+					jsondata, err := json.Marshal(comment)
+					if err != nil {
+						fmt.Printf("err: %v\n", err)
+						return
+					}
+					url := ApiURL
+
+					req, err := http.Post(url, "application/json", bytes.NewBuffer(jsondata))
+					if err != nil {
+						fmt.Printf("err: %v\n", err)
+						return
+					}
+					if req.StatusCode == 200 {
+						p.Update()
+					}
+					defer req.Body.Close()
+				},
+			},
+			//app.If(p.showGuestbook, gbp),
+			gbp.Render(),
+		).Class("main")*/
+}
diff --git a/components/homepanel.go b/src/homepanel.go
similarity index 99%
rename from components/homepanel.go
rename to src/homepanel.go
index e7ce3f3..6b1650e 100644
--- a/components/homepanel.go
+++ b/src/homepanel.go
@@ -1,4 +1,4 @@
-package components
+package main
 
 import "github.com/maxence-charriere/go-app/v9/pkg/app"
 
diff --git a/src/html-doc.go b/src/html-doc.go
new file mode 100644
index 0000000..6200a49
--- /dev/null
+++ b/src/html-doc.go
@@ -0,0 +1,75 @@
+package main
+
+import (
+	"fmt"
+
+	"github.com/maxence-charriere/go-app/v9/pkg/app"
+)
+
+type htmlDoc struct {
+	app.Compo
+
+	Ihtml string
+}
+
+func newHTMLDoc() *htmlDoc {
+	return &htmlDoc{}
+}
+
+func (h *htmlDoc) HTML(v string) *htmlDoc {
+	h.Ihtml = fmt.Sprintf("<div>%s</div>", v)
+	return h
+}
+
+func (h *htmlDoc) Render() app.UI {
+	return app.Raw(h.Ihtml)
+}
+
+type remoteHTMLDoc struct {
+	app.Compo
+
+	Isrc string
+
+	html htmlContent
+}
+
+func newRemoteHTMLDoc() *remoteHTMLDoc {
+	return &remoteHTMLDoc{}
+}
+
+func (h *remoteHTMLDoc) Src(v string) *remoteHTMLDoc {
+	h.Isrc = v
+	return h
+}
+
+func (h *remoteHTMLDoc) OnMount(ctx app.Context) {
+	h.load(ctx)
+}
+
+func (h *remoteHTMLDoc) OnNav(ctx app.Context) {
+	h.load(ctx)
+}
+
+func (h *remoteHTMLDoc) load(ctx app.Context) {
+	src := h.Isrc
+	ctx.ObserveState(htmlState(src)).
+		While(func() bool {
+			return src == h.Isrc
+		}).
+		OnChange(func() {
+
+		}).
+		Value(&h.html)
+
+	ctx.NewAction(getHTML, app.T("path", h.Isrc))
+}
+
+func (h *remoteHTMLDoc) Render() app.UI {
+	return app.Div().
+		Body(
+			app.If(h.html.Status == loaded,
+				newHTMLDoc().
+					HTML(h.html.Data),
+			).Else(),
+		)
+}
diff --git a/src/html.go b/src/html.go
new file mode 100644
index 0000000..a361e72
--- /dev/null
+++ b/src/html.go
@@ -0,0 +1,63 @@
+package main
+
+import (
+	"errors"
+
+	"github.com/maxence-charriere/go-app/v9/pkg/app"
+)
+
+const (
+	getHTML = "/html/get"
+)
+
+func handleGetHTML(ctx app.Context, a app.Action) {
+	path := a.Tags.Get("path")
+	if path == "" {
+		app.Log(errors.New("getting html failed"))
+		return
+	}
+
+	state := htmlState(path)
+
+	var ht htmlContent
+	ctx.GetState(state, &ht)
+	switch ht.Status {
+	case loading, loaded:
+		return
+	}
+
+	ht.Status = loading
+	ht.Error = nil
+	ctx.SetState(state, ht)
+
+	res, err := get(ctx, path)
+	if err != nil {
+		ht.Status = loadingErr
+		ht.Error = err
+		ctx.SetState(state, ht)
+		return
+	}
+
+	ht.Status = loaded
+	ht.Data = string(res)
+	ctx.SetState(state, ht)
+}
+
+func htmlState(src string) string {
+	return src
+}
+
+type htmlContent struct {
+	Status status
+	Error  error
+	Data   string
+}
+
+type status int
+
+const (
+	neverLoaded status = iota
+	loading
+	loadingErr
+	loaded
+)
diff --git a/src/http.go b/src/http.go
new file mode 100644
index 0000000..dc05002
--- /dev/null
+++ b/src/http.go
@@ -0,0 +1,41 @@
+package main
+
+import (
+	"fmt"
+	"io"
+	"net/http"
+	"strings"
+
+	"github.com/maxence-charriere/go-app/v9/pkg/app"
+)
+
+func get(ctx app.Context, path string) ([]byte, error) {
+	url := path
+	if !strings.HasPrefix(url, "http") {
+		u := ctx.Page().URL()
+		u.Path = path
+		url = u.String()
+	}
+
+	req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
+	if err != nil {
+		fmt.Printf("Error at getting html page\n")
+		return nil, err
+	}
+	res, err := http.DefaultClient.Do(req)
+	if err != nil {
+		return nil, err
+	}
+	defer res.Body.Close()
+
+	// Which means either client or server error
+	if res.StatusCode >= 400 {
+		return nil, err
+	}
+
+	b, err := io.ReadAll(res.Body)
+	if err != nil {
+		return nil, err
+	}
+	return b, nil
+}
diff --git a/main.go b/src/main.go
similarity index 92%
rename from main.go
rename to src/main.go
index 1c9cd99..513aa2a 100644
--- a/main.go
+++ b/src/main.go
@@ -4,7 +4,6 @@ import (
 	"log"
 	"net/http"
 
-	"dutchellie.nl/DutchEllie/proper-website-2/components"
 	"github.com/maxence-charriere/go-app/v9/pkg/app"
 )
 
@@ -19,13 +18,15 @@ const (
 )
 
 func main() {
-	homepage := components.NewHomepage()
-	aboutpage := components.NewAboutPage()
-	galaxiespage := components.NewGalaxiesPage()
+	homepage := NewHomepage()
+	aboutpage := NewAboutPage()
+	galaxiespage := NewGalaxiesPage()
 	app.Route("/", homepage)
 	app.Route("/about", aboutpage)
 	app.Route("/galaxies", galaxiespage)
 
+	app.Handle(getHTML, handleGetHTML)
+
 	// This is executed on the client side only.
 	// It handles client side stuff
 	// It exits immediately on the server side
diff --git a/components/modal.go b/src/modal.go
similarity index 97%
rename from components/modal.go
rename to src/modal.go
index 1c7e21a..a200266 100644
--- a/components/modal.go
+++ b/src/modal.go
@@ -1,4 +1,4 @@
-package components
+package main
 
 import "github.com/maxence-charriere/go-app/v9/pkg/app"
 
diff --git a/components/navbar.go b/src/navbar.go
similarity index 95%
rename from components/navbar.go
rename to src/navbar.go
index 6bbea67..8317fd8 100644
--- a/components/navbar.go
+++ b/src/navbar.go
@@ -1,4 +1,4 @@
-package components
+package main
 
 import "github.com/maxence-charriere/go-app/v9/pkg/app"
 
diff --git a/src/page.go b/src/page.go
new file mode 100644
index 0000000..f7856e4
--- /dev/null
+++ b/src/page.go
@@ -0,0 +1,61 @@
+package main
+
+import "github.com/maxence-charriere/go-app/v9/pkg/app"
+
+// Page is a generic page. By default it has a header, navbar and a default leftbar
+type page struct {
+	app.Compo
+
+	Ititle string
+	/*Description
+	Blah blah
+	etc*/
+
+	IleftBar []app.UI
+	Imain    []app.UI
+
+	// TODO: Possibly add "updateavailable" here, so it shows up on every page
+}
+
+func newPage() *page {
+	return &page{}
+}
+
+func (p *page) Title(t string) *page {
+	p.Ititle = t
+	return p
+}
+
+func (p *page) LeftBar(v ...app.UI) *page {
+	p.IleftBar = app.FilterUIElems(v...)
+	return p
+}
+
+func (p *page) Main(v ...app.UI) *page {
+	p.Imain = app.FilterUIElems(v...)
+	return p
+}
+
+func (p *page) Render() app.UI {
+	return app.Div().
+		Class("main").
+		Body(
+			// Header and navbar
+			&header{},
+			app.Div().
+				Class("left").
+				Body(
+					&navbar{},
+					app.Range(p.IleftBar).Slice(func(i int) app.UI {
+						return p.IleftBar[i]
+					}),
+				),
+			app.Div().
+				Class("right").
+				Body(
+					app.Range(p.Imain).Slice(func(i int) app.UI {
+						return p.Imain[i]
+					}),
+				),
+		)
+}
diff --git a/components/updater.go b/src/updater.go
similarity index 97%
rename from components/updater.go
rename to src/updater.go
index d5f32b9..c721ef4 100644
--- a/components/updater.go
+++ b/src/updater.go
@@ -1,4 +1,4 @@
-package components
+package main
 
 import "github.com/maxence-charriere/go-app/v9/pkg/app"
 
diff --git a/web/blocks/about.html b/web/blocks/about.html
new file mode 100644
index 0000000..d5649c1
--- /dev/null
+++ b/web/blocks/about.html
@@ -0,0 +1,22 @@
+<img src="/web/static/images/rin-1.gif" style="width:100px;position:absolute;top:10px;right:10px;">
+<p class="content-text">I am a 21 year old computer science student (they/them, he/him, she/her), living and studying in
+	The Netherlands. I like Docker, Kubernetes and Golang!
+	<br>
+	I made this website because I was inspired again by the amazing Neocities pages that I discovered because of my
+	friends.
+	They also have their own pages (you can find them on the friends tab, do check them out!) and I just had to get a
+	good website of my own!
+	<br>
+	I am not that great at web development, especially design, but I love trying it regardless!
+	<br><br>
+	To say a bit more about me personally, I love all things computers. From servers to embedded devices! I love the
+	cloud and all that it brings
+	(except for big megacorps, but alright) and it's my goal to work for a big cloud company!
+	<br>
+	Aside from career path ambitions,ボーカロイドはすきです! I love vocaloid and other Japanese music and culture!!
+	I also like Vtubers, especially from Hololive and it's my goal to one day finally understand them in their native
+	language!
+	<br><br>
+	There is a lot more to say in words, but who cares about those! Have a look around my creative digital oasis and see
+	what crazy stuff you can find!
+</p>
\ No newline at end of file
diff --git a/web/blocks/galaxies.html b/web/blocks/galaxies.html
new file mode 100644
index 0000000..2498137
--- /dev/null
+++ b/web/blocks/galaxies.html
@@ -0,0 +1,46 @@
+<p class="p-h1">
+	Galaxies
+</p>
+<p class="content-text">
+	Here you can find some really really really cool pages that I found on the internet.
+	Some of these are blogs or even blogposts I found, but the ones on top are special!
+	They're the websites of friends of mine! Please visit them, because they worked really hard
+	on their websites as well!
+</p>
+<div>
+	<p class="p-h2 mt-20 mb-10 bold">My friends!</p>
+	<ul>
+		<li>
+			<div><a href="https://forestofunix.xyz" class="p-h3 m-t5">Forest of Unix</a>
+				<p class="m-t5">A website by Sebastiaan. A massive Linux fanboy, runs Gentoo on his
+					ThinkPad. Absolutely based.</p>
+			</div>
+		</li>
+		<li>
+			<div><a href="https://nymphali.neocities.org" class="p-h3 m-t5">Nymphali</a>
+				<p class="m-t5">The website made by ■■■■■■, whoops Nymphali. They have an awesome
+					minimalist website that's just lovely.</p>
+			</div>
+		</li>
+		<li>
+			<div><a class="p-h3 m-t5" href="https://kristypixel.neocities.org">Kristy</a>
+				<p class="m-t5">Website made by Kristy. Very cute website, I love it! Keep up the
+					awesome work!</p>
+			</div>
+		</li>
+	</ul>
+</div>
+<div>
+	<p class="p-h2 mt-20 mb-10 bold">Neat webspaces</p>
+	<p class="m-t5" style="margin-left:10px;">Just very neat websites I found. Not necessarily by people I know.
+		I just thought it would be nice to share them here!</p>
+	<ul>
+		<li>
+			<div><a href="https://evillious.ylimegirl.com/" class="p-h3 m-t5">Evillious Chronicles fan guide</a>
+				<p class="m-t5">A VERY cool website made by Ylimegirl! They wrote a whole
+					website dedicated to Evillious Chronicles, which is a super
+					good Japanese light novel and vocaloid series!! Definitely look it up!</p>
+			</div>
+		</li>
+	</ul>
+</div>
\ No newline at end of file
diff --git a/web/blocks/intro.html b/web/blocks/intro.html
new file mode 100644
index 0000000..2aa37db
--- /dev/null
+++ b/web/blocks/intro.html
@@ -0,0 +1,18 @@
+<p class="p-h1">Welcome, internet surfer!</p>
+<div style="position:absolute; top:10px; right:5px;">
+	<p class="small">Please sign my guestbook</p>
+	<img src="/web/static/images/email3.gif" alt="" style="width:40px; position:absolute; bottom:0px; right:0px;">
+</div>
+<img src="/web/static/images/rin-len1.webp" alt="" height="230" style="float:right; margin-bottom: 10px;">
+<p class="content-text">
+Welcome to my webspace! Whether you stumbled across this page by accident
+or were linked here, you're more than welcome! This is my personal project that I like
+to work on! I was inspired by a couple friends of mine, please do check their webspaces
+out as well under "Galaxies" on the left side there!
+If you like this page, there is a lot more, so have a look around! You can also leave a
+nice message for me in the guestbook! There is no registration (unlike the rest of the "modern"
+internet) so nothing of that sort!
+That said, this website is my creative outlet and a way to introduce myself, so be kind please!
+Also its code is entirely open-source and can be found 
+<a href="https://dutchellie.nl/DutchEllie/proper-website-2">here</a> so if you like that sort 
+of stuff, be my guest it's cool!</p>
\ No newline at end of file
diff --git a/web/static/style.css b/web/static/style.css
index 4789913..130731f 100644
--- a/web/static/style.css
+++ b/web/static/style.css
@@ -46,6 +46,16 @@ body {
 	color:rgb(252, 230, 255)
 }
 
+.left {
+	float:left;
+	max-width: 250px;
+}
+
+.right {
+	float:right;
+	max-width: 614px;
+}
+
 .leftbar {
 	border: 3px solid;
 	border-radius: 4px;
@@ -57,6 +67,17 @@ body {
 	padding: 5px 0px;
 }
 
+.block {
+	border: 3px solid;
+	border-radius: 4px;
+	border-color: rgb(252, 230, 255);
+	background-color: rgb(54, 39, 48);
+	margin-bottom: 5px;
+	position: relative;
+	width: 614px;
+	padding: 10px;
+}
+
 .content {
 	border: 3px solid;
 	border-radius: 4px;