mirror of
https://github.com/snapotter-hq/SnapOtter.git
synced 2026-08-03 07:46:42 +02:00
- New apps/demo/ that reuses apps/web components with mocked API layer - Full UI shell: login, change password, analytics consent, dashboard, all tool pages - Stateful mock tracks session flow (password change, analytics consent) - Demo banner with link to GitHub repo - Processing attempts show info message with GitHub link - Deployed to Cloudflare Pages as static site (no backend) Also links demo across all surfaces: - README: "Live Demo" badge - Landing navbar: "Try Demo" CTA button (replaces "Book a Demo") - Landing hero: "No sign-ups. No credit card." tagline - Docs getting-started: "Try before installing" tip box Other changes: - Docs: move NVIDIA GPU section above GHCR, demote GHCR to collapsed details - Fix before-after slider checkerboard background for transparency - Fix remove-bg preview reset when no effects applied
57 lines
1.8 KiB
TypeScript
57 lines
1.8 KiB
TypeScript
import { installMocks } from "./mock-api";
|
|
|
|
installMocks();
|
|
|
|
import { StrictMode } from "react";
|
|
import { createRoot } from "react-dom/client";
|
|
import { App } from "@/App";
|
|
import { DemoBanner } from "./demo-banner";
|
|
import "./styles/globals.css";
|
|
|
|
const DEMO_MARKER = "demo instance";
|
|
const GITHUB_URL = "https://github.com/snapotter-hq/SnapOtter";
|
|
const GITHUB_LABEL = "github.com/snapotter-hq/SnapOtter";
|
|
|
|
function patchDemoErrors(root: Element) {
|
|
const observer = new MutationObserver(() => {
|
|
root.querySelectorAll(".text-red-500, [data-type='error']").forEach((el) => {
|
|
if (!(el instanceof HTMLElement)) return;
|
|
if (!el.textContent?.includes(DEMO_MARKER)) return;
|
|
if (el.dataset.demoPatch) return;
|
|
el.dataset.demoPatch = "1";
|
|
el.classList.remove("text-red-500");
|
|
el.style.color = "#3b82f6";
|
|
el.style.fontSize = "13px";
|
|
el.style.lineHeight = "1.5";
|
|
|
|
const text = el.textContent;
|
|
const parts = text.split(GITHUB_LABEL);
|
|
while (el.firstChild) el.removeChild(el.firstChild);
|
|
el.appendChild(document.createTextNode(parts[0]));
|
|
|
|
const link = document.createElement("a");
|
|
link.href = GITHUB_URL;
|
|
link.target = "_blank";
|
|
link.rel = "noopener noreferrer";
|
|
link.textContent = GITHUB_LABEL;
|
|
link.style.fontWeight = "600";
|
|
link.style.textDecoration = "underline";
|
|
link.style.textUnderlineOffset = "2px";
|
|
el.appendChild(link);
|
|
|
|
if (parts[1]) el.appendChild(document.createTextNode(parts[1]));
|
|
});
|
|
});
|
|
observer.observe(root, { childList: true, subtree: true, characterData: true });
|
|
}
|
|
|
|
const rootElement = document.getElementById("root");
|
|
if (!rootElement) throw new Error("Root element not found");
|
|
patchDemoErrors(rootElement);
|
|
createRoot(rootElement).render(
|
|
<StrictMode>
|
|
<DemoBanner />
|
|
<App />
|
|
</StrictMode>,
|
|
);
|