Get the key to your own website.
A zero-dependency, browser-based inline editor for static HTML. Click any text, swap any image, reformat a section with AI, and publish straight to GitHub Pages β no terminal, no CMS, no subscription.
- Site: gitqi.com
- License: MIT β free, forever
Most website tools rent you an experience. GitQi gives you back the page.
- Your HTML is the database. The file you see in the browser is the file on disk, is the file on GitHub. There is no backing store, no CMS schema, no headless API β you can grep it, diff it, or walk away with it at any time.
- Local-first, by design. Your credentials live in one file on your machine and never leave it. No servers, no accounts, no "forgot your password" flow because there is no password.
- Right to Repair your website. Open the source, read every line, fork it, self-host it. MIT licensed, no closed core, no paid tier.
GitQi has two modes:
- Edit mode β activated when
secrets.jsis present beside your HTML. The toolbar, editable zones, link popover, and AI tools all light up. - Public mode β the deployed site.
gitqi.jsandsecrets.jsare stripped from the published HTML automatically. Visitors see static HTML; no editor code, no credentials, no runtime overhead.
- π Get Key β first-time setup for site owners. About 30 minutes the first time, one click forever after. Summarised below; walked through with screenshots at gitqi.com/get-key.html.
- ζ° Git Qi β the advanced path. How GitQi works under the hood, how to pin or self-host
gitqi.js, how to fork and release. Covered in Advanced and at gitqi.com/git-qi.html.
Seven steps. No installs, no terminal. Works on any machine with Chrome or Edge.
Open the Bootstrap Prompt. Fill in the bracketed fields (name, tagline, sections, vibe) and gather 2β5 inspiration images. Paste the prompt into Claude.ai (a free account works), attach your images, and save the output as index.html in a new folder on your computer (e.g. my-site/).
The AI-generated HTML is a starting point, not a final product. You'll edit every word of it directly on the page once GitQi is running. Focus the prompt on establishing a theme and structure you like β don't try to get the copy perfect.
Create a new public repository on GitHub (e.g. jane/jane-osteopathy). Leave it empty β don't add a README, .gitignore, or license. GitQi will populate it on first publish.
You do not need to enable GitHub Pages yet. That step comes last (Step 7), after your first publish creates the
mainbranch. Trying to enable Pages on an empty repo with no branch to serve from will just fail.
Profile photo β Settings β Developer settings β Personal access tokens β Fine-grained tokens β Generate new token.
- Name:
gitqi-my-site(or similar) - Expiration: no expiry, or one year
- Repository access: Only select repositories β pick the repo you just created
- Permissions β Repository permissions β Contents: Read and write
Generate, then copy the token immediately (GitHub only shows it once). It starts with ghp_.
This token can only read and write files in your one repository. It cannot access your GitHub account or any other repo. If it's ever exposed, revoke it and generate a new one in seconds.
Go to aistudio.google.com, sign in with any Google account, and click Get API key β Create API key. Copy the key (starts with AIza). No billing, no credit card, no Cloud Console configuration.
If you get prompted to enable billing, you're in the wrong place β step back from Google Cloud Console to AI Studio itself.
If AI actions fail with "model is busy" or "quota exceeded": GitQi auto-fallbacks across Gemini models (2.5 Flash β 2.5 Pro β 2.0 Flash β Flash latest β 2.5 Flash Lite) on retryable errors. Each model has its own independent quota on AI Studio, so a daily-limit hit on one doesn't block the others. You'll see a status message when a fallback kicks in. If all models fail in one request, the error dialog exposes a Retry with model dropdown so you can pin a specific one.
In the same folder as your index.html, create a plain-text file named secrets.js:
// secrets.js β lives beside your HTML, never published
window.SITE_SECRETS = {
geminiKey: "AIza...", // your Google AI key (Step 4)
githubToken: "ghp_...", // your GitHub token (Step 3)
repo: "username/my-site", // your GitHub user / repo name
branch: "main",
};Your folder now looks like:
my-site/
βββ index.html
βββ secrets.js β stays on your machine, forever
secrets.jsis never pushed to GitHub. GitQi strips it (andgitqi.js) from the published output on every publish. Credentials never leave your computer.
Open index.html in Chrome or Edge (drag it into a browser window, or right-click β Open With). The GitQi toolbar appears automatically.
A banner appears prompting you to Select Folder β pick the folder containing your HTML. This links GitQi to your files so every edit auto-saves within ~1.5 seconds. The link persists across sessions (one permission prompt per session).
Edit anything:
- Click any text and type
- Select text for the formatting toolbar (bold, italic, color, font, size, code, link)
- Click any image to replace it
- Hover sections for β³ Reformat, β Delete, or + Add Section between them
- Click Theme in the toolbar for colors, fonts, spacing, favicon, page title, meta description
- Click Pages (multi-page only) to add AI-generated pages or navigate between them
When you're ready, click Publish in the toolbar. GitQi strips all editor code + secrets.js, serializes the clean HTML, and pushes it to GitHub via the Contents API. That first publish also creates the main branch β which is what Step 7 needs.
Safari and Firefox are not supported. Editing requires the File System Access API, which only Chromium browsers ship today. The published site itself works in every browser.
In your repo on GitHub: Settings β Pages β Source β Deploy from a branch. Set branch to main, folder to / (root), click Save.
GitHub shows a banner: "Your site is live at https://your-username.github.io/your-repo-name/". The first deploy takes about a minute.
π You're in. From here on, the loop is: open index.html, edit, click Publish. No terminal, no git, no CMS, no monthly bill.
Text β click any data-editable element and type directly.
Text formatting β select text to reveal a floating toolbar. Buttons: B (bold), I (italic), π¨ (color β theme swatches, custom picker, or remove), Aa (font β theme font vars or clear), Aβ (font size β em-relative presets from Smaller to Huge), </> (inline code), π (link).
Links β click any link (body or nav) to open the popover. Fields: display text, URL, Go to link β (preview), page/section picker (jumps to any page or #anchor across your site), open-in-new-tab toggle, remove-link.
Images β click any data-editable-image element to replace it. The file is written to your local assets/ folder and queued for GitHub upload on the next publish.
Sections
- Hover between sections β + Add Section (AI-generate a themed new section)
- Hover a section β β³ Reformat (restructure layout with AI; existing content preserved)
- Hover a section β β Delete Section
Navigation β hover the nav β β³ Reformat Nav (AI restructure). Changes sync to every other page automatically.
Pages (multi-page sites) β click Pages in the toolbar. Navigate between pages, generate a new AI page, or delete a page. New page links are added to the nav and propagated to every page.
AI model fallback β all four AI actions (Add Section, Reformat, Reformat Nav, Add Page) route through a fallback chain of Gemini models. If the primary is overloaded or rate-limited, GitQi automatically retries on the next one and shows a status like "Using Gemini 2.5 Pro β primary model was busy". On total failure the error dialog offers a Retry with model dropdown so you can force a specific model.
Theme β click Theme for live controls over:
- Site identity: favicon, page title, meta description, keywords (title/description/keywords are per-page; everything else is site-wide)
- CSS variables, grouped as Colors / Typography / Spacing / Layout
- Google Fonts: Browse Google Fontsβ¦ opens a modal covering the full catalog (~1,900 families), lazy-loaded as rows scroll in, with category filter, name search, and popularity / AβZ sort. Picking a font injects only the
<link>for that family. Abandoned fonts are pruned from<head>on the next auto-save.
Undo / Redo β toolbar β© / βͺ buttons, or Ctrl+Z / Ctrl+Shift+Z. Covers structural changes (AI actions, section/page deletes). Text edits use the browser's native undo.
GitQi uses data attributes to identify editable regions. The AI-generated HTML includes them automatically; if you're hand-authoring, here's the reference.
| Attribute | Applied to | Purpose |
|---|---|---|
data-zone |
<section> |
Marks a top-level editable section. Value is a slug, e.g. "hero". Also used as the element id for anchor links. |
data-zone-label |
<section> |
Human-readable label shown in the delete confirmation, e.g. "Hero". |
data-editable |
Any text element | Makes the element directly editable via contenteditable. |
data-editable-image |
<img> |
Makes the image replaceable by clicking. |
Minimal example:
<section data-zone="about" data-zone-label="About">
<h2 data-editable>About Me</h2>
<p data-editable>Replace this with your own text.</p>
<img src="./assets/placeholder.jpg" data-editable-image alt="Profile photo" />
</section>Two script tags must appear in <head> (after the <style> block) for edit mode to work locally. Both are stripped automatically on export and publish β the deployed site contains neither.
<script src="./secrets.js"></script>
<script src="https://swill.github.io/gitqi/gitqi.js"></script>Multi-page sites use a gitqi-pages.json manifest in the site folder alongside the HTML files:
{
"pages": [
{ "file": "index.html", "title": "Home β My Site", "navLabel": "Home" },
{ "file": "about.html", "title": "About β My Site", "navLabel": "About" },
{ "file": "services.html", "title": "Services β My Site", "navLabel": "Services" }
]
}GitQi creates and maintains this file automatically. It's pushed to GitHub on every publish. Adding GitQi to an existing single-page site creates the manifest automatically the first time you link your folder.
Shared head + nav sync β on every auto-save, GitQi compares the current page's shared elements against a snapshot from the last sync. If anything changed, the updated elements are written to every other page file on disk automatically.
Synced site-wide:
<nav>(including nav-specific CSS in<style id="__gitqi-nav-styles">)- Main
<style>block (CSS variables + base styles edited via the Theme panel) <link rel="icon">and<link rel="apple-touch-icon">(favicon)- Google Fonts
<link>s (plus their preconnect links)
When the nav is synced, the "current page" highlight is re-targeted for each destination: the link matching that page gets the active marker; every other link is cleared. Recognised markers are the aria-current attribute and the CSS classes active, current, is-active, is-current, and selected.
Left page-specific: <title>, <meta name="description">, <meta name="keywords">.
By default your site is served at https://username.github.io/repo-name. To use your own domain (e.g. www.janeosteopathy.com):
- In your DNS provider, add a CNAME record:
Name Type Value wwwCNAME username.github.io - In your GitHub repo, Settings β Pages β Custom domain, enter
www.example.com, click Save. GitHub creates aCNAMEfile automatically. - Check Enforce HTTPS once the certificate is provisioned (usually a few minutes).
GitQi publishes by overwriting HTML files only β it doesn't touch the
CNAMEfile. Your custom domain stays configured across all publishes.
- In your DNS provider, add four A records:
Name Type Value @A 185.199.108.153@A 185.199.109.153@A 185.199.110.153@A 185.199.111.153 - Optionally add a CNAME for
wwwβusername.github.ioso both work. - In your GitHub repo, Settings β Pages β Custom domain, enter
example.com, click Save. - Check Enforce HTTPS once the certificate is provisioned.
DNS changes can take up to 48 hours to propagate. GitHub will warn you if the domain isn't verified yet β wait a few minutes and refresh.
You have the key. Now the Qi: how GitQi actually works, how to pin or self-host gitqi.js, and how to cut your own releases.
GitQi is a single JavaScript file that activates only when window.SITE_SECRETS is set (i.e. when secrets.js has loaded). In public mode the script tag is stripped entirely, so there's nothing to load and nothing to run.
The publish pipeline is:
- Serialize the live DOM (clone, strip editor UI, resolve local image paths).
- Strip the editor and
secrets.jsscript tags. - Push each page via the GitHub Contents API (
PUT /repos/{repo}/contents/{path}). - GitHub Pages serves the updated file within ~60 seconds.
No git on your machine, no CI, no build step. The HTML is the artifact.
gitqi.js is served from its own GitHub Pages repo so multiple sites can share a single hosted copy.
Latest version (always current):
https://swill.github.io/gitqi/gitqi.js
Pinned version (recommended for production β immune to upstream changes):
https://swill.github.io/gitqi/gitqi-<VERSION>.js
Pinned versioned files are committed alongside gitqi.js on each release and are never modified after publishing.
Want to own the whole stack?
- Fork
swill/gitqion GitHub. - Enable GitHub Pages on your fork (Settings β Pages β Deploy from a branch β
main/(root)). - Change the script tag in your site's HTML from
swill.github.io/gitqi/gitqi.jstoyour-user.github.io/gitqi/gitqi.js.
You now run your own copy. Pin it, patch it, release on your own schedule.
Versions follow Semantic Versioning:
- Patch (
1.0.x) β bug fixes, safe to update - Minor (
1.x.0) β new features, backwards compatible - Major (
x.0.0) β breaking changes; pinned sites are unaffected
The version is accessible at runtime:
console.log(window.GitQi.version);# Local development server (http://localhost:8080, CORS enabled)
make serve
# Check JavaScript syntax
make check
# Release a new version β writes gitqi-<VERSION>.js, bumps VERSION, tags, pushes
make release VERSION=1.3.0
# Regenerate the Google Fonts manifest (google-fonts.json)
make fontsSee the Makefile for the full details of what each target does.
GitQi ships a full Google Fonts catalog (google-fonts.json, served alongside gitqi.js) so the font picker covers the entire library, not just a curated subset. The manifest is regenerated manually via make fonts. At runtime gitqi.js fetches it, caches it in localStorage, and falls back to a small built-in list if the fetch fails.
One-time setup β needed only if you want to regenerate the manifest yourself:
- Get a free Google Fonts Developer API key:
- Go to the Google Cloud Console
- Create (or pick) a project
- Enable the Web Fonts Developer API under APIs & Services β Library
- Create a key under APIs & Services β Credentials β Create Credentials β API key
- Restrict it (recommended): under API restrictions pick Web Fonts Developer API only
- Copy the example file and drop your key in:
cp .env.example .env # then edit .env and set GOOGLE_FONTS_API_KEY=<your-key>.envis gitignored β the key never lands in the repo. - Generate the manifest:
This fetches the catalog from the Developer API, sorted by popularity, and writes
make fonts
google-fonts.jsonat the repo root β each entry is{ name, cat, weights }. Array order is the popularity ranking. Commit the file and it deploys alongsidegitqi.json the next release.
The source is yours to read, fork, and improve. Issues and pull requests welcome at github.com/swill/gitqi.
secrets.jslives only on your computer and is never published β your local folder is not a git repository- The GitHub PAT should be a fine-grained token scoped to the single site repo with
contents: read + writeonly - The Gemini API key is used client-side β acceptable for personal / single-owner use; for shared use, proxy through a serverless function
- Exported and published HTML contains no credentials and no editor code
| Browser | Edit mode | Public site |
|---|---|---|
| Chrome 86+ | β | β |
| Edge 86+ | β | β |
| Safari | β | β |
| Firefox | β | β |
Edit mode requires the File System Access API. The published site is plain HTML and works everywhere.
MIT. Free, forever.