Skip to content

Commit 24509c5

Browse files
committed
docs: about page
1 parent 1d4b854 commit 24509c5

2 files changed

Lines changed: 85 additions & 1 deletion

File tree

docs/.vitepress/config.mjs

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,30 @@
1+
import { execSync } from "node:child_process";
2+
import { dirname, join } from "node:path";
3+
import { fileURLToPath } from "node:url";
14
import llmstxt from "vitepress-plugin-llms";
25
import { withMermaid } from "vitepress-plugin-mermaid";
3-
// import { defineConfig } from "vitepress";
46

57
const GITHUB_STARS = 6632;
68

9+
const DOCS_DIR = join(dirname(fileURLToPath(import.meta.url)), "..");
10+
const gitDatesCache = new Map();
11+
const gitDates = (relativePath) => {
12+
if (gitDatesCache.has(relativePath)) return gitDatesCache.get(relativePath);
13+
let dates = null;
14+
try {
15+
const out = execSync(
16+
`git log --follow --format=%aI -- "${relativePath}"`,
17+
{ cwd: DOCS_DIR, encoding: "utf8" },
18+
).trim();
19+
if (out) {
20+
const lines = out.split("\n");
21+
dates = { published: lines.at(-1), modified: lines[0] };
22+
}
23+
} catch {}
24+
gitDatesCache.set(relativePath, dates);
25+
return dates;
26+
};
27+
728
const jsonLd = (obj) => [
829
"script",
930
{ type: "application/ld+json" },
@@ -34,10 +55,14 @@ const SOFTWARE_APPLICATION = {
3455
const ORGANIZATION = {
3556
"@context": "https://schema.org",
3657
"@type": "Organization",
58+
"@id": "https://trycap.dev/#organization",
3759
name: "Cap",
3860
url: "https://trycap.dev",
3961
logo: "https://trycap.dev/logo.png",
62+
foundingDate: "2025-01-11",
63+
founder: { "@type": "Person", name: "tiago", url: "https://tiago.zip" },
4064
sameAs: ["https://github.com/tiagozip/cap", "https://x.com/tiagozip_"],
65+
subjectOf: { "@id": "https://trycap.dev/about.html" },
4166
};
4267

4368
const FAQ_ITEMS = [
@@ -175,8 +200,31 @@ export default withMermaid({
175200
["meta", { name: "twitter:title", content: title }],
176201
["meta", { name: "twitter:description", content: description }],
177202
];
203+
const dates = gitDates(pageData.relativePath);
204+
const published = pageData.frontmatter.datePublished || dates?.published;
205+
const modified = dates?.modified;
206+
if (published) {
207+
head.push(["meta", { property: "article:published_time", content: published }]);
208+
}
209+
if (modified) {
210+
head.push(["meta", { property: "article:modified_time", content: modified }]);
211+
}
178212
if (pageData.relativePath === "index.md") {
179213
head.push(jsonLd(SOFTWARE_APPLICATION), jsonLd(ORGANIZATION), jsonLd(FAQ_PAGE));
214+
} else if (pageData.relativePath === "about.md") {
215+
head.push(
216+
jsonLd(ORGANIZATION),
217+
jsonLd({
218+
"@context": "https://schema.org",
219+
"@type": "AboutPage",
220+
"@id": "https://trycap.dev/about.html",
221+
name: "About Cap",
222+
url: "https://trycap.dev/about.html",
223+
description,
224+
mainEntity: { "@id": "https://trycap.dev/#organization" },
225+
...(modified && { dateModified: modified }),
226+
}),
227+
);
180228
} else {
181229
const bc = breadcrumbList(pageData);
182230
if (bc) head.push(jsonLd(bc));
@@ -191,6 +239,9 @@ export default withMermaid({
191239
url: canonical,
192240
about: { "@id": "https://trycap.dev/#software" },
193241
author: { "@type": "Person", name: "tiago", url: "https://tiago.zip" },
242+
publisher: { "@id": "https://trycap.dev/#organization" },
243+
...(published && { datePublished: published }),
244+
...(modified && { dateModified: modified }),
194245
}),
195246
jsonLd({
196247
"@context": "https://schema.org",

docs/about.md

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
---
2+
title: About Cap
3+
description: "Who builds Cap, the open-source, self-hosted CAPTCHA alternative: its maintainer, history, license, funding, and how to get in touch."
4+
sidebar: false
5+
---
6+
7+
# About Cap
8+
9+
**TL;DR:** Cap is a free, open-source CAPTCHA alternative that replaces visual puzzles with proof-of-work and instrumentation challenges. It's licensed under Apache 2.0 and runs entirely on your own infrastructure, so visitor data never reaches a third party.
10+
11+
## What is Cap?
12+
13+
Cap is bot protection you can read, audit, and self-host:
14+
15+
- A **~20 KB widget** that renders a single checkbox instead of image puzzles.
16+
- A **standalone server** that ships as one Docker container with a dashboard and multi-site-key support.
17+
- **Server libraries** (`@cap.js/server` and community ports) for verifying challenges in your own backend.
18+
- A **siteverify API compatible with reCAPTCHA and hCaptcha**, so migrating is mostly a URL swap.
19+
20+
The full source lives at [github.com/tiagozip/cap](https://github.com/tiagozip/cap) under the [Apache 2.0 license](https://www.apache.org/licenses/LICENSE-2.0).
21+
22+
## Why does Cap exist?
23+
24+
Mainstream CAPTCHAs either interrogate users with puzzles or profile them with fingerprinting and risk scores, and both approaches route your visitors' data through a vendor. Cap takes a different position:
25+
26+
- **Deterministic, not judgmental.** Every real user has a guaranteed path through; no classifier can silently reject someone for using a VPN or a privacy browser.
27+
- **Self-hosted, not rented.** Verification happens on your servers, which makes GDPR and CCPA answers simple. See [Compliance](./guide/compliance.md).
28+
- **Open, not promised.** Privacy claims are auditable because the code that makes decisions is public.
29+
30+
## Get in touch
31+
32+
- Bugs and feature requests: [GitHub issues](https://github.com/tiagozip/cap/issues)
33+
- Security reports and everything else: [hi@tiago.zip](mailto:hi@tiago.zip)

0 commit comments

Comments
 (0)