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
22 changes: 22 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
name: Website build

on:
pull_request:
push:
branches: [master]
workflow_dispatch:

permissions:
contents: read

jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '22'
cache: npm
- run: npm ci
- run: npm run build
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
# Papyrus website

Landing page for the [Papyrus](https://github.com/Eoic/Papyrus) project - a free, open-source e-book reader and library manager for Android, iOS, Windows, macOS, Linux, and Web.
Landing page for the [Papyrus](https://github.com/PapyrusReader/papyrus) project - a free, open-source e-book reader and library manager for Android, iOS, Windows, macOS, Linux, and Web.

## Getting Started

```bash
npm install
npm ci
npm run dev
```

This starts a local server at `http://localhost:8090` with live SCSS recompilation.

Build deployable assets with `npm run build`; output is written to `build/`.
39 changes: 19 additions & 20 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
<a href="#features" class="nav-link">Features</a>
<a href="#platforms" class="nav-link">Platforms</a>
<a href="#open-source" class="nav-link">Open source</a>
<a href="https://github.com/Eoic/Papyrus/tree/master/docs" class="nav-link" target="_blank"
<a href="https://papyrusreader.github.io/docs/" class="nav-link" target="_blank"
rel="noopener">Docs</a>
</div>

Expand Down Expand Up @@ -150,7 +150,7 @@ <h1 class="hero-headline">Your books, your data, <span class="hero-highlight">ev
</div>
<div class="trust-item">
<i class="fa-solid fa-file-lines" aria-hidden="true"></i>
<span>7 e-book formats</span>
<span>EPUB &amp; PDF reading</span>
</div>
<div class="trust-item">
<i class="fa-solid fa-eye-slash" aria-hidden="true"></i>
Expand Down Expand Up @@ -193,7 +193,7 @@ <h3 class="pillar-heading">No internet required</h3>
<h3 class="pillar-heading">Your data stays yours</h3>
</div>
<p class="pillar-body">No analytics. No tracking. No account required. Store books locally, on your own
server, or on any cloud provider you trust.</p>
server. Additional cloud provider integrations are planned.</p>
</div>

<div class="pillar-card">
Expand Down Expand Up @@ -233,10 +233,10 @@ <h3 class="feature-heading">Organize your way</h3>
<h3 class="feature-heading">Read comfortably anywhere</h3>
</div>
<ul class="feature-list">
<li>Integrated reader for EPUB, PDF, MOBI, AZW3, TXT, CBR, CBZ</li>
<li>Integrated reader for EPUB and PDF</li>
<li>Customizable typography: font, size, spacing, margins</li>
<li>Light, dark, sepia, and custom themes</li>
<li>Reading profiles for different devices and contexts</li>
<li>Light, sepia, and night reading appearances</li>
<li>Paginated and continuous scroll layouts</li>
<li>Optimized for e-ink displays</li>
</ul>
</div>
Expand Down Expand Up @@ -306,7 +306,7 @@ <h2 class="section-headline">One app. Every platform.</h2>

<noscript>
<p class="platforms-noscript">
<a href="https://github.com/Eoic/Papyrus/releases">Download Papyrus from GitHub releases</a>
<a href="https://github.com/PapyrusReader/client/releases">Download Papyrus from GitHub releases</a>
</p>
</noscript>

Expand All @@ -318,7 +318,7 @@ <h2 class="section-headline">One app. Every platform.</h2>
<section class="storage">
<div class="container">
<h2 class="section-headline">Store your books where you want</h2>
<p class="section-sub">Local storage by default. Sync through your own server, or connect any cloud provider.
<p class="section-sub">Local storage by default. Sync through your Papyrus server; additional cloud providers are planned.
</p>

<div class="storage-grid">
Expand All @@ -338,23 +338,23 @@ <h2 class="section-headline">Store your books where you want</h2>
<div class="storage-icon">
<i class="fa-brands fa-google-drive" aria-hidden="true"></i>
</div>
<span>Google Drive</span>
<span>Google Drive (planned)</span>
</div>
<div class="storage-item">
<div class="storage-icon">
<i class="fa-solid fa-cloud" aria-hidden="true"></i>
</div>
<span>WebDAV</span>
<span>WebDAV (planned)</span>
</div>
<div class="storage-item">
<div class="storage-icon">
<i class="fa-solid fa-cubes" aria-hidden="true"></i>
</div>
<span>S3-compatible</span>
<span>S3-compatible (planned)</span>
</div>
</div>

<a href="https://github.com/Eoic/Papyrus/tree/master/docs" class="storage-link" target="_blank" rel="noopener">
<a href="https://papyrusreader.github.io/docs/" class="storage-link" target="_blank" rel="noopener">
Learn more about self-hosting
<i class="fa-solid fa-arrow-right" aria-hidden="true"></i>
</a>
Expand Down Expand Up @@ -385,11 +385,11 @@ <h2 class="section-headline section-headline--light">Open source. Transparent. C
</div>

<div class="oss-actions">
<a href="https://github.com/Eoic/Papyrus" class="btn btn-light btn-lg" target="_blank" rel="noopener">
<a href="https://github.com/PapyrusReader/papyrus" class="btn btn-light btn-lg" target="_blank" rel="noopener">
<i class="fa-brands fa-github" aria-hidden="true"></i>
View on GitHub
</a>
<a href="https://github.com/Eoic/Papyrus/tree/master/docs" class="btn btn-outline-light btn-lg"
<a href="https://papyrusreader.github.io/docs/" class="btn btn-outline-light btn-lg"
target="_blank" rel="noopener">Read the documentation</a>
</div>
</div>
Expand All @@ -404,20 +404,20 @@ <h4 class="footer-heading">Product</h4>
<a href="#platforms" class="footer-link">Download</a>
<a href="#features" class="footer-link">Features</a>
<a href="#platforms" class="footer-link">Platforms</a>
<a href="https://github.com/Eoic/Papyrus/tree/master/docs" class="footer-link" target="_blank"
<a href="https://papyrusreader.github.io/docs/" class="footer-link" target="_blank"
rel="noopener">Documentation</a>
</div>
<div class="footer-col">
<h4 class="footer-heading">Community</h4>
<a href="https://github.com/Eoic/Papyrus" class="footer-link" target="_blank" rel="noopener">GitHub</a>
<a href="https://github.com/Eoic/Papyrus/blob/master/CONTRIBUTING.md" class="footer-link" target="_blank"
<a href="https://github.com/PapyrusReader/papyrus" class="footer-link" target="_blank" rel="noopener">GitHub</a>
<a href="https://github.com/PapyrusReader/client#contributing" class="footer-link" target="_blank"
rel="noopener">Contributing</a>
<a href="https://github.com/Eoic/Papyrus/projects" class="footer-link" target="_blank"
<a href="https://github.com/PapyrusReader/papyrus/issues" class="footer-link" target="_blank"
rel="noopener">Roadmap</a>
</div>
<div class="footer-col">
<h4 class="footer-heading">Legal</h4>
<a href="https://github.com/Eoic/Papyrus/blob/master/LICENSE" class="footer-link" target="_blank"
<a href="https://github.com/PapyrusReader/client/blob/master/LICENSE" class="footer-link" target="_blank"
rel="noopener">License (AGPL-3.0)</a>
<a href="#" class="footer-link">Privacy</a>
</div>
Expand All @@ -432,7 +432,6 @@ <h4 class="footer-heading">Legal</h4>
</div>
</footer>

<script src="https://unpkg.com/qr-code-styling@1.8.4/lib/qr-code-styling.js"></script>
<script src="js/main.js"></script>
</body>

Expand Down
164 changes: 18 additions & 146 deletions js/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,74 +2,18 @@
'use strict';

const THEMES = {
'light-gold': { metaColor: '#FDFAF5', qrDot: '#2D2A26' },
'dark-gold': { metaColor: '#1A1814', qrDot: '#2D2A26' },
'light-purple': { metaColor: '#FAFAFE', qrDot: '#1C1B1F' },
'dark-purple': { metaColor: '#151318', qrDot: '#1C1B1F' },
'light-gold': { metaColor: '#FDFAF5' },
'dark-gold': { metaColor: '#1A1814' },
'light-purple': { metaColor: '#FAFAFE' },
'dark-purple': { metaColor: '#151318' },
};

const DEFAULT_THEME = 'light-gold';
const VERSION = '1.2.0';
const BASE = `https://github.com/Eoic/Papyrus/releases/download/v${VERSION}`;

const PLATFORMS = {
android: {
name: 'Android',
downloadLabel: 'Download APK',
downloadUrl: `${BASE}/papyrus-v${VERSION}-android-arm64.apk`,
fileName: `papyrus-v${VERSION}-android-arm64.apk`,
fileSize: '48.3 MB',
showQr: true,
qrUrl: `${BASE}/papyrus-v${VERSION}-android-arm64.apk`,
store: { name: 'Google Play', icon: 'fa-brands fa-google-play', url: '#' },
},
ios: {
name: 'iOS',
downloadLabel: 'Download IPA',
downloadUrl: `${BASE}/papyrus-v${VERSION}-ios-arm64.ipa`,
fileName: `papyrus-v${VERSION}-ios-arm64.ipa`,
fileSize: '52.1 MB',
showQr: true,
qrUrl: `${BASE}/papyrus-v${VERSION}-ios-arm64.ipa`,
store: { name: 'App Store', icon: 'fa-brands fa-app-store', url: '#' },
},
windows: {
name: 'Windows',
downloadLabel: 'Download ZIP',
downloadUrl: `${BASE}/papyrus-v${VERSION}-windows-x64.zip`,
fileName: `papyrus-v${VERSION}-windows-x64.zip`,
fileSize: '62.1 MB',
showQr: false,
store: null,
},
macos: {
name: 'macOS',
downloadLabel: 'Download DMG',
downloadUrl: `${BASE}/papyrus-v${VERSION}-macos-universal.dmg`,
fileName: `papyrus-v${VERSION}-macos-universal.dmg`,
fileSize: '71.4 MB',
showQr: false,
store: { name: 'Mac App Store', icon: 'fa-brands fa-app-store', url: '#' },
},
linux: {
name: 'Linux',
downloadLabel: 'Download tar.gz',
downloadUrl: `${BASE}/papyrus-v${VERSION}-linux-x64.tar.gz`,
fileName: `papyrus-v${VERSION}-linux-x64.tar.gz`,
fileSize: '58.7 MB',
showQr: false,
store: null,
},
web: {
name: 'Web',
downloadLabel: 'Download ZIP',
downloadUrl: `${BASE}/papyrus-v${VERSION}-web.zip`,
fileName: `papyrus-v${VERSION}-web.zip`,
fileSize: '24.5 MB',
showQr: false,
store: null,
},
};
const RELEASES_URL = 'https://github.com/PapyrusReader/client/releases';
const PLATFORMS = Object.fromEntries([
['android', 'Android'], ['ios', 'iOS'], ['windows', 'Windows'],
['macos', 'macOS'], ['linux', 'Linux'], ['web', 'Web'],
].map(([key, name]) => [key, { name }]));

const getCurrentTheme = () =>
document.documentElement.getAttribute('data-theme') ?? DEFAULT_THEME;
Expand All @@ -94,13 +38,7 @@
document.documentElement.removeAttribute('data-theme-transitioning');
}, 350);

