Skip to main content

pagevault

Password-protect semi-private content on static sites – ideal for Hugo blogs, GitHub Pages, or any static hosting.

Encrypt sensitive pages and sections while keeping navigation, styling, and public content unchanged. Deploy to GitHub Pages, Netlify, or any static host without a backend.

The Problem

You want to publish semi-private content on your static site:

  • Technical docs with client-confidential sections
  • Blog posts mixing public narratives with private thoughts
  • Educational material with solutions behind passwords
  • Shared notes that shouldn't be fully public (yet)

Traditional solutions require a backend. pagevault works with pure static hosting – your site is entirely on GitHub Pages or equivalent, no server needed.

How It Works

Mark sections with <pagevault> tags. pagevault encrypts just those sections while preserving your site's structure, styling, navigation, and scripts.

<header>Public navigation</header>

<pagevault hint="Contact me for the password">
  <h2>Private thoughts on this topic</h2>
  <p>This section is encrypted...</p>
</pagevault>

<footer>Public footer</footer>

Visitors see your site normally. When they encounter protected content, a password prompt appears. Once unlocked, the content displays beautifully. Password can be remembered in browser (configurable).

Why pagevault?

Feature pagevault Wrap entire page Hide with CSS No protection
Mixed public/private ✅ ❌ ❌ ❌
Static hosting ✅ ✅ ✅ ✅
No server ✅ ✅ ✅ ✅
Preserves structure ✅ ❌ ✅ ✅
Real encryption ✅ ✅ ❌ ❌
Viewer plugins ✅ ❌ ❌ ❌

Quick Start

1. Install

pip install pagevault

2. Mark content in your HTML

<!-- Mark manually or use the CLI -->
<pagevault>Private content here</pagevault>

Or auto-mark sections:

pagevault mark page.html -s "#private" --hint "Contact admin"

3. Initialize config

pagevault config init
# Creates .pagevault.yaml with a generated password
# Add to .gitignore!

4. Encrypt and deploy

