Skip to content

Commit 8ee07a8

Browse files
committed
docs(site): add GitHub Pages site with privacy policy
Adds docs/site/ (landing + privacy.html + stylesheet) and a workflow that publishes it to the gh-pages branch on push to main. Privacy URL is required for Chrome Web Store and AMO submission. README and CONTRIBUTING link the published privacy URL.
1 parent f5d01c1 commit 8ee07a8

6 files changed

Lines changed: 315 additions & 0 deletions

File tree

.github/workflows/pages.yml

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
name: Publish Pages
2+
3+
on:
4+
push:
5+
branches: [main]
6+
paths:
7+
- 'docs/site/**'
8+
- '.github/workflows/pages.yml'
9+
workflow_dispatch:
10+
11+
concurrency:
12+
group: pages
13+
cancel-in-progress: false
14+
15+
jobs:
16+
publish:
17+
runs-on: ubuntu-latest
18+
permissions:
19+
contents: write
20+
steps:
21+
- uses: actions/checkout@v5
22+
- uses: peaceiris/actions-gh-pages@v4
23+
with:
24+
github_token: ${{ secrets.GITHUB_TOKEN }}
25+
publish_branch: gh-pages
26+
publish_dir: ./docs/site
27+
force_orphan: true
28+
commit_message: "deploy: ${{ github.sha }}"
29+
user_name: "github-actions[bot]"
30+
user_email: "41898282+github-actions[bot]@users.noreply.github.com"

CONTRIBUTING.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,11 @@ CI automatically runs tests, builds Chrome and Firefox packages, and creates a G
9292

9393
### 6. Submit to Browser Stores
9494

95+
Submission requires the privacy policy URL: <https://textbundle.github.io/textbundler-extension/privacy.html>
96+
(served from `docs/site/` via the **Publish Pages** workflow → `gh-pages` branch).
97+
After the first run of that workflow, set **Settings → Pages → Source = Deploy
98+
from a branch → `gh-pages` / `(root)`** in the GitHub repo once.
99+
95100
**Firefox (AMO)**
96101

