diff --git a/src/menu.go b/src/menu.go
new file mode 100644
index 0000000..b828ae4
--- /dev/null
+++ b/src/menu.go
@@ -0,0 +1,77 @@
+package main
+
+import "github.com/maxence-charriere/go-app/v9/pkg/app"
+
+type menu struct {
+	app.Compo
+
+	Iclass          string
+	updateAvailable bool
+
+	IpaneWidth    int
+	OnClickButton func(page string)
+}
+
+func newMenu() *menu {
+	return &menu{}
+}
+
+func (m *menu) PaneWidth(px int) *menu {
+	if px > 0 {
+		m.IpaneWidth = px
+	}
+	return m
+}
+
+func (m *menu) Class(v string) *menu {
+	m.Iclass = app.AppendClass(m.Iclass, v)
+	return m
+}
+
+func (m *menu) OnAppUpdate(ctx app.Context) {
+	m.updateAvailable = ctx.AppUpdateAvailable()
+}
+
+func (m *menu) Render() app.UI {
+	return app.Div().
+		Class("left").
+		Class("block").
+		Class("leftbarblock-nop").
+		Class("navbar").
+		Body(
+			app.Ul().Body(
+				app.Li().Body(
+					app.A().Href("/").Text("Home"),
+				),
+				app.Li().Body(
+					app.A().Href("/about").Text("About"),
+				),
+				app.Li().Body(
+					app.A().Href("/galaxies").Text("Galaxies"),
+				),
+				app.Li().Body(
+					app.A().Href("/music").Text("Music"),
+				),
+				// Disabled for now since there are none anyway
+				app.Li().Body(
+					app.A().Href("/blog").Text("Blog"),
+				).Style("display", "none"),
+			),
+			app.If(m.updateAvailable,
+				app.Div().Body(
+					app.Img().
+						Src("/web/static/images/hot1.gif").
+						Class("update-img"),
+					app.Span().
+						Text("Update available! Click here to update!").
+						Class("update-text"),
+				).
+					Class("update-div").
+					OnClick(m.onUpdateClick),
+			),
+		)
+}
+
+func (m *menu) onUpdateClick(ctx app.Context, e app.Event) {
+	ctx.Reload()
+}
diff --git a/src/navbar.go b/src/navbar.go
index a320e89..8e38008 100644
--- a/src/navbar.go
+++ b/src/navbar.go
@@ -1,6 +1,9 @@
 package main
 