pagevault lock index.html site/*.html -d _locked/
# Deploy _locked/ to your static host

Visitors see password prompts on protected sections. Share the password however you like – via email, in docs, Discord, etc.

Real-World Use Cases

Hugo Blog

# Mark semi-private blog posts
pagevault mark content/posts/*.md --selector ".private"

# Generate locked HTML during build
hugo -o build/
pagevault lock build/posts/ -r --css styles/pagevault.css

# Deploy to GitHub Pages
git add build/
git commit -m "Publish semi-private posts"
git push

Shared Knowledge Base

# Protect implementation details in public docs
pagevault lock docs/ -r --hint "See team wiki for password"
# Upload to Netlify

Client Projects

# Share progress with selective access
pagevault lock status-page.html -p "$CLIENT_PASSWORD"
# Send link + password to stakeholders only

Features

For Users

  • Auto-prompt: Password prompt appears automatically (optional)
  • Remember-me: Store password in browser (session or persistent)
  • Clean logout: #pagevault_logout clears stored passwords
  • Event hooks: JavaScript can react to decryption

For Developers

  • Selective encryption: Mark just what needs protecting
  • HTML structure preserved: Navigation, scripts, styles stay public
  • Custom CSS: Use your own styles for the password prompt
  • Multi-user encryption: Encrypt for different users with different passwords
  • Viewer plugins: Built-in viewers for images, PDFs, HTML, text, and Markdown
  • Configuration cascade: Command-line > env vars > .pagevault.yaml > defaults
  • Web Crypto API: Same encryption as modern browsers use

Security

  • AES-256-GCM: Military-grade AEAD encryption
  • PBKDF2-SHA256: 310,000 iterations for key derivation (OWASP recommended)
  • WebCrypto compatible: Uses standard browser APIs, no custom crypto
  • Stateless: No tracking, no analytics, all processing on-client

Installation

pip install pagevault
# or
pip install git+https://github.com/queelius/pagevault.git

Requires Python 3.10+.

CLI Reference

# Lock (encrypt marked regions or entire files)
pagevault lock page.html                  # HTML: encrypt marked regions
pagevault lock report.pdf                 # PDF: wrap entire file
pagevault lock site/                      # All files in directory
pagevault lock site/ --site               # Bundle as encrypted site
pagevault lock page.html -s "#secret"     # Encrypt only #secret element
pagevault lock page.html --pad            # Pad content to prevent size leakage

# Unlock (decrypt, returns to marked state)
pagevault unlock _locked/page.html
pagevault unlock _locked/ -r
pagevault unlock report.pdf.html --stdout -p "$SECRET" > report.pdf

# Inspect & verify
pagevault info encrypted.html             # Show metadata without password
pagevault check encrypted.html -p "pw"    # Verify password (exit 0=correct)
pagevault audit                           # Health check config & passwords

# Mark (add encryption tags)
pagevault mark page.html                  # Wrap entire body
pagevault mark page.html -s ".private"    # Wrap matching elements

# Config
pagevault config init                     # Create .pagevault.yaml
pagevault config show                     # Display current config
pagevault config where                    # Find config file

# Sync (re-encrypt for user changes)
pagevault sync _locked/ -r                # Update after password change

Configuration

Create .pagevault.yaml in your project root (add to .gitignore!):

# Encryption
password: "your-strong-passphrase"         # Required
salt: "auto-generated"                     # Regenerated on config init

# UI defaults
defaults:
  remember: "ask"                          # "none", "session", "local", "ask"
  remember_days: 0                         # 0 = no expiration
  auto_prompt: true                        # Show password prompt on load

# Styling
template:
  title: "Protected Content"               # Shown in prompt
  button_text: "Unlock"
  error_text: "Incorrect password"
  hint: "Contact admin for password"       # Default hint

# Multi-user
users:
  alice: "alice-password"
  bob: "bob-password"

Or use environment variable:

export PAGEVAULT_PASSWORD="your-password"
pagevault lock page.html

Architecture

Workflow:

CLI (cli.py)
  ↓
Config (config.py) – cascade: args > env > .pagevault.yaml > defaults
  ↓
Parser (parser.py) – HTML manipulation with BeautifulSoup/lxml
  ↓
Crypto (crypto.py) – WebCrypto-compatible AES-256-GCM
  ↓
Wrap (wrap.py) – Bundle files/sites into encrypted HTML
  ↓
Template (template.py) – Inject Web Component + JS runtime

Self-contained output: Every encrypted HTML file includes the decryption logic, no external dependencies at runtime.

Contributing

# Setup
python -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]"

# Test
pytest tests/ -v --cov=pagevault

# Lint
ruff check src/ tests/
ruff format src/ tests/

License

MIT – See LICENSE for details.

FAQ

Q: Is this safe? A: Yes. Uses AES-256-GCM and PBKDF2-SHA256 with 310k iterations. All processing is client-side, no data leaves your browser.

Q: Can I share the encrypted files publicly? A: Yes! Encryption is strong. The password is what you control – share it however you like (email, docs, Discord, etc.) or not at all.

Q: Does this work with Hugo/Next.js/Gatsby? A: Yes! Any static site generator. pagevault processes HTML files after your generator creates them.

Q: Can multiple people have different passwords? A: Yes! Use the users config to encrypt for multiple users independently.

Q: What if I forget the password? A: You'd need to re-encrypt with a new password. Store passwords safely! Consider a password manager.

Q: Can I update encrypted content? A: Decrypt with pagevault unlock, edit the HTML, then re-encrypt with pagevault lock.


Made with ❤️ for static site builders who want privacy without complexity.

Release files for pagevault 0.4.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for pagevault 0.4.2
File Size Uploaded
pagevault-0.4.2.tar.gz 243.9 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for pagevault 0.4.2
File Interpreter ABI Platform
pagevault-0.4.2-py3-none-any.whl Python 3 none any Details

Total release size: 346.8 kB

Release files / pagevault-0.4.2.tar.gz

Download URL pagevault-0.4.2.tar.gz
Size 243.9 kB
Tags Source
SHA-256 checksum
How to use checksums
143d30aab660b783253fd017f33577c09bbecb6283b647502a9e5567c4fc7aff
BLAKE2b-256 checksum
How to use checksums
33ed18cd43e42fdf2a39a72b6ee23f3f5352b405f1fbd765864d5395f899eb75
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.12.3

Release files / pagevault-0.4.2-py3-none-any.whl

Download URL pagevault-0.4.2-py3-none-any.whl
Size 103.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
86d2118f24db5604233a70f5687def3a6aab47c51bdecf240b67cd4ccbfe7c55
BLAKE2b-256 checksum
How to use checksums
bff8bdf527bd166a598a40e9a4a97d3eda0254b18d4692d51d5d419af1b83035
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.12.3

Release history Release notifications | RSS feed

This release

0.4.2 This release

2 release files

0.4.1

2 release files

0.4.0

2 release files

0.3.2

2 release files

0.3.1

2 release files

0.3.0

2 release files

0.2.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page