97102
1. Go to [addons.mozilla.org/developers](https://addons.mozilla.org/en-US/developers/)

README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,11 @@ Two-context event-driven pipeline:
197197
- Packages into `.textpack` via JSZip
198198
- Triggers browser download
199199

200+
## Privacy
201+
202+
TextBundler collects no data and has no analytics. See the
203+
[privacy policy](https://textbundle.github.io/textbundler-extension/privacy.html).
204+
200205
## License
201206

202207
Copyright (C) 2026 TextBundle Contributors

docs/site/index.html

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
<!doctype html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="utf-8">
5+
<meta name="viewport" content="width=device-width, initial-scale=1">
6+
<title>TextBundler — archive web pages as TextBundle .textpack</title>
7+
<meta name="description" content="Cross-browser extension that captures web pages as self-contained Markdown archives in the TextBundle .textpack format.">
8+
<link rel="stylesheet" href="style.css">
9+
</head>
10+
<body>
11+
<main>
12+
<header>
13+
<span class="eyebrow">Browser extension</span>
14+
<h1>TextBundler</h1>
15+
</header>
16+
17+
<p>
18+
TextBundler captures the article on the current web page and saves it
19+
as a self-contained <a href="https://textbundle.org/">TextBundle</a>
20+
<code>.textpack</code> archive — Markdown body plus all referenced
21+
images, packaged into a single file you can drop into any TextBundle-
22+
aware editor.
23+
</p>
24+
25+
<h2>How it works</h2>
26+
<ol>
27+
<li>Click the toolbar icon, or right-click and choose <em>Archive Page as TextBundle</em>.</li>
28+
<li>Mozilla Readability extracts the main article from the current page.</li>
29+
<li>The HTML is converted to Markdown, images are downloaded, and everything is zipped into a <code>.textpack</code> file.</li>
30+
<li>Your browser downloads the file to your default downloads folder.</li>
31+
</ol>
32+
33+
<h2>Install</h2>
34+
<p>
35+
Pre-built <code>.zip</code> packages for Chrome and Firefox are attached
36+
to every <a href="https://github.com/textbundle/textbundler-extension/releases">GitHub release</a>.
37+
Store listings are in preparation.
38+
</p>
39+
40+
<h2>Source</h2>
41+
<p>
42+
TextBundler is free software released under the GPL-3.0-only license.
43+
Source, issue tracker, and contribution guide live on
44+
<a href="https://github.com/textbundle/textbundler-extension">GitHub</a>.
45+
</p>
46+
47+
<h2>Privacy</h2>
48+
<p>
49+
TextBundler does not collect, transmit, or share any personal data.
50+
See the <a href="privacy.html">privacy policy</a> for details.
51+
</p>
52+
53+
<footer>
54+
<a href="https://github.com/textbundle/textbundler-extension">GitHub</a> ·
55+
<a href="privacy.html">Privacy</a>
56+
</footer>
57+
</main>
58+
</body>
59+
</html>

docs/site/privacy.html

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
<!doctype html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="utf-8">
5+
<meta name="viewport" content="width=device-width, initial-scale=1">
6+
<title>Privacy Policy — TextBundler</title>
7+
<meta name="description" content="TextBundler privacy policy. The extension does not collect, transmit, or share any personal data.">
8+
<link rel="stylesheet" href="style.css">
9+
</head>
10+
<body>
11+
<main>
12+
<header>
13+
<span class="eyebrow"><a href="index.html">TextBundler</a></span>
14+
<h1>Privacy Policy</h1>
15+
<p class="meta">Last updated: 2026-05-23</p>
16+
</header>
17+
18+
<h2>Summary</h2>
19+
<p>
20+
TextBundler does not collect, transmit, sell, or share any personal data.
21+
The extension has no analytics, no telemetry, no remote servers, and no
22+
user accounts. Everything happens locally in your browser.
23+
</p>
24+
25+
<h2>What the extension does</h2>
26+
<p>
27+
When you click the toolbar icon or use the context menu on the page you
28+
are currently viewing, TextBundler:
29+
</p>
30+
<ol>
31+
<li>Reads the HTML of the active tab to extract the article.</li>
32+
<li>Downloads the images referenced by that article directly from their
33+
original hosts, using your browser's normal network stack.</li>
34+
<li>Converts the HTML to Markdown and packages it together with the
35+
downloaded images into a <code>.textpack</code> file.</li>
36+
<li>Saves that file via your browser's normal download mechanism.</li>
37+
</ol>
38+
<p>
39+
Nothing is sent to the extension authors. Image requests go directly
40+
from your browser to the same servers that hosted the article — exactly
41+
as if you had right-clicked and saved each image yourself.
42+
</p>
43+
44+
<h2>Permissions and why they exist</h2>
45+
<dl>
46+
<dt><code>activeTab</code> and <code>scripting</code></dt>
47+
<dd>Inject the extraction script into the page you are viewing, only
48+
when you explicitly invoke the extension.</dd>
49+
50+
<dt><code>downloads</code></dt>
51+
<dd>Save the generated <code>.textpack</code> file to your downloads
52+
folder.</dd>
53+
54+
<dt><code>contextMenus</code></dt>
55+
<dd>Add the <em>Archive Page as TextBundle</em> entry to the right-click
56+
menu.</dd>
57+
58+
<dt><code>notifications</code></dt>
59+
<dd>Show a confirmation when an archive succeeds or fails.</dd>
60+
61+
<dt><code>storage</code></dt>
62+
<dd>Store your extension preferences (figure and table output format).
63+
Synced through your browser's built-in settings sync if you have it
64+
enabled; never sent to any third party.</dd>
65+
66+
<dt>Host permissions</dt>
67+
<dd>The extension fetches images from the same hosts that served the
68+
article you are archiving. It does not run scripts on arbitrary pages
69+
in the background; the content script is injected on demand for the
70+
single tab you invoke it on.</dd>
71+
</dl>
72+
73+
<h2>Data the extension stores</h2>
74+
<p>
75+
The only data stored by the extension is your preferences (a couple of
76+
formatting options). They live in your browser's extension storage. The
77+
extension does not store browsing history, page contents, downloaded
78+
archives, image data, URLs, or any identifier of any kind.
79+
</p>
80+
81+
<h2>Third parties</h2>
82+
<p>
83+
None. The extension communicates with no third-party services. Image
84+
downloads go directly to whichever servers the article links to — those
85+
requests are governed by those servers' own privacy policies and your
86+
browser's settings, not by TextBundler.
87+
</p>
88+
89+
<h2>Children</h2>
90+
<p>
91+
TextBundler is a general-purpose archiving tool and is not directed at
92+
children. It collects no information from anyone, including children
93+
under 13.
94+
</p>
95+
96+
<h2>Changes</h2>
97+
<p>
98+
Material changes to this policy will be published at this URL with an
99+
updated <em>Last updated</em> date and noted in the project
100+
<a href="https://github.com/textbundle/textbundler-extension/blob/main/CHANGELOG.md">changelog</a>.
101+
</p>
102+
103+
<h2>Contact</h2>
104+
<p>
105+
Open an issue on
106+
<a href="https://github.com/textbundle/textbundler-extension/issues">GitHub</a>
107+
for any privacy-related question.
108+
</p>
109+
110+
<footer>
111+
<a href="index.html">Home</a> ·
112+
<a href="https://github.com/textbundle/textbundler-extension">GitHub</a>
113+
</footer>
114+
</main>
115+
</body>
116+
</html>

docs/site/style.css

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
:root {
2+
--fg: #1a1a1a;
3+
--muted: #5a5a5a;
4+
--bg: #fafaf7;
5+
--accent: #b34700;
6+
--rule: #d8d4cc;
7+
--code-bg: #efece4;
8+
}
9+
10+
* { box-sizing: border-box; }
11+
12+
html { -webkit-text-size-adjust: 100%; }
13+
14+
body {
15+
margin: 0;
16+
padding: 2.5rem 1.25rem 4rem;
17+
font: 16px/1.6 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
18+
color: var(--fg);
19+
background: var(--bg);
20+
}
21+
22+
main {
23+
max-width: 38rem;
24+
margin: 0 auto;
25+
}
26+
27+
header {
28+
border-bottom: 1px solid var(--rule);
29+
padding-bottom: 1rem;
30+
margin-bottom: 2rem;
31+
}
32+
33+
header .eyebrow {
34+
display: block;
35+
font-size: 0.78rem;
36+
letter-spacing: 0.08em;
37+
text-transform: uppercase;
38+
color: var(--muted);
39+
margin-bottom: 0.25rem;
40+
}
41+
42+
h1 {
43+
font-size: 1.75rem;
44+
margin: 0;
45+
line-height: 1.2;
46+
}
47+
48+
h2 {
49+
font-size: 1.1rem;
50+
margin-top: 2.25rem;
51+
margin-bottom: 0.5rem;
52+
border-bottom: 1px solid var(--rule);
53+
padding-bottom: 0.25rem;
54+
}
55+
56+
h3 {
57+
font-size: 0.98rem;
58+
margin-top: 1.5rem;
59+
margin-bottom: 0.25rem;
60+
}
61+
62+
a {
63+
color: var(--accent);
64+
text-decoration: underline;
65+
text-underline-offset: 2px;
66+
}
67+
68+
a:hover { text-decoration-thickness: 2px; }
69+
70+
p, ul, ol { margin: 0.75rem 0; }
71+
72+
ul, ol { padding-left: 1.25rem; }
73+
74+
li { margin: 0.25rem 0; }
75+
76+
code, kbd {
77+
font: 0.92em ui-monospace, "SF Mono", Menlo, Consolas, monospace;
78+
background: var(--code-bg);
79+
padding: 0.1em 0.35em;
80+
border-radius: 3px;
81+
}
82+
83+
dl { margin: 1rem 0; }
84+
dt { font-weight: 600; margin-top: 0.75rem; }
85+
dd { margin: 0.15rem 0 0 0; color: var(--muted); }
86+
87+
footer {
88+
margin-top: 3rem;
89+
padding-top: 1rem;
90+
border-top: 1px solid var(--rule);
91+
font-size: 0.85rem;
92+
color: var(--muted);
93+
}
94+
95+
footer a { color: var(--muted); }
96+
97+
.meta {
98+
color: var(--muted);
99+
font-size: 0.9rem;
100+
}

0 commit comments

Comments
 (0)