diff --git a/Cargo.lock b/Cargo.lock
index bc4f684..5dc6c13 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -82,9 +82,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
 
 [[package]]
 name = "cc"
-version = "1.2.0"
+version = "1.2.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1aeb932158bd710538c73702db6945cb68a8fb08c519e6e12706b94263b36db8"
+checksum = "fd9de9f2205d5ef3fd67e685b0df337994ddd4495e2a28d185500d0e1edfea47"
 dependencies = [
  "shlex",
 ]
diff --git a/sysdata/libraries/sunset_proto/src/lib.hb b/sysdata/libraries/sunset_proto/src/lib.hb
index 630d960..f5df7b6 100644
--- a/sysdata/libraries/sunset_proto/src/lib.hb
+++ b/sysdata/libraries/sunset_proto/src/lib.hb
@@ -14,18 +14,6 @@ server := @use("./server.hb")
 message := @use("./message.hb")
 permissions := @use("./permissions.hb")
 
-opaque := fn(i: uint): bool {
-	if i == 0 {
-		return true
-	}
-	return false
-}
-
-sleep := fn(): void {
-	i := 10000000
-	loop if opaque(i) break else i -= 1
-}
-
 $send_message := fn($Expr: type, kind: uint, msg: Expr, buffer_id: uint): void {
 	buffer.write(?Message(Expr), buffer_id, &@as(?Message(Expr), .(.(kind), msg)))
 }
diff --git a/sysdata/libraries/sunset_proto/src/server.hb b/sysdata/libraries/sunset_proto/src/server.hb
index 23e250b..6737a40 100644
--- a/sysdata/libraries/sunset_proto/src/server.hb
+++ b/sysdata/libraries/sunset_proto/src/server.hb
@@ -6,7 +6,7 @@ WindowServer := struct {
 	window_count: uint,
 	channel: Channel,
 	// ! replace this with a collection when we get an allocator
-	windows: [?WindowData; 10],
+	windows: [?Window; 10],
 	font: text.Font,
 }
 
@@ -42,34 +42,51 @@ incoming := fn(): bool {
 		// ! do inspection of requested props here
 		data := WindowData.(props.body, channel, permissions.default)
 		send_message(WindowData, message.ack, data, channel.client)
-		server.windows[server.window_count] = data
+		surface := new_window_decorations(data.props.dimensions)
+		put_filled_rect(surface, .(0, 0), data.props.dimensions + .(DECO_WIDTH, DECO_HEIGHT_TOP + DECO_HEIGHT_BOTTOM), DECO_COLOUR)
+		put_filled_rect(surface, .(0, 0), .(data.props.dimensions.x + DECO_WIDTH, DECO_HEIGHT_TOP), DECO_COLOUR)
+		put_text(surface, server.font, .(2, 1), .(0, 0, 0, 255), data.props.title)
+		server.windows[server.window_count] = .(data, surface)
 		server.window_count += 1
 	}
 	return true
 }
 
-render_clients := fn(screen: Surface): void {
-	// support one window for test case
+$DECO_WIDTH := 2
+$DECO_HEIGHT_TOP := 20
+$DECO_HEIGHT_BOTTOM := 1
+$DECO_COLOUR := Color.(100, 200, 255, 255)
+
+new_window_decorations := fn(dimensions: math.Vec2(uint)): Surface {
+	return new_surface(dimensions.x + DECO_WIDTH, dimensions.y + DECO_HEIGHT_TOP + DECO_HEIGHT_BOTTOM)
+}
+
+// ! compositor code. this currently disallows tearing.
+
+collect_frames := fn(): void {
 	window := server.windows[0]
 	if window == null {
 		return
 	}
-	header := recv_header(window.channel.server)
-	if header == null {
+	header := recv_header(window.data.channel.server)
+	if header == null | @unwrap(header).kind != message.frame_ready {
 		return
 	}
-	if header.kind != message.frame_ready {
+	send_header(message.ack, window.data.channel.client)
+	ptr := await_message(^Color, window.data.channel.server)
+	// ! weird compiler error
+	// if ptr.header.kind != message.ack {
+	// return
+	// }
+	put_surface(window.surface, Surface.(ptr.body, window.data.props.dimensions.x, window.data.props.dimensions.y, window.data.props.dimensions.x * window.data.props.dimensions.y), .(DECO_WIDTH / 2, DECO_HEIGHT_TOP), false)
+	send_header(message.ack, window.data.channel.client)
+}
+
+render_clients := fn(screen: Surface): void {
+	window := server.windows[0]
+	if window == null {
 		return
 	}
-	send_header(message.ack, window.channel.client)
-	ptr := await_message(^Color, window.channel.server)
-	if ptr.header.kind != message.ack {
-		return
-	}
-	put_surface(screen, .(ptr.body, window.props.dimensions.x, window.props.dimensions.y, window.props.dimensions.x * window.props.dimensions.y), window.props.position, false)
-	put_rect(screen, window.props.position - .(1, 1), window.props.dimensions + .(1, 1), .(255, 255, 255, 255))
-	put_filled_rect(screen, window.props.position - .(1, 21), .(window.props.dimensions.x + 2, 20), .(255, 255, 255, 255))
-	put_text(screen, server.font, window.props.position - .(-2, 20), .(0, 0, 0, 255), window.props.title)
+	put_surface(screen, window.surface, window.data.props.position, false)
 	sync(screen)
-	send_header(message.ack, window.channel.client)
 }
\ No newline at end of file
diff --git a/sysdata/programs/sunset_client/src/main.hb b/sysdata/programs/sunset_client/src/main.hb
index 8b46a12..a4cb5f6 100644
--- a/sysdata/programs/sunset_client/src/main.hb
+++ b/sysdata/programs/sunset_client/src/main.hb
@@ -2,9 +2,18 @@
 sunset := @use("../../../libraries/sunset_proto/src/lib.hb")
 render := @use("../../../libraries/render/src/lib.hb")
 
+bmp := @embed("../../../assets/mini.bmp")
+
 main := fn(): void {
 	sunset.client.find_server()
-	window := sunset.client.new(.(.(100, 100), .(700, 100), "Hello, World!\0"))
+
+	image := render.image.from(@bitcast(&bmp))
+	if image == null {
+		log.error("got no image\0")
+		return
+	}
+
+	window := sunset.client.new(.(.(100, 100), .(480, 200), "sunset windowing demo paddingpaddingpadding\0"))
 	if window == null {
 		log.error("got no window\0")
 		return
@@ -12,7 +21,7 @@ main := fn(): void {
 	x := 0
 	loop {
 		render.clear(window.surface, render.cyan)
-		render.put_filled_circle(window.surface, .(50 + x % window.data.props.dimensions.x, 50), 25, render.magenta)
+		render.put_surface(window.surface, image, .(image.width + x % window.data.props.dimensions.x, 20), false)
 		if sunset.client.send_frame(window) == false {
 			log.error("did not send frame\0")
 		}
diff --git a/sysdata/programs/sunset_server/src/main.hb b/sysdata/programs/sunset_server/src/main.hb
index f11694e..96f749e 100644
--- a/sysdata/programs/sunset_server/src/main.hb
+++ b/sysdata/programs/sunset_server/src/main.hb
@@ -5,6 +5,7 @@ main := fn(): void {
 	screen := render.init(true)
 	sunset.server.start()
 	loop if sunset.server.incoming() {
+		sunset.server.collect_frames()
 		sunset.server.render_clients(screen)
 	}
 }
\ No newline at end of file