import { useEffect, useState } from "react";
import Nav from "../components/Nav";
import Footer from "../components/Footer";
import NeuralBoot from "../components/NeuralBoot";
import SignupForm from "../components/SignupForm";
import LiveCounter from "../components/LiveCounter";
import USMap from "../components/USMap";
import { fetchCount } from "../lib/signup";
import { useStats } from "../lib/useStats";
const BEATS = [
{
id: "about",
idx: "01 / what it is",
big: "Local AI is the next personal computer.",
body: (
<>
Not a chatbot account. Not a rented API. A model you can run on your own machine, inspect,
repair, improve, and use without asking a platform to stay online. That is the line RTI
exists to protect.
>
),
img: "/beats/beat-01-local.webp",
alt: "A laptop running a small AI model locally",
imgMax: 505,
},
{
id: "principles",
idx: "02 / what we want",
big: "Protect lawful use. Enforce real harm.",
body: (
<>
People should be free to download, own, run, study, modify, and share open AI models.
Fraud, cybercrime, CSAM, harassment, nonconsensual intimate deepfakes, discrimination, and
sabotage should stay illegal and be enforced seriously. The red line is requiring a license
just to own or run the tool.
>
),
img: "/beats/beat-02-protect.webp",
alt: "A shield protecting a growing sprout",
},
{
id: "local-first",
idx: "03 / local first",
big: "Use the computer you already own.",
body: (
<>
Not every AI task needs a warehouse of GPUs. For many everyday tasks, a small open model can
run on a laptop, desktop, or phone people already have. Local AI will not replace every cloud
model or training run, but the law should not force simple, lawful workloads back into the
cloud when the task fits the device.
>
),
img: "/beats/beat-03-devices.webp",
alt: "A phone and laptop running models without the cloud",
imgMax: 505,
},
];
// Mobile hero boot: its own full-strength stage under the CTA (workbench v2).
// lean: 0 skips pointer physics so taps never warp it. fill leaves ~50px of
// headroom around the boot inside the canvas — the breath (±14px) and scroll
// jello (±34px) excursions stay inside the render area instead of clipping.
const MOBILE_BOOT_OPTS = {
wallMin: 0,
wallGap: 12,
cutoff: 0.02,
fill: 0.67,
nodeScale: 0.62,
lean: 0,
};
function useIsMobile() {
const [mobile, setMobile] = useState(
() => window.matchMedia("(max-width: 820px)").matches,
);
useEffect(() => {
const mq = window.matchMedia("(max-width: 820px)");
const on = (e: MediaQueryListEvent) => setMobile(e.matches);
mq.addEventListener("change", on);
return () => mq.removeEventListener("change", on);
}, []);
return mobile;
}
// Compact US-focused live stats for the endbeat: American signatures, calls,
// and active states — the domestic fight, next to the state map.
function EndStats() {
const stats = useStats();
if (!stats) return null;
let signups = 0;
let calls = 0;
let active = 0;
for (const s of Object.values(stats.states)) {
signups += s.signups;
calls += s.calls;
if (s.signups + s.calls > 0) active += 1;
}
return (
{signups.toLocaleString("en-US")}US signatures
{calls.toLocaleString("en-US")}calls logged
{active}states active
);
}
export default function Home() {
const isMobile = useIsMobile();
const [total, setTotal] = useState(null);
useEffect(() => {
let alive = true;
fetchCount().then((n) => {
if (alive && n !== null) setTotal(n);
});
// Fresh totals broadcast by the signup modal (which lives at App level).
const onTotal = (e: Event) => {
const n = (e as CustomEvent).detail;
if (alive && typeof n === "number") setTotal(n);
};
window.addEventListener("rti:total", onTotal);
return () => {
alive = false;
window.removeEventListener("rti:total", onTotal);
};
}, []);
return (
<>
{!isMobile && }
Protect your right to run local AI.
New state laws could put local AI behind a license — turning open models into something
you need permission to use.{" "}
Signing takes ten seconds. If you're down to do more, we've got a call script ready.
{isMobile && (
)}
{BEATS.map((b, i) => (
{b.idx}
{b.big}
{b.body}
))}
→ now
Start with your state.
Choose any state and get one useful call script. State is enough to start. The
official lookup may ask for your address to find exact legislators; RTI does not
store it.
→ get involved
Want to do more than call?
Follow the people building this in the open. If you want to help with research,
outreach, data, or the site, reach out directly.