Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
212 changes: 212 additions & 0 deletions DESIGN.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,212 @@
# Design

## Source of truth

**Status:** Active
**Date:** 2026-09-02
**Product surfaces:** browser-extension popup/options UI, public GitHub Pages landing page, store-facing product presentation.

Evidence reviewed:

- Current extension popup structure and existing product styling.
- README product description, supported platforms, privacy model, and project-impact figures.
- Existing GitHub Pages landing-page files under `docs/`.
- GitHub Pages deployment logs showing the repository root is the active publishing source.
- User screenshot of the live site showing the README rendered as the homepage.

## Brand

FocusTube should feel calm, focused, technical, and trustworthy. It is a practical productivity tool, not a lifestyle brand or a flashy startup landing page.

Trust signals:

- Free and open source.
- No analytics or tracking.
- No account or project-controlled backend.
- Available on Chrome, Firefox, and Edge.
- Real public source, releases, tests, and store listings.

Avoid:

- Generic AI-startup aesthetics.
- Decorative gradients, glow effects, excessive shadows, and card grids used only for visual filler.
- Huge marketing copy that pushes the product below the fold.
- Fake browser chrome, fake live counters, or invented usage statistics.
- Repeating the same claim in multiple sections.

## Product goals

Goals:

- Explain the product in one screen: keep useful parts of social sites, remove distracting feeds.
- Make the Chrome install action obvious while keeping Firefox and Edge easy to find.
- Show enough of the extension UI to make the product feel real.
- Establish privacy and open-source trust quickly.
- Work well on desktop and mobile without JavaScript.

Non-goals:

- Reproduce every extension setting on the marketing page.
- Turn the landing page into full documentation.
- Add analytics, accounts, tracking, or a backend.
- Add animation or visual effects that do not improve comprehension.

Success signals:

- A visitor can identify what FocusTube does within a few seconds.
- Store links are visible without scrolling on common desktop sizes.
- The live root URL serves the product landing page rather than the repository README.

## Personas and jobs

Primary personas:

- Students who need YouTube or social platforms for useful tasks but get pulled into short-form feeds.
- Knowledge workers who want to keep access to specific social-site functions without blocking entire domains.
- Privacy-conscious users who prefer a local, open-source extension.

Primary jobs:

- Understand what FocusTube blocks.
- Decide whether it fits the user's browsing habits.
- Install it in the user's browser.
- Verify that it does not track browsing activity.

## Information architecture

Public landing page hierarchy:

1. Header with FocusTube brand, key navigation, GitHub, and install action.
2. Hero with the core promise, browser install links, current project proof, and a product-control preview.
3. Supported-platform strip.
4. Short explanation of how FocusTube removes distracting surfaces while keeping useful pages available.
5. Privacy section.
6. Final install action.
7. Minimal footer with source link.

The README remains developer/project documentation and must not be used as the public landing-page entry file.

## Design principles

1. **Product before prose.** Show what the extension does before explaining every detail.
2. **One primary action.** Chrome is the main install CTA; Firefox and Edge remain visible secondary actions.
3. **Use real product language.** Prefer terms already used by FocusTube and avoid generic productivity slogans.
4. **Trust through restraint.** Privacy and open-source facts should be specific and verifiable, not exaggerated.
5. **No visual filler.** Every panel, border, label, and metric must carry product information.
6. **Preserve brand continuity.** The existing FocusTube blue is intentional product branding, not a default landing-page choice.

## Visual language

Color:

- Base: near-black neutral background.
- Surfaces: restrained dark gray layers.
- Text: high-contrast white with muted gray secondary copy.
- Accent: existing FocusTube blue `#4facfe` with a lighter hover state.
- Success state: muted green only for explicit enabled/status feedback.

Typography:

- System-first sans-serif stack using Inter when available.
- Large but controlled hero type; no oversized display text that overwhelms the product preview.
- Body copy at comfortable reading sizes with short line lengths.

Spacing:

- Wide desktop breathing room with tighter mobile spacing.
- Prefer separators and whitespace over stacking many boxed cards.

Shape and elevation:

- Moderate corner radii on interactive/product-preview surfaces.
- Borders provide separation; avoid gratuitous drop shadows and glow effects.

Motion:

- No required motion. Hover transitions should be subtle and functional.

Imagery and iconography:

