File size: 6,321 Bytes
32cc346 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 | ---
license: mit
pretty_name: OpenSite
tags:
- html
- javascript
- single-file
- productivity
- keyboard
- no-dependencies
---
<div align="center">
<img src="assets/logo.png" alt="OpenSite logo" width="128" height="128"/>
<h1>OpenSite</h1>
<p><strong>Type a command. The site opens.</strong></p>
<p>A single HTML file that turns your browser into a command-line launcher for the sites you actually use.</p>
</div>

## What this is
OpenSite is a **one-file web launcher**. You open `index.html`, a command field sits in the middle of the
screen, and you tell it what you want:
```text
open youtube -> https://youtube.com
open gh -> https://github.com
open docs:rust -> https://doc.rust-lang.org/std/
search: rust tokio -> https://www.google.com/search?q=rust+tokio
```
No install, no build step, no dependencies. There is no framework, no bundler, no CDN font request and no
analytics β the whole tool is markup, styles and one plain `<script>` block you can read from top to bottom
in a couple of minutes.
## Why
The address bar is a search box that you occasionally use for navigation, and bookmarks are a list you never
open. A command field inverts that: you keep a short vocabulary in your hands (`gh`, `yt`, `docs:rust`) and
the browser stops being a place you browse through. It is measurably faster for a fixed set of destinations,
and it stays fast because there is nothing to update, sync, migrate or sign in to.
## Quick start
1. Download `index.html` from this repo.
2. Double-click the file, or drag it into a tab. That is the entire setup β it runs straight off `file://`.
3. Optional: point your browser's home page or a new-tab extension at it, so every new tab is a prompt.
## Commands
| You type | What happens |
| --- | --- |
| `open youtube` | Opens the matching site from your list in a new tab |
| `youtube` | Bare word works too β the prefix is optional |
| `open gh` | Aliases resolve, so one or two keystrokes per favorite |
| `you` | Fuzzy matching wins over strict prefixes: `you` β YouTube |
| `search: rust tokio` | Sends a query to the search engine instead of opening a site |
| `docs:rust` | Prefixed entries are grouped, so `docs:` lists your docs only |
| `1`, `2`, `3` | Opens the 1st / 2nd / 3rd result without leaving the keyboard |
| `add <name> <url>` | Saves a new entry to your list, stored locally in the browser |
Unmatched input is not swallowed: if nothing resolves, the field hands the text to your browser's default
search, so a typo costs you one keystroke rather than a trip back to the address bar.
## Editing your own site list
Everything you care about lives in one array at the top of the file:
```js
const SITES = [
{ name: "youtube", url: "https://youtube.com", alias: ["yt"] },
{ name: "github", url: "https://github.com", alias: ["gh"] },
{ name: "rust docs", url: "https://doc.rust-lang.org/", alias: ["docs"] },
];
```
Add a row, save, reload. Aliases are checked before the fuzzy pass, and entries you use often float to the
top: the score is a mix of name similarity, alias hit and a local usage counter kept in `localStorage`.
Clear that key to reset the ordering if it drifts somewhere you don't like.
## Keyboard
| Key | Action |
| --- | --- |
| `Enter` | Open the highlighted result |
| `Alt` + `Enter` | Open in a new background tab instead of focusing it |
| `β` / `β` | Move through results |
| `Tab` | Complete the current word against the best match |
| `Esc` | Clear the field |
The field is focused on load and there is no modal, banner or first-run tour in front of it.
## Non-goals
- **Not a bookmark manager.** There is no folder tree, no tag UI and no cloud sync β the file is the list.
- **Not a PWA.** No service worker, no manifest, no install prompt, nothing that survives offline as an app.
- **No network calls at all.** Nothing is fetched, so nothing can be sent. The page works with Wi-Fi off.
- **Not multi-device.** Your list is whatever is on this machine, which is the trade for having no account.
## Gallery
**Three steps, one keypress.** Type, pick from the shortlist, the tab opens.

**Keyboard-first by construction.** Everything is reachable without the mouse.

**Local by default.** One file on disk β no cloud, no cookies, no telemetry.

## Files
```text
.
βββ index.html # the whole tool
βββ README.md # this card
βββ assets/
βββ logo.png # repo avatar / logo
βββ banner.png # card banner
βββ how-it-works.png # flow: type -> match -> open
βββ keyboard.png # keyboard-first shot
βββ local-first.png # offline / no-telemetry shot
```
## Notes and limits
- Pop-up blockers need a user gesture, which the `Enter` / click path already provides; the very first open
in a session may ask you to allow pop-ups for the page.
- `file://` pages can't write back to disk. `add <name> <url>` persists in `localStorage`; the portable way to
carry your list between machines is to paste those lines into the `SITES` array and keep the file in a repo.
- Tabs opened in a new window depend on your browser's tab-position setting; the tool does not try to control it.
<details>
<summary><strong>Publishing this as a Hugging Face Static Space instead of a model repo</strong></summary>
Nothing about the file changes β add the Space keys to the frontmatter above and keep `index.html` at the
repository root:
```yaml
---
title: OpenSite
emoji: "π"
colorFrom: indigo
colorTo: purple
sdk: static
app_file: index.html
pinned: false
license: mit
---
```
`sdk: static` serves the HTML directly, so the Space behaves like the local file, including the
`localStorage` list β which is per-browser and per-origin, not shared with your downloaded copy.
</details>
## License
Released under the [MIT License](LICENSE). Use it, fork it, paste it into your own dotfiles, ship a
modified version β attribution is nice, never required.
|