still-free.openapps.xyz

Source

This app’s code and revision history are public. Download a copy or explore the files below.

Public
The app’s code and revision history are public.
Owned app · rev 0fa0e84d537b
Run it yourself
Take the whole tree and run it on your own machine. The download needs no account. Cloning needs a sign-in.
Download .zip
bounded clone a8c677472ab5691741798a3d
A copy you download is not bounded. The guarantees this app runs under - declared egress, proven invariants, writes that fail closed - live in the runtime serving this page, not in the files. What you get is auditable source you can read and run, with no runtime guarantees attached.
← All files
src/main.tsx
// Still's entry. "/" keeps the static landing and mounts the quick start into its hero. The app's
// routes (/today, /breathe, /meditate, /sounds, /sleep, /progress) hide the landing and load the app.
import { lazy, Suspense, useEffect } from "react";
import { createRoot } from "react-dom/client";
import { useLocation } from "./lib/router";
import { A, Icon, Toaster } from "./ui";
import "./styles.css";

const App = lazy(() => import("./App"));
const APP_ROUTE = /^\/(today|breathe|meditate|sounds|sleep|progress)(\/|$)/;
const LANDING_TITLE = document.title;

function Root() {
  const { path } = useLocation();
  const inApp = APP_ROUTE.test(path);
  document.body.classList.toggle("app-mode", inApp);
  useEffect(() => { if (!inApp) document.title = LANDING_TITLE; }, [inApp]);
  return (
    <>
      {inApp && (
        <Suspense fallback={<div className="page wrap"><div className="spinner" /></div>}>
          <App />
        </Suspense>
      )}
      <Toaster />
    </>
  );
}

/** The landing hero's way in: four doors and one button. */
function Start() {
  return (
    <div className="start card">
      <p className="eyebrow">Start now, no sign-up</p>
      <ul className="start-list">
        <li><A href="/breathe/box?min=1"><Icon name="breathe" /><span><strong>Breathe for a minute</strong><small>Box breathing, 4-4-4-4</small></span></A></li>
        <li><A href="/meditate"><Icon name="meditate" /><span><strong>Meditate</strong><small>12 guided sessions and a timer</small></span></A></li>
        <li><A href="/sounds"><Icon name="sounds" /><span><strong>Sleep sounds</strong><small>Rain, ocean, fire, white noise</small></span></A></li>
        <li><A href="/sleep"><Icon name="sleep" /><span><strong>Sleep stories</strong><small>Six calm stories read aloud</small></span></A></li>
      </ul>
      <A className="btn btn-lg btn-block" href="/today">Open Still</A>
    </div>
  );
}

// The night look before the app has loaded, so sleep screens never flash bright.
document.body.classList.toggle("night", /^\/(sleep(\/|$)|meditate\/falling-asleep)/.test(location.pathname));
createRoot(document.getElementById("app")!).render(<Root />);
const startSlot = document.getElementById("start");
if (startSlot) createRoot(startSlot).render(<Start />);

if (import.meta.env.PROD && "serviceWorker" in navigator) {
  window.addEventListener("load", () => void navigator.serviceWorker.register("/sw.js").catch(() => null));
}

const head = document.querySelector(".site-head");
const onScroll = () => head?.classList.toggle("scrolled", window.scrollY > 4);
window.addEventListener("scroll", onScroll, { passive: true });
onScroll();

Change history

Link to OpenApps pages and add a contribution strip
0fa0e84d53 · 19 hours ago
Bind the agent address in the policy
6f3baa1c72 · 1 day ago
Add favicon.ico so browsers that ask for it stop getting a 404
1a004fe0e3 · 1 day ago
Bounded source sync
afe642fe50 · 2 days ago
Bounded source sync
2c581f55ea · 2 days ago
Bounded source sync
375934c28b · 2 days ago
Bounded source sync
74ff37d51a · 2 days ago