- Use the real FocusTube extension icon.
- Product preview should reflect actual controls and terminology rather than a fake browser window.

## Components

Landing-page components:

- `site-header`: brand, navigation, install shortcut.
- `store-actions`: Chrome primary action plus Firefox and Edge secondary actions.
- `product-shot`: static representation of the extension control surface.
- `supported-strip`: supported-site names.
- `feature-rows`: three concise product behaviors.
- `privacy-section`: direct privacy statement plus specific trust facts.
- `install-section`: final install prompt.
- `site-footer`: brand/source closure.

Token ownership:

- Landing-page tokens live in the landing-page stylesheet and must not modify the extension's root `styles.css`.
- Extension UI tokens remain owned by the extension stylesheet.

## Accessibility

Target: WCAG 2.2 AA where practical for the static landing page.

- Semantic `header`, `nav`, `main`, `section`, and `footer` structure.
- Visible keyboard focus on links and controls.
- Decorative icon images use empty alt text; meaningful text remains in the DOM.
- Maintain readable text/background contrast.
- Do not require hover, animation, or color alone to understand content.
- Respect reduced-motion expectations by keeping motion minimal and nonessential.

## Responsive behavior

Desktop:

- Two-column hero with copy and product preview.
- Full navigation visible.
- Privacy content can use two columns.

Tablet:

- Hero and privacy sections collapse to one column.
- Product preview moves below the hero copy.

Mobile:

- Hide nonessential header links while preserving the install action.
- Stack platform preview items and install controls when needed.
- Keep tap targets comfortably sized.
- Prevent horizontal overflow except the intentionally scrollable supported-platform strip.

## Interaction states

The public page is static and has no application loading state.

- Links: default, hover, and keyboard-focus states.
- Install buttons: clear default and hover/focus states.
- Product preview controls are illustrative, not interactive, and must not imply that settings can be changed on the website.
- If an external store is unavailable, the page itself remains usable and the other store/GitHub links remain available.

## Content voice

- Short, direct, and specific.
- Prefer plain language such as "Hide short-form feeds" over marketing jargon.
- Use "FocusTube" consistently.
- Do not claim certification, auditing, or privacy guarantees beyond what the repository supports.
- Do not invent user counts, ratings, time-saved figures, or blocked-count values.

## Implementation constraints

- Static HTML and CSS only for the landing page.
- No JavaScript, analytics, tracking pixels, external runtime dependencies, or backend.
- GitHub Pages currently publishes from `main` at the repository root, so the public entry file must be root `index.html` unless Pages settings are deliberately changed later.
- Do not overwrite the extension's root `styles.css`; the landing page uses its own stylesheet.
- Store URLs and GitHub URL must remain the official existing links.
- Required repository CI, CodeQL, and release-verification checks must stay green.
- Public-page changes should be checked at desktop and mobile widths before being considered finished.

## Open questions

- [ ] Replace the illustrative extension preview with a polished real product screenshot if a stable screenshot asset is added later. **Owner:** maintainer. **Impact:** medium.
- [ ] Decide later whether project-impact numbers should remain hard-coded on the landing page or be removed to avoid stale public metrics. **Owner:** maintainer. **Impact:** low.
Empty file removed docs/.nojekyll
Empty file.
16 changes: 9 additions & 7 deletions docs/index.html → index.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,14 @@
<meta name="description" content="FocusTube blocks YouTube Shorts, Instagram Reels, TikTok, Facebook Reels and distracting LinkedIn feeds while keeping the useful parts of each site available.">
<meta name="theme-color" content="#0d0f12">
<title>FocusTube | Block Shorts, Reels and distracting feeds</title>
<link rel="stylesheet" href="styles.css">
<link rel="icon" href="icons/icon128.png">
<link rel="canonical" href="https://malekwael229.github.io/FocusTube/">
<link rel="stylesheet" href="docs/styles.css">
</head>
<body>
<header class="site-header">
<a class="brand" href="#top" aria-label="FocusTube home">
<img src="https://raw.githubusercontent.com/malekwael229/FocusTube/main/icons/icon128.png" alt="" width="30" height="30">
<img src="icons/icon128.png" alt="" width="30" height="30">
<span>FocusTube</span>
</a>
<nav aria-label="Primary navigation">
Expand Down Expand Up @@ -49,7 +51,7 @@ <h1>Use the site.<br>Skip the scroll trap.</h1>
<div class="preview-label">Extension preview</div>
<div class="popup-header">
<div class="popup-title">
<img src="https://raw.githubusercontent.com/malekwael229/FocusTube/main/icons/icon128.png" alt="" width="36" height="36">
<img src="icons/icon128.png" alt="" width="36" height="36">
<div><strong>FocusTube</strong><span>Distraction blocker</span></div>
</div>
<div class="status-pill"><span></span>Enabled</div>
Expand Down Expand Up @@ -91,13 +93,13 @@ <h1>Use the site.<br>Skip the scroll trap.</h1>
<section class="section-shell product-section" id="how-it-works">
<div class="section-heading">
<h2>Keep what you need. Remove what you don’t.</h2>
<p>FocusTube targets distracting surfaces instead of taking the lazy approach of blocking entire websites.</p>
<p>FocusTube targets distracting surfaces instead of blocking entire websites.</p>
</div>

