diff --git a/editor/.gitignore b/editor/.gitignore
new file mode 100644
index 0000000..5ef6a52
--- /dev/null
+++ b/editor/.gitignore
@@ -0,0 +1,41 @@
+# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
+
+# dependencies
+/node_modules
+/.pnp
+.pnp.*
+.yarn/*
+!.yarn/patches
+!.yarn/plugins
+!.yarn/releases
+!.yarn/versions
+
+# testing
+/coverage
+
+# next.js
+/.next/
+/out/
+
+# production
+/build
+
+# misc
+.DS_Store
+*.pem
+
+# debug
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+.pnpm-debug.log*
+
+# env files (can opt-in for committing if needed)
+.env*
+
+# vercel
+.vercel
+
+# typescript
+*.tsbuildinfo
+next-env.d.ts
diff --git a/editor/next.config.ts b/editor/next.config.ts
new file mode 100644
index 0000000..66e1566
--- /dev/null
+++ b/editor/next.config.ts
@@ -0,0 +1,8 @@
+import type { NextConfig } from "next";
+
+const nextConfig: NextConfig = {
+ /* config options here */
+ reactCompiler: true,
+};
+
+export default nextConfig;
diff --git a/editor/package.json b/editor/package.json
new file mode 100644
index 0000000..d9b0b83
--- /dev/null
+++ b/editor/package.json
@@ -0,0 +1,23 @@
+{
+ "name": "dusk-editor",
+ "version": "0.1.0",
+ "private": true,
+ "scripts": {
+ "start:dev": "next dev",
+ "build:prod": "next build",
+ "start:prod": "next start"
+ },
+ "dependencies": {
+ "next": "16.2.1",
+ "react": "19.2.4",
+ "react-dom": "19.2.4",
+ "sass": "^1.98.0"
+ },
+ "devDependencies": {
+ "@types/node": "^20",
+ "@types/react": "^19",
+ "@types/react-dom": "^19",
+ "babel-plugin-react-compiler": "1.0.0",
+ "typescript": "^5"
+ }
+}
diff --git a/editor/src/app/layout.tsx b/editor/src/app/layout.tsx
new file mode 100644
index 0000000..dadb6d5
--- /dev/null
+++ b/editor/src/app/layout.tsx
@@ -0,0 +1,23 @@
+import type { Metadata } from "next";
+import "@/styles/styles.scss";
+import Navbar from "@/components/Navbar/Navbar";
+
+export const metadata: Metadata = {
+ title: "Dusk Editor",
+ description: "Editor for the Dusk Game Engine",
+};
+
+export default function RootLayout({
+ children,
+}: Readonly<{
+ children: React.ReactNode;
+}>) {
+ return (
+
+
+
+ {children}
+
+
+ );
+}
diff --git a/editor/src/app/page.tsx b/editor/src/app/page.tsx
new file mode 100644
index 0000000..18b31b7
--- /dev/null
+++ b/editor/src/app/page.tsx
@@ -0,0 +1,9 @@
+import Link from "next/link";
+
+export default function Home() {
+ return (
+
+ Go to Texture Creator
+
+ );
+}
diff --git a/editor/src/app/texture-creator/page.tsx b/editor/src/app/texture-creator/page.tsx
new file mode 100644
index 0000000..1b91498
--- /dev/null
+++ b/editor/src/app/texture-creator/page.tsx
@@ -0,0 +1,17 @@
+'use client';
+import React, { createContext, useContext, useState } from "react";
+
+type TexturePageContextType = {
+};
+
+const TexturePageContext = createContext(undefined);
+
+const TextureCreatorPage: React.FC<{ children: React.ReactNode }> = (props) => {
+ return (
+
+
+
+ );
+}
+
+export default TextureCreatorPage;
\ No newline at end of file
diff --git a/editor/src/components/Navbar/Navbar.tsx b/editor/src/components/Navbar/Navbar.tsx
new file mode 100644
index 0000000..91406f1
--- /dev/null
+++ b/editor/src/components/Navbar/Navbar.tsx
@@ -0,0 +1,12 @@
+import React from 'react';
+import * as styles from './Navbar.module.scss';
+
+const Navbar:React.FC<{}> = (props) => {
+ return (
+
+ );
+}
+
+export default Navbar;
\ No newline at end of file
diff --git a/editor/src/objects/Typography/Typography.tsx b/editor/src/objects/Typography/Typography.tsx
new file mode 100644
index 0000000..7c9a74d
--- /dev/null
+++ b/editor/src/objects/Typography/Typography.tsx
@@ -0,0 +1,14 @@
+
+const Typography:React.FC<{
+ element?:string|React.JSXElementConstructor;
+}> = (props) => {
+ const Element = props.element || 'p';
+
+ return (
+
+ {props.children}
+
+ )
+};
+
+export default Typography;
\ No newline at end of file
diff --git a/editor/src/pages/TextureCreator/TextureCreator.tsx b/editor/src/pages/TextureCreator/TextureCreator.tsx
new file mode 100644
index 0000000..fc2e02c
--- /dev/null
+++ b/editor/src/pages/TextureCreator/TextureCreator.tsx
@@ -0,0 +1,17 @@
+
+import React, { createContext, useContext, useState } from "react";
+
+type TextureContextType = {
+};
+
+const TextureContext = createContext(undefined);
+
+const TextureCreator: React.FC<{ children: React.ReactNode }> = (props) => {
+ return (
+
+ {props.children}
+
+ );
+}
+
+export default TextureCreator;
\ No newline at end of file
diff --git a/editor/src/styles/elements/a.scss b/editor/src/styles/elements/a.scss
new file mode 100644
index 0000000..68e3e7d
--- /dev/null
+++ b/editor/src/styles/elements/a.scss
@@ -0,0 +1,4 @@
+a {
+ color: inherit;
+ text-decoration: none;
+}
\ No newline at end of file
diff --git a/editor/src/styles/elements/all.scss b/editor/src/styles/elements/all.scss
new file mode 100644
index 0000000..be0ab6c
--- /dev/null
+++ b/editor/src/styles/elements/all.scss
@@ -0,0 +1,3 @@
+* {
+ box-sizing: border-box;
+}
\ No newline at end of file
diff --git a/editor/src/styles/elements/body.scss b/editor/src/styles/elements/body.scss
new file mode 100644
index 0000000..367a047
--- /dev/null
+++ b/editor/src/styles/elements/body.scss
@@ -0,0 +1,8 @@
+body {
+ margin: 0;
+ padding: 0;
+ max-width: 100vw;
+ overflow-x: hidden;
+ font-size: 16px;
+ font-family: Arial, Helvetica, sans-serif;
+}
\ No newline at end of file
diff --git a/editor/src/styles/elements/html.scss b/editor/src/styles/elements/html.scss
new file mode 100644
index 0000000..e9c2cd4
--- /dev/null
+++ b/editor/src/styles/elements/html.scss
@@ -0,0 +1,6 @@
+html {
+ margin: 0;
+ padding: 0;
+ max-width: 100vw;
+ overflow-x: hidden;
+}
\ No newline at end of file
diff --git a/editor/src/styles/elements/root.scss b/editor/src/styles/elements/root.scss
new file mode 100644
index 0000000..2e1e952
--- /dev/null
+++ b/editor/src/styles/elements/root.scss
@@ -0,0 +1,3 @@
+:root {
+
+}
\ No newline at end of file
diff --git a/editor/src/styles/styles.scss b/editor/src/styles/styles.scss
new file mode 100644
index 0000000..94e282d
--- /dev/null
+++ b/editor/src/styles/styles.scss
@@ -0,0 +1,12 @@
+// Elements
+@use './elements/root.scss';
+@use './elements/all.scss';
+@use './elements/a.scss';
+@use './elements/html.scss';
+@use './elements/body.scss';
+
+// Objects
+
+// Components
+
+// Utilities
\ No newline at end of file
diff --git a/editor/tsconfig.json b/editor/tsconfig.json
new file mode 100644
index 0000000..cf9c65d
--- /dev/null
+++ b/editor/tsconfig.json
@@ -0,0 +1,34 @@
+{
+ "compilerOptions": {
+ "target": "ES2017",
+ "lib": ["dom", "dom.iterable", "esnext"],
+ "allowJs": true,
+ "skipLibCheck": true,
+ "strict": true,
+ "noEmit": true,
+ "esModuleInterop": true,
+ "module": "esnext",
+ "moduleResolution": "bundler",
+ "resolveJsonModule": true,
+ "isolatedModules": true,
+ "jsx": "react-jsx",
+ "incremental": true,
+ "plugins": [
+ {
+ "name": "next"
+ }
+ ],
+ "paths": {
+ "@/*": ["./src/*"]
+ }
+ },
+ "include": [
+ "next-env.d.ts",
+ "**/*.ts",
+ "**/*.tsx",
+ ".next/types/**/*.ts",
+ ".next/dev/types/**/*.ts",
+ "**/*.mts"
+ ],
+ "exclude": ["node_modules"]
+}
diff --git a/src/dusk/CMakeLists.txt b/src/dusk/CMakeLists.txt
index 834eb1e..3e5e165 100644
--- a/src/dusk/CMakeLists.txt
+++ b/src/dusk/CMakeLists.txt
@@ -40,9 +40,6 @@ target_sources(${DUSK_BINARY_TARGET_NAME}
main.c
)
-# Defs
-dusk_env_to_h(duskdefs.env duskdefs.h)
-
# Subdirs
add_subdirectory(assert)
add_subdirectory(asset)
diff --git a/src/dusk/duskdefs.env b/src/dusk/duskdefs.env
deleted file mode 100644
index 1629af9..0000000
--- a/src/dusk/duskdefs.env
+++ /dev/null
@@ -1,45 +0,0 @@
-# Copyright (c) 2025 Dominic Masters
-#
-# This software is released under the MIT License.
-# https://opensource.org/licenses/MIT
-
-ENTITY_DIR_SOUTH = 0
-ENTITY_DIR_WEST = 1
-ENTITY_DIR_EAST = 2
-ENTITY_DIR_NORTH = 3
-
-ENTITY_COUNT = 128
-
-ENTITY_TYPE_NULL = 0
-ENTITY_TYPE_PLAYER = 1
-ENTITY_TYPE_NPC = 2
-ENTITY_TYPE_COUNT = 3
-
-CHUNK_WIDTH = 16
-CHUNK_HEIGHT = 16
-CHUNK_DEPTH = 4
-# CHUNK_VERTEX_COUNT_MAX = QUAD_VERTEXES * CHUNK_WIDTH * CHUNK_HEIGHT * 4
-CHUNK_VERTEX_COUNT_MAX=6144
-CHUNK_MESH_COUNT_MAX = 14
-CHUNK_ENTITY_COUNT_MAX = 8
-
-TILE_WIDTH = 16.0
-TILE_HEIGHT = 16.0
-TILE_DEPTH = 16.0
-
-TILE_SHAPE_NULL = 0
-TILE_SHAPE_FLOOR = 1
-TILE_SHAPE_RAMP_SOUTH = 2
-TILE_SHAPE_RAMP_WEST = 3
-TILE_SHAPE_RAMP_EAST = 4
-TILE_SHAPE_RAMP_NORTH = 5
-TILE_SHAPE_RAMP_SOUTHWEST = 6
-TILE_SHAPE_RAMP_SOUTHEAST = 7
-TILE_SHAPE_RAMP_NORTHWEST = 8
-TILE_SHAPE_RAMP_NORTHEAST = 9
-
-RPG_CAMERA_FOV = 70
-RPG_CAMERA_PIXELS_PER_UNIT = 1.0
-RPG_CAMERA_Z_OFFSET = 24.0
-
-ASSET_LANG_CHUNK_CHAR_COUNT = 6144
\ No newline at end of file
diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt
index fc27de7..b0f3be2 100644
--- a/tools/CMakeLists.txt
+++ b/tools/CMakeLists.txt
@@ -3,5 +3,4 @@
# This software is released under the MIT License.
# https://opensource.org/licenses/MIT
-add_subdirectory(run_python)
-add_subdirectory(env_to_h)
\ No newline at end of file
+add_subdirectory(run_python)
\ No newline at end of file
diff --git a/tools/env_to_h/CMakeLists.txt b/tools/env_to_h/CMakeLists.txt
deleted file mode 100644
index b97b1a2..0000000
--- a/tools/env_to_h/CMakeLists.txt
+++ /dev/null
@@ -1,15 +0,0 @@
-# Copyright (c) 2026 Dominic Masters
-#
-# This software is released under the MIT License.
-# https://opensource.org/licenses/MIT
-
-function(dusk_env_to_h INPUT_PATH OUTPUT_NAME_RELATIVE)
- set(DUSK_DEFS_TARGET_NAME "DUSK_DEFS_${OUTPUT_NAME_RELATIVE}")
- dusk_run_python(
- ${DUSK_DEFS_TARGET_NAME}
- tools.env_to_h
- --env "${CMAKE_CURRENT_LIST_DIR}/${INPUT_PATH}"
- --output ${DUSK_GENERATED_HEADERS_DIR}/${OUTPUT_NAME_RELATIVE}
- )
- add_dependencies(${DUSK_LIBRARY_TARGET_NAME} ${DUSK_DEFS_TARGET_NAME})
-endfunction()
\ No newline at end of file
diff --git a/tools/env_to_h/__main__.py b/tools/env_to_h/__main__.py
deleted file mode 100644
index 88ab6a2..0000000
--- a/tools/env_to_h/__main__.py
+++ /dev/null
@@ -1,46 +0,0 @@
-import argparse
-import os
-from dotenv import load_dotenv, dotenv_values
-
-parser = argparse.ArgumentParser(description="Convert .env to .h defines")
-parser.add_argument("--env", required=True, help="Path to .env file")
-parser.add_argument("--output", required=True, help="Path to output .h file")
-args = parser.parse_args()
-
-# Load .env file
-load_dotenv(dotenv_path=args.env)
-fileDefs = dotenv_values(dotenv_path=args.env)
-
-outHeader = ""
-outHeader += "#include \"dusk.h\"\n\n"
-for key, value in fileDefs.items():
- # Determine type and print out appropriate C type define.
-
- # Integer
- try:
- asInt = int(value)
- outHeader += f"#define {key} {asInt}\n"
- continue
- except:
- pass
-
- # Float
- try:
- asFloat = float(value)
- outHeader += f"#define {key} {asFloat}f\n"
- continue
- except:
- pass
-
- # Boolean
- if value.lower() in ['true', 'false']:
- asBool = '1' if value.lower() == 'true' else '0'
- outHeader += f"#define {key} {asBool}\n"
- continue
-
- # String
- outHeader += f'#define {key} "{value}"\n'
-
-# Write to output file
-with open(args.output, 'w') as outFile:
- outFile.write(outHeader)
\ No newline at end of file