Add project landing page - #10
Merged
Merged
Conversation
A static page for GitHub Pages, served from /docs. No build step, no dependencies, 48 KB total including the icon. The hero is built from the product's own vocabulary - two backlit keycaps that alternate - rather than stock imagery, so the page works without app screenshots and does not look like every other landing page. No invented testimonials or user counts: the app shipped today and has none. Verified in a real browser at 1200px and 375px. Caught and fixed a mobile overflow where the brew command, being a flex item with the default min-width:auto, stretched the page to 503px instead of scrolling in its own box.
There was a problem hiding this comment.
Pull request overview
Adds a new static landing page under /docs intended for GitHub Pages, presenting InputPilot’s value proposition, setup flow, features, and a privacy-focused explanation of the Input Monitoring permission.
Changes:
- Add a single-page marketing/landing site (
docs/index.html) with embedded CSS (no external dependencies). - Include a “brew install” snippet with a copy-to-clipboard button.
- Add sections for problem statement, setup steps, features, privacy explanation, FAQ, and download CTA.
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
|
|
||
| <div class="brew"> | ||
| <code class="mono" id="brewcmd">brew install --cask lucagerlich/tap/inputpilot</code> | ||
| <button type="button" onclick="navigator.clipboard.writeText(document.getElementById('brewcmd').textContent).then(()=>{this.textContent='Copied';setTimeout(()=>this.textContent='Copy',1600)})">Copy</button> |
| <li>The only network traffic is the update check. No telemetry, no analytics, no crash reporter.</li> | ||
| <li>The source is public and the whole app is about 4,000 lines. You can read the keyboard handling in a few minutes.</li> | ||
| </ul> | ||
| <p style="margin-top:1.2rem"><a href="https://github.com/LucaGerlich/InputPilot/blob/main/SECURITY.md">Read the full privacy statement →</a></p> |
| <div> | ||
| <a href="https://github.com/LucaGerlich/InputPilot">GitHub</a> | ||
| <a href="https://github.com/LucaGerlich/InputPilot/releases">Releases</a> | ||
| <a href="https://github.com/LucaGerlich/InputPilot/blob/main/CHANGELOG.md">Changelog</a> |
Terminal aesthetic throughout: monospace, dark, bordered panels, a window chrome around the hero. The hero is a QWERTZ keyboard drawn in box-drawing characters, with the keys that move between the German and U.S. layouts picked out in orange - the product's premise, stated in one image. The art is generated by docs/generate-keyboard-art.py so the alignment is exact rather than hand-tuned; every row is 75 characters. Below it: an example debug log and device cards in the app's own vocabulary (vendor and product IDs, transport, layout, status), then setup, privacy, and FAQ. No fabricated metrics - the reference mockups showed CPU, memory and latency readouts that this app does not measure and would be inventing. Verified in a browser at 1280px and 375px: no page overflow, art fills 80% of the terminal on desktop and fits within it on mobile.
The keyboard now fills 96% of the terminal (25px, 1129px wide) instead of half of it, and it moves: keys light up as if typed, then the layout flips between German and U.S. - Z and Y swap places, the umlauts become brackets and quotes, and the window title changes to the other keyboard. That is the whole product demonstrated in the hero without a screenshot or a word. Every legend is a span emitted by generate-keyboard-art.py, so the animation addresses individual keys and swaps their labels while the box drawing stays aligned; each row is still exactly 75 characters. Verified in a browser: keypress highlights and layout swaps both observed over a 9-second sample, no page overflow, and the art fits inside its box on a 375px viewport. Animation stops for prefers-reduced-motion and pauses when the tab is hidden.
Replaces the clean box-drawing board with character-density shading: the keyboard is drawn as a bitmap with bright keycaps and legends punched out, then sampled per character cell onto a ' .:-=+*#%@' ramp, so caps read as solid blocks with the letters showing through as dark shapes. 168 columns wide, which is the resolution needed for the legends to survive sampling; a bold face and a gamma curve on the cell means keep partial coverage from washing out to mid-grey. The animation survives the change: each cap's characters are wrapped in a span carrying its US counterpart, so a keypress lights the whole keycap and a layout switch rewrites the legends in place. Every row is still exactly 168 characters after any swap. generate-keyboard-art.py renders the grids, generate-keyboard-html.py emits the markup, so the art can be regenerated rather than hand-edited. Verified: 94% of the terminal width on desktop, fits a 375px viewport with no page overflow, keypresses and layout swaps both observed over a 10s sample.
Readability came from fixing the sampling aspect: cells were 6x13px while a browser renders monospace at roughly 6x10, so the board was drawn squashed and wasted vertical resolution on the legends. Sampling at the aspect the page actually renders gives 34 rows instead of 26, and the letters survive. Supersampling 3x before downsampling cleans up the keycap edges. The hero now animates between the two physical boards rather than swapping legends: ISO with its L-shaped Enter, extra key beside left Shift and 13-key home row, against ANSI with a wide flat Enter and long left Shift. Both are built from real 60% key units and every row totals exactly 15u, which is asserted before rendering; a units error in the bottom row (14u) surfaced that way. Both boards render at identical size so the cross-fade cannot shift the layout. Verified in a browser: aspect 2.97 against a real keyboard's 3.00, 94% of the terminal width, 34x168 characters on both boards, keypresses and board swaps observed across a full 10s cycle, no page overflow.
The headline sat flush against the keyboard - the measured gap was 0px, so the board and the type read as one crowded block. Adds a responsive gap below the terminal (70px on desktop, 44px on mobile) and rebalances the headline-to-tagline spacing that was doubling up underneath.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
A small static site for InputPilot, ready to serve from GitHub Pages at
/docsonmain.https://lucagerlich.github.io/InputPilot/ once Pages is enabled.
Approach
The hero is built from the product's own vocabulary — two backlit keycaps that alternate between DE and US — in pure CSS. That means the page works today without app screenshots, loads instantly, and does not look like the generic SaaS template.
Deliberately omitted: invented testimonials, user counts, and stock photos of people smiling at laptops. The app shipped today and has no users yet; fabricating social proof for a keyboard-monitoring utility would undercut the one thing that actually sells it, which is trustworthiness. The privacy section gets the space instead.
Content
Hero with download and
brewinstall · the problem it solves · three-step setup · features · a plain-language explanation of why it needs Input Monitoring and what it does with that access · FAQ covering the App Store question, the missing-from-the-list issue we hit, and the relaunch requirement.Verified in a real browser
brewcommand is a flex item, and flex items default tomin-width: auto, so the long unwrappable command stretched the page to 503px in a 375px viewport instead of scrolling inside its boxFollow-up
Screenshots slot naturally between the hero and the how-it-works section once they exist.