<div class="feature-rows">
<article>
<span class="feature-number">01</span>
<div><h3>Hide short-form feeds</h3><p>Remove YouTube Shorts, Instagram Reels, Facebook Reels and other high-friction feed surfaces.</p></div>
<div><h3>Hide short-form feeds</h3><p>Remove YouTube Shorts, Instagram Reels, Facebook Reels and other distracting feed surfaces.</p></div>
</article>
<article>
<span class="feature-number">02</span>
Expand Down Expand Up @@ -126,7 +128,7 @@ <h2>Your browsing data stays yours.</h2>
<section class="section-shell install-section">
<div>
<h2>Make your browser quieter.</h2>
<p>Install FocusTube for free. Pick what disappears. Get back to what you opened the site for.</p>
<p>Install FocusTube for free, choose what disappears, and use the sites for what you opened them for.</p>
</div>
<div class="store-actions" aria-label="Install FocusTube">
<a class="primary-button" href="https://chromewebstore.google.com/detail/focustube-distraction-blo/ppdjgkniggbikifojmkindmbhppmoell">Add to Chrome</a>
Expand All @@ -139,7 +141,7 @@ <h2>Make your browser quieter.</h2>
<footer class="site-footer">
<div class="footer-inner">
<div class="brand footer-brand">
<img src="https://raw.githubusercontent.com/malekwael229/FocusTube/main/icons/icon128.png" alt="" width="26" height="26">
<img src="icons/icon128.png" alt="" width="26" height="26">
<span>FocusTube</span>
</div>
<span>Free, open source and privacy-first.</span>
Expand Down
1 change: 1 addition & 0 deletions scripts/run-test-all.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ function main() {
runSyntaxChecks();
run(process.execPath, [path.join("tests", "package-reproducibility.test.js")]);
run(process.execPath, [path.join("tests", "regression.test.js")]);
run(process.execPath, [path.join("tests", "pages-site.test.js")]);
run(process.execPath, [path.join("tests", "background-timer.test.js")]);
run(process.execPath, [path.join("tests", "playwright-smoke.test.js"), "--build-dir", chromiumBuild], {
...process.env,
Expand Down
19 changes: 19 additions & 0 deletions tests/pages-site.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
const assert = require("node:assert/strict");
const fs = require("node:fs");
const path = require("node:path");

const root = path.resolve(__dirname, "..");
const read = (file) => fs.readFileSync(path.join(root, file), "utf8");

const page = read("index.html");

assert.match(page, /<title>FocusTube \| Block Shorts, Reels and distracting feeds<\/title>/);
assert.match(page, /href="docs\/styles\.css"/);
assert.match(page, /href="https:\/\/chromewebstore\.google\.com\/detail\/focustube-distraction-blo\/ppdjgkniggbikifojmkindmbhppmoell"/);
assert.match(page, /href="https:\/\/addons\.mozilla\.org\/addon\/focus-tube\/"/);
assert.match(page, /href="https:\/\/microsoftedge\.microsoft\.com\/addons\/detail\/focustube\/emffahlehkfdlknpmpndaabhigchhoog"/);
assert.match(page, /src="icons\/icon128\.png"/);
assert.doesNotMatch(page, /<script\b/i);
assert.equal(fs.existsSync(path.join(root, "docs", "index.html")), false);

console.log("Pages entry checks passed.");