if (currentPlatform && PLATFORMS[currentPlatform]?.showQr) {
const container = document.querySelector(`.platform-qr-code[data-qr-target="${currentPlatform}"]`);
if (container) {
container.replaceChildren();
generateQrCode(currentPlatform);
}
}

};

const detectPlatform = () => {
Expand Down Expand Up @@ -136,98 +74,35 @@
const detectedPlatform = detectPlatform();
let currentPlatform = null;

const buildStoreBadge = (store) => {
if (!store) return null;
const badge = el('a', 'platform-store-badge', { href: store.url });
badge.appendChild(faIcon(store.icon));
const label = document.createElement('span');
label.textContent = store.name;
badge.appendChild(label);
return badge;
};

const buildPanelEl = (key) => {
const cfg = PLATFORMS[key];
if (!cfg) return null;

const inner = el('div', cfg.showQr
? 'platform-details-inner platform-details-inner--with-qr'
: 'platform-details-inner');

const inner = el('div', 'platform-details-inner');
const left = el('div', 'platform-details-left');

const header = el('div', 'platform-details-header');
const title = el('h3', 'platform-details-title');
title.textContent = cfg.name;
header.appendChild(title);
const ver = el('span', 'platform-details-version');
ver.textContent = `v${VERSION}`;
header.appendChild(ver);
left.appendChild(header);

const actions = el('div', 'platform-details-actions');
const actionsRow = el('div', 'platform-actions-row');

const dlBtn = el('a', 'platform-download-btn', { href: cfg.downloadUrl, download: '' });
dlBtn.appendChild(faIcon('fa-solid fa-download'));
const dlSpan = document.createElement('span');
dlSpan.textContent = cfg.downloadLabel;
dlBtn.appendChild(dlSpan);
actionsRow.appendChild(dlBtn);

const storeBadge = buildStoreBadge(cfg.store);

if (storeBadge)
actionsRow.appendChild(storeBadge);

const releases = el('a', 'platform-download-btn', { href: RELEASES_URL });
releases.appendChild(faIcon('fa-brands fa-github'));
const label = document.createElement('span');
label.textContent = 'Check available releases';
releases.appendChild(label);
actionsRow.appendChild(releases);
actions.appendChild(actionsRow);

const meta = el('span', 'platform-download-meta');
meta.textContent = `${cfg.fileName} \u00B7 ${cfg.fileSize}`;
meta.textContent = 'Platform support is under development. Release builds are not published yet.';
actions.appendChild(meta);
left.appendChild(actions);
inner.appendChild(left);

if (cfg.showQr) {
const qrWrap = el('div', 'platform-details-qr');
const qrBox = el('div', 'platform-qr-code', { 'data-qr-target': key });
qrWrap.appendChild(qrBox);
const qrLabel = el('span', 'platform-qr-label');
qrLabel.textContent = 'Scan to download';
qrWrap.appendChild(qrLabel);
inner.appendChild(qrWrap);
}

return inner;
};

const generateQrCode = (key) => {
if (typeof QRCodeStyling === 'undefined') return;

const cfg = PLATFORMS[key];
if (!cfg?.qrUrl) return;

const container = document.querySelector(`.platform-qr-code[data-qr-target="${key}"]`);
if (!container) return;

const theme = getCurrentTheme();
const { qrDot } = THEMES[theme] ?? {};

const qr = new QRCodeStyling({
width: 140,
height: 140,
type: 'svg',
data: cfg.qrUrl,
dotsOptions: { color: qrDot ?? '#2D2A26', type: 'rounded' },
backgroundOptions: { color: '#FFFFFF' },
cornersSquareOptions: { type: 'extra-rounded' },
cornersDotOptions: { type: 'dot' },
qrOptions: { errorCorrectionLevel: 'M' },
});

qr.append(container);
};

const collapsePanel = () => {
if (!currentPlatform) return;

Expand Down Expand Up @@ -263,9 +138,6 @@
document.querySelector(`.platform-card[data-platform="${key}"]`)
?.setAttribute('aria-expanded', 'true');

if (PLATFORMS[key]?.showQr) {
generateQrCode(key);
}
};

const onScroll = () => nav.classList.toggle('scrolled', window.scrollY > 20);
Expand Down
Loading
Loading