contact-guard
v1.0.0
Published
Multi-layer obfuscation for protecting emails and links on static sites from scrapers.
Maintainers
Readme
contact-guard
Multi-layer obfuscation package for protecting emails and links on static sites from scrapers.
Protection pipeline: plaintext → XOR cipher → JSON array → Base64 → ROT13
Installation
# From npm (after publishing)
npm install contact-guard
# Or link locally during development
npm linkUsage
Option A — Jekyll / plain HTML (UMD script tag)
Copy dist/contact-guard.umd.js into your Jekyll repo at assets/js/.
In _layouts/default.html, before </body>:
<script src="{{ '/assets/js/contact-guard.umd.js' | relative_url }}"></script>
<script>
ContactGuard.init({ xorKey: "sjsu_ai_2025" });
</script>Option B — ES module (Vite, Webpack, native <script type="module">)
import ContactGuard from "contact-guard";
// or named imports:
import { encode, decode, init } from "contact-guard";
ContactGuard.init({ xorKey: "sjsu_ai_2025" });Option C — Node.js / CommonJS
const { encode, decode } = require("contact-guard");
const encoded = encode("[email protected]", "sjsu_ai_2025");
const plain = decode(encoded, "sjsu_ai_2025");CLI
# Encode a single value
npx contact-guard encode --key "sjsu_ai_2025" --value "[email protected]"
# Decode to verify
npx contact-guard decode --key "sjsu_ai_2025" --value "JmV5YQRk..."
# Batch encode from a JSON file
npx contact-guard encode --key "sjsu_ai_2025" --file contacts.json --out encoded.json
# Help
npx contact-guard --helpcontacts.json format
[
{ "id": "email", "type": "email", "value": "[email protected]", "label": "Email me" },
{ "id": "github", "type": "link", "value": "https://github.com/you", "label": "GitHub" }
]The --out file will contain the encoded values plus ready-to-paste HTML snippets.
HTML element format
Place <span> elements in your HTML with these data attributes:
<span class="cg-contact"
data-cg-type="email"
data-cg-value="<encoded>"
data-cg-label="Email me"
tabindex="0"
aria-label="Email — hover to reveal">
[hover to reveal]
</span>| Attribute | Values | Description |
|-----------|--------|-------------|
| data-cg-type | email, link, text | How to render after decode |
| data-cg-value | encoded string | Output of encode() or CLI |
| data-cg-label | any string | Optional display text (overrides decoded value) |
API Reference
init(options)
Bootstraps the DOM listener. Call once after the page loads.
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| xorKey | string | required | Must match the key used to encode |
| autoReveal | boolean | true | Wire up hover/focus reveal listeners |
| honeypots | boolean | true | Inject off-screen fake addresses |
encode(plaintext, xorKey) → string
Encode a value for use as data-cg-value. Run this offline or in a build step.
decode(encoded, xorKey) → string
Reverse encode. Called automatically by init() at reveal time.
Rebuilding dist
node build.jsOutputs:
dist/contact-guard.umd.js— browser<script>tagdist/contact-guard.esm.js— ES module importdist/contact-guard.cjs.js— Node.js require()
Changing the XOR key
- Pick a new key string
- Re-run the CLI to re-encode all your values
- Update the key passed to
ContactGuard.init({ xorKey: "..." }) - Update
XOR_KEYin any local encode tooling
Security note
This runs client-side, so a determined person using DevTools can always call
ContactGuard.decode(value, key) manually. The goal is defeating automated
scrapers and harvesters, not cryptographic secrecy.
