diff --git a/site/docs/05-user-interface/01-html.mdx b/site/docs/05-user-interface/01-html.mdx
new file mode 100644
index 000000000..0d767f4d9
--- /dev/null
+++ b/site/docs/05-user-interface/01-html.mdx
@@ -0,0 +1,136 @@
+---
+title: HTML, CSS, and JavaScript
+slug: /html
+section: User Interface
+---
+
+HTML is super great at building UI's for the web, there are many popular front end frameworks and tool kits that will deliver highly polished UIs, so we recommend that first.
+
+Please consider html based first, but if the UI makes more sense in-canvas look to [screen elements](/docs/screen-elements).
+
+Advantages of HTML
+* Accessibility
+* Built in keyboard/pointer events
+* Powerful layout engine
+* CSS styling
+
+## Using HTML with Excalibur's Canvas
+
+A common technique for building UI wit canvas based games is overlaying HTML elements over the canvas.
+
+Check out this full demo [excaliburjs/sample-html](https://github.com/excaliburjs/sample-html)
+
+```html
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+When positioning elements over the Excalibur canvas, it is important to set `pointer-events: none` on elements you want to pass through to Excalibur. For elements you want to receive clicks/taps be sure to set `pointer-events: all`.
+
+
+## Positioning HTML Elements with Excalibur
+
+Excalibur provides an API for converting game positions in world/screen space to page coordinates.
+
+```typescript
+const engine = new ex.Engine({...});
+
+// Excalibur camera is centered at (100, 100)
+engine.currentScene.camera.pos = ex.vec(100, 100);
+
+// Finds the absolution page position that corresponds to the excalibur position (100, 100)
+const pagePositionFromWorld = engine.screen.worldToPageCoordinates(ex.vec(100, 100));
+
+// Finds the absolute page position that corresponds to the top left of the excalibur canvas, screen (0, 0)
+const pagePositionFromScreen = engine.screen.screenToPageCoordinates(ex.vec(0, 0));
+
+// Use pagePositions in page coordinates to position HTML elements
+// Setting CSS variables is a convenient way to do this
+document.documentElement.style.setProperty('--pointer-x', evt.pagePos.x.toString() + 'px');
+document.documentElement.style.setProperty('--pointer-y', evt.pagePos.y.toString() + 'px');
+```
+
+Then to position any elements reference the CSS variables in your CSS
+
+```css
+.menu {
+ position: absolute;
+ /* position menu on click */
+ left: var(--pointer-x);
+ top: var(--pointer-y);
+}
+```
+
+## Scaling between CSS & Excalibur Pixels
+
+It is useful in CSS to scale your elements to match the Excalibur game canvas, this is done by calculating the ratio between between Excalibur pixels and browser pixels.
+
+```typescript
+const calculateExPixelConversion = (screen: ex.Screen) => {
+ const origin = screen.worldToPageCoordinates(Vector.Zero);
+ const singlePixel = screen.worldToPageCoordinates(vec(1, 0)).sub(origin);
+ const pixelConversion = singlePixel.x;
+ document.documentElement.style.setProperty('--pixel-conversion', pixelConversion.toString());
+}
+
+// Update pixel conversion on resize
+game.screen.events.on('resize', () => calculateExPixelConversion(game.screen));
+
+// Set initial conversion
+game.start().then(() => {
+ calculateExPixelConversion(game.screen);
+});
+```
+
+
+One of the lowest effort options is to apply a CSS transform to the container of your HTML UI based on the excalibur pixel conversion.
+
+```css
+.excalibur-scale {
+ /* transform from the top left of the element */
+ transform-origin: 0 0;
+ /* scale the ui */
+ transform: scale(var(--pixel-conversion), var(--pixel-conversion));
+}
+```
+
+Another option is to manually apply conversion to specific CSS properties.
+
+```css
+.text {
+ /* Convert to excalibur 24px from page 24px */
+ font-size: calc(24px * var(--pixel-conversion));
+}
+```
\ No newline at end of file
diff --git a/site/docs/05-user-interface/02-screen-elements.mdx b/site/docs/05-user-interface/02-screen-elements.mdx
new file mode 100644
index 000000000..0f15ab45f
--- /dev/null
+++ b/site/docs/05-user-interface/02-screen-elements.mdx
@@ -0,0 +1,52 @@
+---
+title: Screen Elements
+slug: /screen-elements
+section: User Interface
+---
+
+Please consider [html based first](#html-based-ui) but if the UI makes more sense in-canvas look to [screen elements](#screen-elements).
+
+## Screen Elements
+
+In Excalibur, if you want to display something like a HUD element or UI element inside the Excalibur canvas, you can create an instance of [[ScreenElement]]. A screen element has the following semantics that differ from a regular [actor](/docs/actors):
+
+- They automatically [capture pointer events](/docs/input#actor-pointer-events)
+- They do not participate in collisions
+- They appear above all "normal" actors in a [scene](/docs/scenes)
+- Invoking [[ScreenElement.contains]] will check against [screen coordinates](/docs/engine#screen-coordinates) by default.
+
+Other than that, they are the same as normal actors where you can assign drawings, perform actions, etc.
+
+```ts
+import * as ex from 'excalibur'
+import Resources from './resources'
+
+class StartButton extends ex.ScreenElement {
+ constructor() {
+ super({
+ x: 50,
+ y: 50,
+ })
+ }
+
+ onInitialize() {
+ this.graphics.add('idle', Resources.StartButtonBackground)
+ this.graphics.add('hover', Resources.StartButtonHovered)
+
+ this.on('pointerup', () => {
+ alert("I've been clicked")
+ })
+
+ this.on('pointerenter', () => {
+ this.graphics.show('hover')
+ })
+
+ this.on('pointerleave', () => {
+ this.graphics.show('idle')
+ })
+ }
+}
+
+game.add(new StartButton())
+game.start()
+```
\ No newline at end of file
diff --git a/site/docs/05-user-interface/03-web-fonts.mdx b/site/docs/05-user-interface/03-web-fonts.mdx
new file mode 100644
index 000000000..66e3e3422
--- /dev/null
+++ b/site/docs/05-user-interface/03-web-fonts.mdx
@@ -0,0 +1,34 @@
+---
+title: Web Fonts
+slug: /web-fonts
+section: User Interface
+---
+
+When building UIs in order to prevent a flash of unstyled content (a moment of default font/styling before the font loads) Excalibur has a built in resource type to help with that.
+
+## Using FontSource
+
+Using a [[FontSource]] will ensure the font is loaded and the font face is ready before the game starts!
+
+```typescript
+const fontSource = new ex.FontSource('/my-font.ttf', 'My Font')
+loader.addResource(fontSource)
+
+game.start(loader).then(() => {
+ const font = fontSource.toFont() // returns ex.Font
+})
+```
+
+Font options can be defined either at the source or at the `toFont()` call. If defined in both, `toFont(options)` will
+override the options in the [[FontSource]].
+
+```typescript
+const fontSource = new ex.FontSource('/my-font.ttf', 'My Font', {
+ filtering: ex.ImageFiltering.Pixel,
+ size: 16, // set a default size
+})
+const font = fontSource.toFont({
+ // override just the size
+ size: 20,
+})
+```
\ No newline at end of file
diff --git a/site/docs/05-user-interface/_category_.json b/site/docs/05-user-interface/_category_.json
new file mode 100644
index 000000000..7d34b31bb
--- /dev/null
+++ b/site/docs/05-user-interface/_category_.json
@@ -0,0 +1,8 @@
+{
+ "label": "User Interface",
+ "position": 5,
+ "link": {
+ "type": "generated-index",
+ "description": "5 minutes to learn the most important Excalibur.js concepts."
+ }
+}