From ab65fd528bd9a09ee03d8b9857d1d9b204bb0636 Mon Sep 17 00:00:00 2001
From: snekxs <26660858+snekxs@users.noreply.github.com>
Date: Sat, 1 Aug 2026 14:32:20 -0600
Subject: [PATCH 001/284] feat: make dev a public control panel
---
.env.example | 3 -
README.md | 20 +-
control-app.html | 18 --
control.html | 18 --
demo.html | 32 ---
functions/_middleware.js | 52 ----
functions/api/license/activate.js | 60 -----
index.html | 31 +--
public/_routes.json | 5 -
public/apple-touch-icon.png | Bin 8791 -> 0 bytes
public/favicon-32.png | Bin 1704 -> 0 bytes
public/favicon-dark.svg | 7 -
public/favicon.png | Bin 29398 -> 0 bytes
public/icon-512.png | Bin 29398 -> 0 bytes
public/mouse-preview.svg | 38 ---
public/og-dark.png | Bin 1833360 -> 0 bytes
public/og-dark.svg | 15 --
public/og-preview-dark.png | Bin 1725610 -> 0 bytes
public/og.png | Bin 2372156 -> 0 bytes
public/robots.txt | 4 -
public/sitemap.xml | 15 --
public/superlight-2c-black.png | Bin 1509418 -> 0 bytes
public/x-banner-v2.png | Bin 379972 -> 0 bytes
public/x-banner-v2.svg | 38 ---
public/x-banner-v3.png | Bin 293025 -> 0 bytes
public/x-banner-v3.svg | 20 --
public/x-banner.png | Bin 86457 -> 0 bytes
public/x-profile.png | Bin 14295 -> 0 bytes
public/x-profile.svg | 9 -
src/control-gate.ts | 67 -----
src/control.ts | 2 +-
src/demo.ts | 206 --------------
src/main.ts | 432 ------------------------------
src/styles.css | 421 -----------------------------
vite.config.ts | 8 -
35 files changed, 10 insertions(+), 1511 deletions(-)
delete mode 100644 .env.example
delete mode 100644 control-app.html
delete mode 100644 control.html
delete mode 100644 demo.html
delete mode 100644 functions/_middleware.js
delete mode 100644 functions/api/license/activate.js
delete mode 100644 public/_routes.json
delete mode 100644 public/apple-touch-icon.png
delete mode 100644 public/favicon-32.png
delete mode 100644 public/favicon-dark.svg
delete mode 100644 public/favicon.png
delete mode 100644 public/icon-512.png
delete mode 100644 public/mouse-preview.svg
delete mode 100644 public/og-dark.png
delete mode 100644 public/og-dark.svg
delete mode 100644 public/og-preview-dark.png
delete mode 100644 public/og.png
delete mode 100644 public/robots.txt
delete mode 100644 public/sitemap.xml
delete mode 100644 public/superlight-2c-black.png
delete mode 100644 public/x-banner-v2.png
delete mode 100644 public/x-banner-v2.svg
delete mode 100644 public/x-banner-v3.png
delete mode 100644 public/x-banner-v3.svg
delete mode 100644 public/x-banner.png
delete mode 100644 public/x-profile.png
delete mode 100644 public/x-profile.svg
delete mode 100644 src/control-gate.ts
delete mode 100644 src/demo.ts
delete mode 100644 src/main.ts
delete mode 100644 src/styles.css
diff --git a/.env.example b/.env.example
deleted file mode 100644
index 14559dd..0000000
--- a/.env.example
+++ /dev/null
@@ -1,3 +0,0 @@
-# Cloudflare Pages Functions runtime bindings.
-SUPABASE_URL=https://your-project.supabase.co
-SUPABASE_SERVICE_ROLE_KEY=configure-as-a-cloudflare-secret
diff --git a/README.md b/README.md
index bf79f9d..d29132f 100644
--- a/README.md
+++ b/README.md
@@ -1,20 +1,8 @@
# OpenMouse
-OpenMouse is a website for managing supported gaming mice in one place.
+OpenMouse is a browser-based control panel for supported gaming mice.
-The goal is to let you connect a mouse, view its information, and change settings
-like DPI and polling rate without installing a different app for every brand.
+Connect a mouse, view its information, and change supported settings such as DPI
+and polling rate without installing a different app for every brand.
-The website currently includes an interactive preview of the planned interface.
-It is only a demo and does not make changes to a real mouse.
-
-## Future plans
-
-OpenMouse will begin with a small number of supported mice and grow one device at
-a time. Future versions are planned to include verified device controls, more
-supported models, and an offline-ready app.
-
-OpenMouse is planned to become open-source software, but it is not currently
-licensed for use, modification, or redistribution. A license will be selected
-before the project's full release. You can follow its progress, suggest a
-mouse, or share feedback through GitHub and the OpenMouse Discord.
+This branch is deployed as the public development control panel.
diff --git a/control-app.html b/control-app.html
deleted file mode 100644
index 89d6912..0000000
--- a/control-app.html
+++ /dev/null
@@ -1,18 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
- OpenMouse Control
-
-
-
-
-
-
diff --git a/control.html b/control.html
deleted file mode 100644
index a6e2a28..0000000
--- a/control.html
+++ /dev/null
@@ -1,18 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
- OpenMouse License
-
-
-
-
-
-
diff --git a/demo.html b/demo.html
deleted file mode 100644
index 221a6ca..0000000
--- a/demo.html
+++ /dev/null
@@ -1,32 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- OpenMouse Interface Preview
-
-
-
-
-
-
diff --git a/functions/_middleware.js b/functions/_middleware.js
deleted file mode 100644
index 35b130e..0000000
--- a/functions/_middleware.js
+++ /dev/null
@@ -1,52 +0,0 @@
-const COOKIE_NAME = "om_license_session";
-
-function readCookie(request, name) {
- const cookies = request.headers.get("Cookie") ?? "";
- for (const part of cookies.split(";")) {
- const [key, ...value] = part.trim().split("=");
- if (key === name) return value.join("=");
- }
- return null;
-}
-
-async function sha256(value) {
- const digest = await crypto.subtle.digest("SHA-256", new TextEncoder().encode(value));
- return [...new Uint8Array(digest)].map((byte) => byte.toString(16).padStart(2, "0")).join("");
-}
-
-export async function onRequest({ request, env, next }) {
- const url = new URL(request.url);
- if (url.pathname.startsWith("/api/license/")) return next();
-
- const sessionToken = readCookie(request, COOKIE_NAME);
- const supabaseUrl = env.SUPABASE_URL || env.VITE_SUPABASE_URL;
- const serviceKey = env.SUPABASE_SERVICE_ROLE_KEY;
- let allowed = false;
-
- if (sessionToken && supabaseUrl && serviceKey) {
- const response = await fetch(`${supabaseUrl}/rest/v1/rpc/validate_license_session`, {
- method: "POST",
- headers: {
- apikey: serviceKey,
- Authorization: `Bearer ${serviceKey}`,
- "Content-Type": "application/json",
- },
- body: JSON.stringify({ session_hash: await sha256(sessionToken) }),
- });
- if (response.ok) {
- const result = await response.json();
- allowed = result?.allowed === true;
- }
- }
-
- if (!allowed) {
- if (url.pathname.startsWith("/protected-assets/")) return new Response("Not found", { status: 404 });
- return Response.redirect(new URL("/control", url), 302);
- }
-
- const response = await next();
- const protectedResponse = new Response(response.body, response);
- protectedResponse.headers.set("Cache-Control", "private, no-store");
- protectedResponse.headers.set("X-Content-Type-Options", "nosniff");
- return protectedResponse;
-}
diff --git a/functions/api/license/activate.js b/functions/api/license/activate.js
deleted file mode 100644
index 503d349..0000000
--- a/functions/api/license/activate.js
+++ /dev/null
@@ -1,60 +0,0 @@
-const COOKIE_NAME = "om_license_session";
-
-function json(body, status = 200, headers = {}) {
- return new Response(JSON.stringify(body), {
- status,
- headers: { "Content-Type": "application/json", "Cache-Control": "no-store", ...headers },
- });
-}
-
-function toBase64Url(bytes) {
- let binary = "";
- for (const byte of bytes) binary += String.fromCharCode(byte);
- return btoa(binary).replaceAll("+", "-").replaceAll("/", "_").replaceAll("=", "");
-}
-
-async function sha256(value) {
- const digest = await crypto.subtle.digest("SHA-256", new TextEncoder().encode(value));
- return [...new Uint8Array(digest)].map((byte) => byte.toString(16).padStart(2, "0")).join("");
-}
-
-export async function onRequest({ request, env }) {
- if (request.method !== "POST") {
- return json({ message: "Method not allowed." }, 405, { Allow: "POST" });
- }
- const supabaseUrl = env.SUPABASE_URL || env.VITE_SUPABASE_URL;
- const serviceKey = env.SUPABASE_SERVICE_ROLE_KEY;
- if (!supabaseUrl || !serviceKey) return json({ message: "License service is not configured." }, 503);
-
- let body;
- try {
- body = await request.json();
- } catch {
- return json({ message: "Invalid request." }, 400);
- }
- const licenseCode = typeof body.licenseCode === "string" ? body.licenseCode.trim() : "";
- if (licenseCode.length < 12 || licenseCode.length > 200) {
- return json({ message: "Invalid license code." }, 400);
- }
-
- const sessionToken = toBase64Url(crypto.getRandomValues(new Uint8Array(32)));
- const sessionHash = await sha256(sessionToken);
- const response = await fetch(`${supabaseUrl}/rest/v1/rpc/activate_license_session`, {
- method: "POST",
- headers: {
- apikey: serviceKey,
- Authorization: `Bearer ${serviceKey}`,
- "Content-Type": "application/json",
- },
- body: JSON.stringify({ license_key: licenseCode, session_hash: sessionHash }),
- });
-
- if (!response.ok) {
- return json({ message: "Invalid, expired, or disabled license code." }, 401);
- }
- const result = await response.json();
- const expiresAt = new Date(result.session_expires_at);
- const maxAge = Math.max(0, Math.floor((expiresAt.getTime() - Date.now()) / 1000));
- const cookie = `${COOKIE_NAME}=${sessionToken}; Path=/; HttpOnly; Secure; SameSite=Strict; Max-Age=${maxAge}`;
- return json({ ok: true }, 200, { "Set-Cookie": cookie });
-}
diff --git a/index.html b/index.html
index e80fd1a..0cfad7b 100644
--- a/index.html
+++ b/index.html
@@ -7,33 +7,12 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- OpenMouse | All Your Mice. One Control Panel.
+
+
+ OpenMouse Control
-
-
+
+