FocusNexus — run it on your own computer, or host your own copy
================================================================
This bundle is built automatically from the same files that are live at
https://cerrver.github.io/focusnexus/ — it always matches the hosted app.
The full guide, with screenshots and FAQ, is on the homepage:
https://cerrver.github.io/focusnexus/home.html#local

What is in the zip
------------------
  focusnexus.html       the desktop app (open this one)
  minifocusnexus.html   the phone app (same data, phone-sized layout)
  sw.js                 service worker (keeps the page fresh; optional)
  serve.py              a tiny local web server (Python 3, standard library)
  launch.bat            Windows launcher: starts serve.py, opens the browser
  launch.command        macOS launcher (same thing)
  fn_*.png / fn_*.svg   icons;  site.webmanifest  (add-to-home-screen data)
  LICENSE.md            CC BY-NC-SA 4.0 — free for personal, academic and
                        other non-commercial use, with attribution and
                        share-alike; commercial rights reserved.

1. Run it on your own computer
------------------------------
Why not just double-click focusnexus.html?  A page opened from a file
(file://) has no web origin, and Google's sign-in is tied to the page's
origin, so Drive can never connect from a file.  The launcher fixes that by
serving the folder at http://127.0.0.1:8734, which is registered with the
app's Google sign-in.

  a) Install Python 3 if you do not have it (https://www.python.org/downloads/
     — on Windows tick "Add python.exe to PATH").
  b) Unzip this bundle into a folder of its own.
  c) Windows: double-click launch.bat.  macOS: double-click launch.command
     (first time: right-click → Open, or run  chmod +x launch.command  in
     Terminal if macOS refuses).  Keep the window open — closing it stops
     the server.
  d) Your browser opens http://127.0.0.1:8734/focusnexus.html.  Press
     "Connect Google Drive" and sign in exactly as on the hosted site.  It
     reads and writes the same FocusNexus folder in your Drive, so your data
     is the same wherever you open it.

Things to know
  - The port is fixed at 8734 on purpose; do not change it.
  - The copy is frozen at the version you downloaded (the version is printed
    in the app header).  The hosted page updates itself; a local copy does
    not — download a fresh bundle when the change log shows a new release.
  - It still needs the internet: the app loads React from a CDN and talks to
    Google.  Nothing else is contacted.
  - The browser keeps a separate local cache for this address; after
    connecting Drive it fills from your Drive document.
  - Windows SmartScreen / macOS Gatekeeper may warn about an unrecognised
    script.  Both launchers are short plain-text files you can read.
  - The server listens on 127.0.0.1 only: nothing on your network can reach
    it.

2. Host your own copy (your own GitHub Pages, or any static host)
-----------------------------------------------------------------
The app is static files, so any static host works.  ONE thing must change:
the Google sign-in.  Google only allows sign-in from origins registered on
the app's OAuth client, and that client belongs to the original project —
you cannot add your site to it.  So a copy at a new address needs its own
client:

  a) Google Cloud Console → create a project → APIs & Services → Library →
     enable the Google Drive API.
  b) OAuth consent screen: External; add the scope
     https://www.googleapis.com/auth/drive.file (non-sensitive — no
     verification needed; it lets the app see only files it created).
     Publish the app (Testing status expires grants after 7 days).
  c) Credentials → Create credentials → OAuth client ID → Web application.
     Authorized JavaScript origins: your site's origin, e.g.
     https://<you>.github.io  (and http://127.0.0.1:8734 if you also want
     the launcher).  The sign-in flow the app uses checks only the
     JavaScript origin; adding the same value as a redirect URI is harmless.
  d) Put the new client ID into BOTH app files: the line beginning
     const GOOGLE_CLIENT_ID='...'  (focusnexus.html and minifocusnexus.html).
  e) Push the files to a repository and enable GitHub Pages (Settings →
     Pages → deploy from the branch), or copy them to any static host.

Because drive.file is per-app, a copy with a new client ID cannot see the
FocusNexus files made by the original app.  Move your data once with
Tools → Export .json on the old copy and Tools → Import .json on the new one.

Other things you may want to change in a copy: the time zone is fixed in
the source (const TZ='America/New_York' in both files); the "About" link
and the saved-copy notice point at the original homepage.

Teams (beta) additionally need an OAuth client SECRET for the team hub
account, entered in the Create Team dialog — use your own client's secret.

The license (LICENSE.md) applies to copies and modified versions alike:
keep the attribution, keep the license, no commercial use without a
separate agreement.  Questions: deasyj@mskcc.org
