diff --git a/assets/files.png b/assets/files.png
new file mode 100644
index 0000000..ae08dc4
Binary files /dev/null and b/assets/files.png differ
diff --git a/assets/logo.png b/assets/logo.png
new file mode 100644
index 0000000..2793ec6
Binary files /dev/null and b/assets/logo.png differ
diff --git a/assets/shadow_dog.png b/assets/shadow_dog.png
new file mode 100644
index 0000000..220b7b7
Binary files /dev/null and b/assets/shadow_dog.png differ
diff --git a/assets/sprite_template.png b/assets/sprite_template.png
new file mode 100644
index 0000000..516df4d
Binary files /dev/null and b/assets/sprite_template.png differ
diff --git a/index.html b/index.html
index 92c07a7..73b31c4 100644
--- a/index.html
+++ b/index.html
@@ -3,16 +3,21 @@
 
   
     
-    TS Electron Template
+    Desktop Daemon
+    
+
+    
   
   
-    
-    Versions:
-    Node.js - 
-    Chromium - 
-    Electron - 
-
-    
+    
     
   
 
diff --git a/src/constants.ts b/src/constants.ts
new file mode 100644
index 0000000..0efa98b
--- /dev/null
+++ b/src/constants.ts
@@ -0,0 +1 @@
+export const FRAME_RATE = 10;
diff --git a/src/main.ts b/src/main.ts
index 7847c13..b716803 100644
--- a/src/main.ts
+++ b/src/main.ts
@@ -1,14 +1,29 @@
-import {app, BrowserWindow} from "electron";
+import {app, BrowserWindow, screen} from "electron";
 import * as path from "path";
 
 // Window factory
 function createWindow() {
+  const primaryDisplay = screen.getPrimaryDisplay();
+  const height = 250;
+
   const window = new BrowserWindow({
-    height: 600,
-    width: 800,
+    x: 0,
+    y: primaryDisplay.workArea.height - height,
+    height: height,
+    width: primaryDisplay.size.width,
+    frame: false,
+    transparent: true,
+    roundedCorners: false,
+    resizable: false,
+    fullscreen: false,
+    alwaysOnTop: false,
+    icon: path.join(__dirname, "../assets/logo.png"),
+    title: 'Desktop Daemon',
     webPreferences: {
+      nodeIntegration:  true,
+      contextIsolation: false,
       preload: path.join(__dirname, "preload.js")
-    }
+    },
   });
 
   window.loadFile(path.join(__dirname, "../index.html"));