-import "github.com/maxence-charriere/go-app/v9/pkg/app"
+import (
+	"dutchellie.nl/DutchEllie/proper-website-2/ui"
+	"github.com/maxence-charriere/go-app/v9/pkg/app"
+)
 
 type navbar struct {
 	app.Compo
@@ -14,38 +17,14 @@ func (n *navbar) OnAppUpdate(ctx app.Context) {
 }
 
 func (n *navbar) Render() app.UI {
-	return app.Div().Body(
-		app.Ul().Body(
-			app.Li().Body(
-				app.A().Href("/").Text("Home"),
-			),
-			app.Li().Body(
-				app.A().Href("/about").Text("About"),
-			),
-			app.Li().Body(
-				app.A().Href("/galaxies").Text("Galaxies"),
-			),
-			app.Li().Body(
-				app.A().Href("/music").Text("Music"),
-			),
-			// Disabled for now since there are none anyway
-			app.Li().Body(
-				app.A().Href("/blog").Text("Blog"),
-			).Style("display", "none"),
-		),
-		app.If(n.updateAvailable,
-			app.Div().Body(
-				app.Img().
-					Src("/web/static/images/hot1.gif").
-					Class("update-img"),
-				app.Span().
-					Text("Update available! Click here to update!").
-					Class("update-text"),
-			).
-				Class("update-div").
-				OnClick(n.onUpdateClick),
-		),
-	).Class("navbar")
+	return ui.Menu().
+		PaneWidth(250).
+		Menu(
+			newMenu(),
+		).
+		HamburgerMenu(
+			newMenu(),
+		)
 }
 
 func (n *navbar) onUpdateClick(ctx app.Context, e app.Event) {
diff --git a/ui/menu.go b/ui/menu.go
new file mode 100644
index 0000000..c508f8a
--- /dev/null
+++ b/ui/menu.go
@@ -0,0 +1,171 @@
+package ui
+
+import (
+	"strconv"
+
+	"github.com/maxence-charriere/go-app/v9/pkg/app"
+)
+
+type IMenu interface {
+	app.UI
+
+	ID(v string) IMenu
+	Class(v string) IMenu
+	PaneWidth(px int) IMenu
+	HamburgerButton(v app.UI) IMenu
+	HamburgerMenu(v ...app.UI) IMenu
+	Menu(v ...app.UI) IMenu
+}
+
+func Menu() IMenu {
+	return &menu{}
+}
+
+type menu struct {
+	app.Compo
+
+	Iid              string
+	Iclass           string
+	Ipanewidth       int
+	IhamburgerButton app.UI
+	IhamburgerMenu   []app.UI
+	Imenu            []app.UI
+
+	hideMenu          bool
+	showHamburgerMenu bool
+	width             int
+}
+
+func (m *menu) ID(v string) IMenu {
+	m.Iid = v
+	return m
+}
+
+func (m *menu) Class(v string) IMenu {
+	m.Iclass = app.AppendClass(m.Iclass, v)
+	return m
+}
+
+func (m *menu) PaneWidth(px int) IMenu {
+	if px > 0 {
+		m.Ipanewidth = px
+	}
+	return m
+}
+
+func (m *menu) HamburgerButton(v app.UI) IMenu {
+	b := app.FilterUIElems(v)
+	if len(b) != 0 {
+		m.IhamburgerButton = b[0]
+	}
+	return m
+}
+
+func (m *menu) HamburgerMenu(v ...app.UI) IMenu {
+	m.IhamburgerMenu = app.FilterUIElems(v...)
+	return m
+}
+
+func (m *menu) Menu(v ...app.UI) IMenu {
+	m.Imenu = app.FilterUIElems(v...)
+	return m
+}
+
+func (m *menu) OnPreRender(ctx app.Context) {
+	m.refresh(ctx)
+}
+
+func (m *menu) OnMount(ctx app.Context) {
+	m.refresh(ctx)
+}
+
+func (m *menu) OnResize(ctx app.Context) {
+	m.refresh(ctx)
+}
+
+func (m *menu) OnUpdate(ctx app.Context) {
+	m.refresh(ctx)
+}
+
+func (m *menu) Render() app.UI {
+	visible := func(v bool) string {
+		if v {
+			return "block"
+		}
+		return "none"
+	}
+
+	return app.Div().
+		ID(m.Iid).
+		Class(m.Iclass).
+		Body(
+			app.Div().
+				//Style("display", "flex").
+				Style("width", "100%").
+				Style("height", "100%").
+				Style("overflow", "hidden").
+				Body(
+					app.Div().
+						Style("position", "relative").
+						Style("display", visible(!m.hideMenu)).
+						Style("flex-shrink", "0").
+						Style("flex-basis", pxToString(m.Ipanewidth)).
+						Style("overflow", "hidden").
+						Body(m.Imenu...),
+				),
+			app.Div().
+				Style("display", visible(m.hideMenu && len(m.IhamburgerMenu) != 0)).
+				Style("position", "absolute").
+				Style("top", "0").
+				Style("left", "0").
+				Style("cursor", "pointer").
+				OnClick(m.onHamburgerButtonClick).
+				Body(
+					app.If(m.IhamburgerButton == nil,
+						app.Div().
+							Class("goapp-shell-hamburger-button-default").
+							Text("☰"),
+					),
+				),
+			app.Div().
+				Style("display", visible(m.hideMenu && m.showHamburgerMenu)).
+				Style("position", "absolute").
+				Style("top", "0").
+				Style("left", "0").
+				Style("width", "100%").
+				Style("height", "100%").
+				Style("overflow", "hidden").
+				OnClick(m.hideHamburgerMenu).
+				Body(m.IhamburgerMenu...),
+		)
+}
+
+func (m *menu) refresh(ctx app.Context) {
+	w, _ := app.Window().Size()
+	hideMenu := true
+	if w >= 914 {
+		hideMenu = false
+	}
+
+	if hideMenu != m.hideMenu ||
+		w != m.width {
+		m.hideMenu = hideMenu
+		m.width = w
+
+		ctx.Defer(func(app.Context) {
+			m.ResizeContent()
+		})
+	}
+}
+
+func pxToString(px int) string {
+	return strconv.Itoa(px) + "px"
+}
+
+func (m *menu) onHamburgerButtonClick(ctx app.Context, e app.Event) {
+	m.showHamburgerMenu = true
+}
+
+func (m *menu) hideHamburgerMenu(ctx app.Context, e app.Event) {
+	m.showHamburgerMenu = false
+}
diff --git a/web/static/style.css b/web/static/style.css
index 40e7bc4..c9e5b47 100644
--- a/web/static/style.css
+++ b/web/static/style.css
@@ -69,14 +69,6 @@ body {
 }
 
 .navbar {
-	border: 3px solid;
-	border-radius: 4px;
-	border-color: rgb(252, 230, 255);
-	margin-bottom: 5px;
-	background-color: rgb(54, 39, 48);
-	position: relative;
-	float:left;
-	width: 250px;
 	text-decoration: none;
 	list-style: none;
 }
@@ -88,7 +80,7 @@ body {
 
 .left {
 	float:left;
-	max-width: 250px;
+	max-width: 256px;
 }
 
 .right {
@@ -116,6 +108,11 @@ body {
 	position: relative;
 }
 
+.leftbarblock-nop {
+	float:left;
+	width: 250px;
+}
+
 .leftbarblock {
 	float:left;
 	width: 250px;