···11+# HTTP/Minimal
22+33+A constrained version of HTTP designed for serving human-readable documents without tracking, scripting, or behavioral manipulation.
44+55+## Specification
66+77+See [spec.md](spec.md) for the full specification.
88+99+## License
1010+1111+Released under [CC0 1.0 Universal](https://creativecommons.org/publicdomain/zero/1.0/) - no rights reserved.
+537
spec.md
···11+# HTTP/Minimal
22+33+**Version:** 0.1.0-draft
44+**Status:** Proposal
55+66+## Abstract
77+88+HTTP/Minimal is a constrained version of HTTP designed for serving human-readable documents without tracking, scripting, or behavioral manipulation. It is not a new protocol - it is a voluntary restriction on how HTTP is used, enforceable by clients and verifiable by automated tools.
99+1010+## Goals
1111+1212+1. **Radical simplicity.** A document is text and links. Maybe images.
1313+2. **Privacy by architecture.** No cookies, no auth headers, no state.
1414+3. **Zero JavaScript.** Not "minimal scripts" - none.
1515+4. **Works today.** Any static file server can serve compliant content.
1616+5. **Human-writable source.** Content is authored in Markdown, not markup soup.
1717+1818+## Non-Goals
1919+2020+- Replacing HTTP for applications, APIs, or dynamic content
2121+- Defining a new transport protocol
2222+- Competing with Gemini (this is HTTP; use Gemini if you want Gemini)
2323+2424+---
2525+2626+## 1. Transport Requirements
2727+2828+### 1.1 TLS Required
2929+3030+All HTTP/Minimal content MUST be served over HTTPS (TLS 1.2+, TLS 1.3 RECOMMENDED).
3131+3232+Plain HTTP requests SHOULD receive a 301 redirect to the HTTPS equivalent and nothing else.
3333+3434+### 1.2 HTTP Version
3535+3636+HTTP/1.1, HTTP/2, and HTTP/3 are all acceptable. Servers SHOULD support HTTP/2 at minimum.
3737+3838+---
3939+4040+## 2. Request Constraints
4141+4242+Compliant clients MUST NOT send the following headers:
4343+4444+| Header | Reason |
4545+|--------|--------|
4646+| `Cookie` | State tracking |
4747+| `Authorization` | Implies authenticated content |
4848+| `DNT` | Unnecessary - tracking is minimized by design |
4949+| `X-Requested-With` | AJAX patterns not applicable |
5050+| Any `X-` header | Custom headers are a slippery slope |
5151+5252+Compliant clients MUST use only these methods:
5353+5454+- `GET` - Retrieve a document
5555+- `HEAD` - Check if a document exists or has changed
5656+5757+All other methods (`POST`, `PUT`, `DELETE`, etc.) are non-compliant.
5858+5959+### 2.1 Query Strings
6060+6161+Query strings are PERMITTED but SHOULD be limited to:
6262+6363+- Pagination (`?page=2`)
6464+6565+Query strings MUST NOT be used for:
6666+6767+- Session tracking
6868+- User identification
6969+- Analytics parameters (utm_*, fbclid, etc.)
7070+7171+Compliant servers SHOULD ignore or strip unrecognized query parameters.
7272+7373+---
7474+7575+## 3. Response Constraints
7676+7777+### 3.1 Forbidden Response Headers
7878+7979+Compliant servers MUST NOT send:
8080+8181+| Header | Reason |
8282+|--------|--------|
8383+| `Set-Cookie` | State tracking |
8484+| `WWW-Authenticate` | Implies auth-gated content |
8585+| `Content-Security-Policy` | Implies executable content to policy |
8686+| `X-Frame-Options` | Embedding restrictions suggest app behavior |
8787+| `Refresh` | Client-side redirects enable tracking |
8888+8989+### 3.2 Permitted Response Headers
9090+9191+Servers SHOULD send:
9292+9393+| Header | Purpose |
9494+|--------|---------|
9595+| `Content-Type` | Required (`text/markdown; charset=utf-8`) |
9696+| `Content-Length` | Required for HTTP/1.1 |
9797+| `Last-Modified` | Caching |
9898+| `ETag` | Caching |
9999+| `Cache-Control` | Caching (SHOULD be generous; `max-age=3600` or higher) |
100100+| `Link` | Discovery (see Section 6) |
101101+102102+### 3.3 Status Codes
103103+104104+Compliant servers SHOULD limit responses to:
105105+106106+| Code | Meaning |
107107+|------|---------|
108108+| `200` | OK |
109109+| `301` | Moved Permanently |
110110+| `304` | Not Modified |
111111+| `400` | Bad Request |
112112+| `404` | Not Found |
113113+| `410` | Gone (content deliberately removed) |
114114+| `500` | Server Error |
115115+116116+Codes `302`, `303`, and `307` are NOT RECOMMENDED as they enable tracking redirects.
117117+118118+---
119119+120120+## 4. Content Format
121121+122122+HTTP/Minimal uses **Markdown** as its content format, served with Content-Type `text/markdown; charset=utf-8`.
123123+124124+### 4.1 Markdown Variant
125125+126126+HTTP/Minimal uses [CommonMark](https://commonmark.org/) as the base specification, with the following extensions PERMITTED:
127127+128128+- **Tables** - GitHub Flavored Markdown (GFM) pipe tables
129129+- **Strikethrough** - `~~text~~`
130130+- **Autolinks** - GFM automatic URL linking
131131+- **Footnotes** - `[^1]` reference-style footnotes
132132+133133+### 4.2 Permitted Syntax
134134+135135+All standard CommonMark elements:
136136+137137+- Headings (`#`, `##`, etc.)
138138+- Paragraphs
139139+- Emphasis (`*italic*`, `**bold**`)
140140+- Links (`[text](url)` or `[text][ref]`)
141141+- Images (``)
142142+- Blockquotes (`>`)
143143+- Code spans (`` `code` ``)
144144+- Code blocks (fenced or indented)
145145+- Lists (ordered and unordered)
146146+- Horizontal rules (`---`)
147147+- Hard line breaks
148148+149149+### 4.3 Forbidden Syntax
150150+151151+The following MUST NOT appear in HTTP/Minimal documents:
152152+153153+| Syntax | Reason |
154154+|--------|--------|
155155+| Raw HTML blocks | Enables script injection, tracking pixels, forms |
156156+| Raw HTML inline | Same |
157157+| `<script>` | No JavaScript |
158158+| `<iframe>` | Embedded third-party content |
159159+| `<form>` | Data collection |
160160+| `<img>` with tracking URLs | Use Markdown image syntax with compliant URLs |
161161+162162+Clients MUST strip or ignore any raw HTML encountered in Markdown source.
163163+164164+### 4.4 Image Requirements
165165+166166+Images referenced via `` syntax:
167167+168168+- MUST include alt text (the `[alt]` portion MUST NOT be empty)
169169+- SHOULD be same-origin or from trusted, non-tracking sources
170170+- MUST NOT be 1x1 tracking pixels
171171+172172+### 4.5 Link Requirements
173173+174174+Links are unrestricted in destination -HTTP/Minimal documents MAY link to any URL.
175175+176176+Clients MAY warn users when following links to non-compliant origins.
177177+178178+#### 4.5.1 URL Fragments
179179+180180+URL fragments (`#section-name`) are supported and SHOULD work as follows:
181181+182182+- When rendering Markdown to HTML, headings SHOULD receive auto-generated `id` attributes based on their text (lowercase, spaces replaced with hyphens)
183183+- Clients receiving `text/markdown` SHOULD scroll to the heading matching the fragment
184184+- Fragment matching SHOULD be case-insensitive
185185+186186+For example, `## My Section` would be reachable via `#my-section`.
187187+188188+### 4.6 Metadata
189189+190190+Document metadata SHOULD be provided via a YAML front matter block:
191191+192192+```markdown
193193+---
194194+title: My Document
195195+author: Jane Doe
196196+date: 2025-12-27
197197+lang: en
198198+---
199199+200200+# My Document
201201+202202+Content begins here.
203203+```
204204+205205+Recognized front matter fields:
206206+207207+| Field | Required | Description |
208208+|-------|----------|-------------|
209209+| `title` | RECOMMENDED | Document title |
210210+| `author` | No | Author name or identifier |
211211+| `date` | No | Publication date (ISO 8601) |
212212+| `lang` | No | Language code (BCP 47) |
213213+| `license` | No | Content license (SPDX identifier or URL) |
214214+215215+Clients SHOULD use `title` for window/tab titles and `lang` for text rendering.
216216+217217+---
218218+219219+## 5. Client Rendering
220220+221221+### 5.1 Dedicated Clients
222222+223223+HTTP/Minimal clients SHOULD:
224224+225225+1. Parse Markdown and render to styled, readable output
226226+2. Apply a legible default stylesheet (user-configurable)
227227+3. Strip any raw HTML before rendering
228228+4. Display images inline with alt text fallback
229229+5. Make links clearly navigable
230230+231231+### 5.2 Browser Rendering
232232+233233+Standard browsers receiving `text/markdown` will typically display raw source. Options for browser compatibility:
234234+235235+**Option A: Server-side rendering**
236236+237237+Servers MAY content-negotiate and serve pre-rendered HTML to browsers:
238238+239239+- Request with `Accept: text/markdown` → serve Markdown
240240+- Request with `Accept: text/html` → serve HTML rendering
241241+242242+The HTML rendering MUST be a direct transformation of the Markdown source with no additions (no scripts, no tracking, no analytics).
243243+244244+**Option B: Client-side rendering via browser extension**
245245+246246+Browser extensions may render `text/markdown` responses directly.
247247+248248+**Option C: Raw display**
249249+250250+Markdown is human-readable as source. No rendering required.
251251+252252+### 5.3 Suggested Default Styles
253253+254254+Clients SHOULD apply sensible typographic defaults:
255255+256256+- Readable font (system serif or sans-serif)
257257+- Comfortable line length (45-75 characters)
258258+- Adequate line height (1.4-1.6)
259259+- Responsive viewport handling
260260+- Respect user preferences (dark mode, font size)
261261+262262+---
263263+264264+## 6. Discovery and Verification
265265+266266+### 6.1 Well-Known Endpoint
267267+268268+Compliant servers SHOULD serve a policy document at:
269269+270270+```
271271+/.well-known/http-minimal
272272+```
273273+274274+This document is a JSON object:
275275+276276+```json
277277+{
278278+ "http_minimal": "0.1",
279279+ "compliant": true,
280280+ "scope": "/",
281281+ "contact": "mailto:admin@example.com",
282282+ "validator": "https://example.com/validation-report.json"
283283+}
284284+```
285285+286286+| Field | Required | Description |
287287+|-------|----------|-------------|
288288+| `http_minimal` | Yes | Spec version |
289289+| `compliant` | Yes | Self-attestation |
290290+| `scope` | No | Path prefix this policy applies to (default: entire origin) |
291291+| `contact` | No | Maintainer contact |
292292+| `validator` | No | URL to a third-party validation report |
293293+294294+### 6.2 Link Header
295295+296296+Responses MAY include:
297297+298298+```
299299+Link: </.well-known/http-minimal>; rel="profile"
300300+```
301301+302302+### 6.3 Compliance Badge (Optional)
303303+304304+Documents MAY include a compliance indicator:
305305+306306+```markdown
307307+---
308308+[HTTP/Minimal Compliant](/.well-known/http-minimal)
309309+```
310310+311311+---
312312+313313+## 7. Example Document
314314+315315+```markdown
316316+---
317317+title: Welcome to HTTP/Minimal
318318+author: Jane Doe
319319+date: 2025-12-27
320320+lang: en
321321+---
322322+323323+# Welcome to HTTP/Minimal
324324+325325+This is a document served over **HTTP/Minimal** - a constrained version of
326326+HTTPS for human-readable content without tracking, scripts, or manipulation.
327327+328328+## What is this?
329329+330330+HTTP/Minimal is not a new protocol. It's a voluntary restriction on how
331331+HTTP is used:
332332+333333+- HTTPS only, no exceptions
334334+- No cookies or authentication headers
335335+- No JavaScript, ever
336336+- Content is Markdown, not HTML
337337+338338+## Why Markdown?
339339+340340+Markdown is:
341341+342342+1. Human-readable as source
343343+2. Human-writable without tooling
344344+3. Transparent - tracking pixels are visible in source and enforceable by clients
345345+4. Universally supported
346346+347347+## Learn More
348348+349349+Read the full [specification](/spec) or view the
350350+[source for this page](/source/index.md).
351351+352352+---
353353+354354+*[HTTP/Minimal Compliant](/.well-known/http-minimal)*
355355+```
356356+357357+---
358358+359359+## 8. Relationship to Other Specifications
360360+361361+### Gemini Protocol
362362+363363+HTTP/Minimal shares philosophical goals with Gemini (simplicity, anti-tracking, anti-JavaScript) but differs in approach:
364364+365365+| Aspect | Gemini | HTTP/Minimal |
366366+|--------|--------|--------------|
367367+| Transport | New protocol (gemini://) | HTTPS |
368368+| Content format | text/gemini | text/markdown |
369369+| Browser support | Requires dedicated client | Works with extensions or server-side rendering |
370370+| Port | 1965 | 443 |
371371+372372+### Gemtext vs Markdown
373373+374374+Gemini's text/gemini format is simpler than Markdown (one link per line, no inline formatting). HTTP/Minimal accepts the tradeoff of a slightly more complex format for broader tooling support.
375375+376376+### Semantic Web / Microformats
377377+378378+HTTP/Minimal Markdown documents can include semantic meaning via:
379379+380380+- Structured YAML front matter
381381+- Consistent heading hierarchies
382382+- Machine-parseable date/author metadata
383383+384384+---
385385+386386+## 9. Security Considerations
387387+388388+- **No cookies** eliminates CSRF and session hijacking vectors
389389+- **No JavaScript** eliminates XSS entirely
390390+- **No forms** eliminates CSRF for data submission
391391+- **No raw HTML** prevents injection attacks
392392+- **HTTPS required** ensures transport security
393393+394394+Remaining vectors:
395395+396396+- **Malicious links** - users may still be linked to harmful external sites
397397+- **Image-based tracking** - external images can still leak requests; clients MAY block third-party images
398398+- **Cache timing** - sophisticated attackers may infer browsing history via cache timing; out of scope
399399+400400+---
401401+402402+## 10. Future Considerations
403403+404404+Items explicitly deferred for future versions:
405405+406406+- **Signed content** - integration with Signed HTTP Exchanges or content-addressed storage
407407+- **Content addressing** - integration with IPFS, AT Protocol, or content-hash URLs
408408+- **Client certificates** - Gemini-style TOFU identity without cookies
409409+- **Extended metadata** - richer front matter schemas (JSON-LD, etc.)
410410+- **Media embedding** - whether/how to handle audio and video
411411+412412+---
413413+414414+## Appendix A: Validator Pseudocode
415415+416416+```python
417417+def validate_response(response):
418418+ errors = []
419419+420420+ # Check forbidden response headers
421421+ forbidden = ['set-cookie', 'www-authenticate', 'refresh']
422422+ for header in forbidden:
423423+ if header in response.headers:
424424+ errors.append(f"Forbidden header: {header}")
425425+426426+ # Check content type
427427+ content_type = response.headers.get('content-type', '')
428428+ if not content_type.startswith('text/markdown'):
429429+ errors.append("Content-Type must be text/markdown")
430430+431431+ # Parse Markdown
432432+ doc = parse_markdown(response.body)
433433+434434+ # Check for raw HTML
435435+ if contains_raw_html(doc):
436436+ errors.append("Raw HTML is forbidden")
437437+438438+ # Check images have alt text
439439+ for image in doc.images:
440440+ if not image.alt:
441441+ errors.append(f"Image missing alt text: {image.url}")
442442+443443+ return errors
444444+```
445445+446446+---
447447+448448+## Appendix B: Content-Type Registration
449449+450450+This specification uses `text/markdown` as defined in [RFC 7763](https://datatracker.ietf.org/doc/html/rfc7763).
451451+452452+Recommended Content-Type header:
453453+454454+```
455455+Content-Type: text/markdown; charset=utf-8; variant=CommonMark
456456+```
457457+458458+---
459459+460460+## Appendix C: Migration Checklist
461461+462462+For existing sites adopting HTTP/Minimal:
463463+464464+- [ ] Enable HTTPS if not already
465465+- [ ] Convert content to Markdown (or add Markdown alongside HTML)
466466+- [ ] Configure server to serve `.md` files as `text/markdown`
467467+- [ ] Remove all analytics (Google Analytics, Plausible, etc.)
468468+- [ ] Remove comment systems or link to external discussion
469469+- [ ] Ensure all images have alt text
470470+- [ ] Ensure no raw HTML in Markdown source
471471+- [ ] Add `/.well-known/http-minimal` endpoint
472472+- [ ] Run validator against all documents
473473+- [ ] Optional: implement content negotiation for HTML clients
474474+475475+---
476476+477477+## Appendix D: Server Configuration Examples
478478+479479+### Nginx
480480+481481+```nginx
482482+location ~ \.md$ {
483483+ types { text/markdown md; }
484484+ charset utf-8;
485485+ add_header Link '</.well-known/http-minimal>; rel="profile"';
486486+487487+ # Remove forbidden headers (shouldn't exist, but defensive)
488488+ proxy_hide_header Set-Cookie;
489489+ proxy_hide_header WWW-Authenticate;
490490+}
491491+```
492492+493493+### Caddy
494494+495495+```caddyfile
496496+@markdown path *.md
497497+header @markdown Content-Type "text/markdown; charset=utf-8"
498498+header @markdown Link "</.well-known/http-minimal>; rel=\"profile\""
499499+header @markdown -Set-Cookie
500500+```
501501+502502+### Static file server (Go)
503503+504504+```go
505505+http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
506506+ if r.Method != "GET" && r.Method != "HEAD" {
507507+ http.Error(w, "Method not allowed", 405)
508508+ return
509509+ }
510510+511511+ if strings.HasSuffix(r.URL.Path, ".md") {
512512+ w.Header().Set("Content-Type", "text/markdown; charset=utf-8")
513513+ w.Header().Set("Link", "</.well-known/http-minimal>; rel=\"profile\"")
514514+ }
515515+516516+ http.FileServer(http.Dir("./public")).ServeHTTP(w, r)
517517+})
518518+```
519519+520520+---
521521+522522+## Acknowledgments
523523+524524+This specification draws inspiration from:
525525+526526+- **[Gemini Protocol](https://geminiprotocol.net/)** - for proving that radical simplicity has an audience
527527+- **["Gemini is Solutionism at its Worst"](https://xn--gckvb8fzb.com/gemini-is-solutionism-at-its-worst/)** - マリウス's critique arguing Gemini's goals could be achieved via HTTP with constraints, not a new protocol
528528+- **[CommonMark](https://commonmark.org/)** - for standardizing Markdown
529529+- **[The Web We Lost](https://www.anildash.com/2012/12/13/the-web-we-lost/)** - Anil Dash's 2012 essay on web degradation
530530+- **[Motherfucking Website](https://motherfuckingwebsite.com/)** - satirical proof that content needs nothing else
531531+- **[IndieWeb](https://indieweb.org/)** - for keeping personal publishing alive
532532+533533+---
534534+535535+## License
536536+537537+This specification is released under [CC0 1.0 Universal](https://creativecommons.org/publicdomain/zero/1.0/) - no rights reserved. Use it, fork it, improve it.