diff --git a/src/renderer.ts b/src/renderer.ts
index 66b947d..6aaab8c 100644
--- a/src/renderer.ts
+++ b/src/renderer.ts
@@ -1,4 +1,34 @@
-/*
-This file is imported by index.html, you can put any code you want to run afer
-page load, here.
- */
+const {FRAME_RATE} = require('./dist/constants.js');
+const {UnitController} = require('./dist/unit-controller.js');
+const {StaticSprite} = require('./dist/sprites.js');
+const {sleep} = require('./dist/utils.js');
+
+const canvas = document.getElementById('canvas');
+const ctx = canvas.getContext('2d');
+const screenHeight = window.innerHeight;
+const screenWidth = window.innerWidth;
+
+canvas.width = screenWidth;
+canvas.height = screenHeight;
+
+function clearScreen() { ctx.clearRect(0, 0, screenWidth, screenHeight); }
+
+const file = new StaticSprite(ctx, './assets/files.png', [1, 0], 0.5);
+const sprite = new UnitController(ctx, {
+		spritesheetSrc: './assets/shadow_dog.png',
+		spriteAnimations: ['idle'],
+		spriteScale: 0.5,
+		spriteWidth: 575,
+		spriteHeight: 523,
+		spriteFrames: 7,
+	});
+
+(async () => {
+	sprite.vel = [20, 0];
+	while(true) {
+		clearScreen();
+		file.render(25, 25);
+		sprite.tick();
+		await sleep(1000 / FRAME_RATE);
+	}
+})();
diff --git a/src/sprites.ts b/src/sprites.ts
new file mode 100644
index 0000000..b815389
--- /dev/null
+++ b/src/sprites.ts
@@ -0,0 +1,58 @@
+export class AnimatedSprite {
+	private animation = '';
+	private animationIndex = -1;
+	private frame = -1;
+	private spriteSheet!: HTMLImageElement;
+
+	constructor(private ctx: CanvasRenderingContext2D,
+				public spritesheetSrc: string,
+				public spriteAnimations: string[],
+				public spriteScale = 1,
+				public spriteWidth = 100,
+				public spriteHeight = 100,
+				public spriteFrames = 10,
+	) {
+		this.spriteSheet = new Image();
+		this.spriteSheet.src = this.spritesheetSrc;
+	}
+
+	render(x: number, y: number, animation: string = this.animation) {
+		if(this.animation != animation) {
+			this.frame = 0;
+			this.animation = animation;
+			this.animationIndex = this.spriteAnimations.findIndex((a) => a == animation);
+		} else {
+			this.frame++;
+			if(this.frame >= this.spriteFrames) this.frame = 0;
+		}
+
+		this.ctx.drawImage(this.spriteSheet,
+			this.frame * this.spriteWidth, this.animationIndex * this.spriteHeight,
+			this.spriteWidth, this.spriteHeight,
+			x, this.ctx.canvas.height - (this.spriteHeight * this.spriteScale + y),
+			this.spriteWidth * this.spriteScale, this.spriteHeight * this.spriteScale);
+	}
+}
+
+export class StaticSprite {
+	private spriteSheet!: HTMLImageElement;
+
+	constructor(private ctx: CanvasRenderingContext2D,
+				public spritesheetSrc: string,
+				public sprite: [number, number],
+				public spriteScale = 1,
+				public spriteWidth = 100,
+				public spriteHeight = 100,
+	) {
+		this.spriteSheet = new Image();
+		this.spriteSheet.src = this.spritesheetSrc;
+	}
+
+	render(x: number, y: number) {
+		this.ctx.drawImage(this.spriteSheet,
+			this.sprite[0] * this.spriteWidth, this.sprite[1] * this.spriteHeight,
+			this.spriteWidth, this.spriteHeight,
+			x, this.ctx.canvas.height - (this.spriteHeight * this.spriteScale + y),
+			this.spriteWidth * this.spriteScale, this.spriteHeight * this.spriteScale);
+	}
+}
diff --git a/src/unit-controller.ts b/src/unit-controller.ts
new file mode 100644
index 0000000..08add2d
--- /dev/null
+++ b/src/unit-controller.ts
@@ -0,0 +1,35 @@
+// const {FRAME_RATE} = require('./dist/constants.js');
+const {AnimatedSprite} = require('./sprites.js');
+
+// TODO - Move to import
+const FRAME_RATE = 10;
+
+export type SpriteOptions = {
+	spritesheetSrc: string,
+	spriteAnimations: string[],
+	spriteWidth?: number,
+	spriteHeight?: number,
+	spriteFrames?: number,
+	scale?: number,
+}
+
+export class UnitController {
+	private sprite!: typeof AnimatedSprite;
+
+	public pos = [0, 0];
+	public vel = [0, 0];
+
+	constructor(private ctx: CanvasRenderingContext2D,
+				private spriteOptions: SpriteOptions,
+	) {
+		this.sprite = new AnimatedSprite(ctx, ...Object.values(spriteOptions));
+	}
+
+	tick() {
+		this.pos = [this.pos[0] + (this.vel[0] / FRAME_RATE), this.pos[1] + (this.vel[1] / FRAME_RATE)];
+		let animation = 'idle';
+		// if(this.vel[0] < 0) animation = 'left';
+		// if(this.vel[0] > 0) animation = 'right';
+		this.sprite.render(this.pos[0], this.pos[1], animation);
+	}
+}
diff --git a/src/utils.ts b/src/utils.ts
new file mode 100644
index 0000000..1fc455e
--- /dev/null
+++ b/src/utils.ts
@@ -0,0 +1,3 @@
+export function sleep(ms: number) {
+	return new Promise(res => setTimeout(res, ms));
+}
diff --git a/tsconfig.json b/tsconfig.json
index 302b714..15a8cc0 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -1,14 +1,15 @@
 {
   "compilerOptions": {
+    "target": "ES2022",
     "module": "commonjs",
     "noImplicitAny": true,
+    "esModuleInterop": true,
     "sourceMap": true,
     "outDir": "dist",
     "baseUrl": ".",
     "paths": {
       "*": ["node_modules/*"]
-    },
-    "lib": ["dom", "es2015"]
+    }
   },
   "include": [
     "src/**/*"