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
16 changes: 16 additions & 0 deletions _cloudflare/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Cloudflare in front of 207studio.dev (plan)

Goal: fix the two is-agentic essentials GitHub Pages cannot do: `Accept: text/markdown` answers in Markdown with `Vary: Accept`, and a Markdown 404 body.

State on 2026-10-23 12:40 KST: registrar Spaceship, nameservers `launch1/launch2.spaceship.net`, DNSSEC ON (DS keyTag 27026), A = GitHub Pages 185.199.108-111.153, MX iCloud, TXT: SPF iCloud, apple-domain, anthropic-domain-verification. No Cloudflare account in Kiwi.

## Steps (유일 님 = needs login/signup; agent can do the rest once logged in)
1. 유일 님: create/log in to a Cloudflare account (Free plan, no card needed) and add site `207studio.dev`. Cloudflare imports DNS; check A×4, MX×2, TXT×3 are all there (MX/TXT "DNS only").
2. 유일 님: in Spaceship, turn DNSSEC off (remove DS record) FIRST. Wait for the DS to disappear (up to 24 h). Changing nameservers with the old DS still published breaks the domain and mail.
3. 유일 님: in Spaceship, change nameservers to the two Cloudflare gives.
4. When the zone is Active: SSL/TLS mode Full; GitHub Pages "Enforce HTTPS" stays on.
5. Deploy this worker: `npx wrangler login` (유일 님 browser) then `cd _cloudflare && npx wrangler deploy`. Route `207studio.dev/*`.
6. Optional: re-enable DNSSEC in Cloudflare and add its DS record at Spaceship.
7. Check: `curl -sI -H 'Accept: text/markdown' https://207studio.dev/` → `content-type: text/markdown`, `vary: Accept`; `curl -s -H 'Accept: text/markdown' https://207studio.dev/nope` → 404 Markdown. Then is-agentic Rescan.

Rollback: delete the worker route, or switch nameservers back to `launch1/launch2.spaceship.net` (DNS records stay at Spaceship).
68 changes: 68 additions & 0 deletions _cloudflare/worker.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
// 207studio.dev edge worker: Markdown for agents in front of GitHub Pages.
// Accept: text/markdown -> Markdown body (Vary: Accept on every response).
// Subrequests to the same hostname go to the origin (GitHub Pages) without re-entering the worker.
const NOT_FOUND_MD = `# 404: page not found

This page does not exist on 207studio.dev.

- All products: https://207studio.dev/products/
- Product list for AI agents: https://207studio.dev/llms.txt
- Full reference with prices and buy links: https://207studio.dev/llms-full.txt
- Contact: support@207studio.dev
`;

function wantsMarkdown(req) {
const a = (req.headers.get("Accept") || "").toLowerCase();
return a.includes("text/markdown") || a.includes("text/x-markdown");
}

function md(body, status = 200) {
return new Response(body, {
status,
headers: {
"Content-Type": "text/markdown; charset=utf-8",
"Vary": "Accept",
"Cache-Control": "public, max-age=300",
},
});
}

function htmlToMarkdown(html) {
let s = html.replace(/<(script|style|noscript|svg)[\s\S]*?<\/\1>/gi, "");
const t = (s.match(/<title>([\s\S]*?)<\/title>/i) || [])[1] || "";
s = s.replace(/<head[\s\S]*?<\/head>/i, "");
s = s.replace(/<h([1-6])[^>]*>([\s\S]*?)<\/h\1>/gi, (_, n, x) => `\n\n${"#".repeat(+n)} ${x}\n\n`);
s = s.replace(/<a [^>]*href="([^"]+)"[^>]*>([\s\S]*?)<\/a>/gi, (_, h, x) => `[${x}](${h})`);
s = s.replace(/<li[^>]*>/gi, "\n- ").replace(/<(p|div|section|article|tr|br)[^>]*>/gi, "\n");
s = s.replace(/<[^>]+>/g, "");
s = s.replace(/&amp;/g, "&").replace(/&lt;/g, "<").replace(/&gt;/g, ">").replace(/&quot;/g, '"').replace(/&#39;/g, "'").replace(/&nbsp;/g, " ");
s = s.split("\n").map((l) => l.trim()).join("\n").replace(/\n{3,}/g, "\n\n").trim();
return (t && !s.startsWith("# ") ? `# ${t.trim()}\n\n` : "") + s + "\n";
}

export default {
async fetch(req) {
const url = new URL(req.url);
const ORIGIN = url.origin;
const originUrl = req.url;
if (!wantsMarkdown(req) || req.method !== "GET") {
const r = await fetch(originUrl, { method: req.method, headers: req.headers, redirect: "manual" });
const out = new Response(r.body, r);
out.headers.append("Vary", "Accept");
return out;
}
if (url.pathname === "/" || url.pathname === "/index.html") {
const r = await fetch(ORIGIN + "/llms.txt");
if (r.ok) return md(await r.text());
}
const r = await fetch(originUrl, { redirect: "follow" });
if (r.status === 404) return md(NOT_FOUND_MD, 404);
const type = r.headers.get("Content-Type") || "";
if (!type.includes("text/html")) {
const out = new Response(r.body, r);
out.headers.append("Vary", "Accept");
return out;
}
return md(htmlToMarkdown(await r.text()), r.status);
},
};
7 changes: 7 additions & 0 deletions _cloudflare/wrangler.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
name = "207studio-edge"
main = "worker.js"
compatibility_date = "2026-10-01"
workers_dev = false
routes = [
{ pattern = "207studio.dev/*", zone_name = "207studio.dev" },
]
Loading