Commit

Author:

Hash:

Timestamp:

+896 -0 +/-22 browse

Kevin Schoon [me@kevinschoon.com]

ca9da92df120624110eab5a8e681e14f383fd10e

Mon, 06 Oct 2025 13:11:56 +0000 (1 hour ago)

automated www update
1diff --git a/public/404.html b/public/404.html
2new file mode 100644
3index 0000000..f8414f0
4--- /dev/null
5+++ b/public/404.html
6 @@ -0,0 +1,3 @@
7+ <!doctype html>
8+ <title>404 Not Found</title>
9+ <h1>404 Not Found</h1>
10 diff --git a/public/android-chrome-192x192.png b/public/android-chrome-192x192.png
11new file mode 100644
12index 0000000..f6137eb
13 Binary files /dev/null and b/public/android-chrome-192x192.png differ
14 diff --git a/public/android-chrome-512x512.png b/public/android-chrome-512x512.png
15new file mode 100644
16index 0000000..c77c2af
17 Binary files /dev/null and b/public/android-chrome-512x512.png differ
18 diff --git a/public/apple-touch-icon.png b/public/apple-touch-icon.png
19new file mode 100644
20index 0000000..aaeaa8d
21 Binary files /dev/null and b/public/apple-touch-icon.png differ
22 diff --git a/public/favicon-16x16.png b/public/favicon-16x16.png
23new file mode 100644
24index 0000000..29dd09f
25 Binary files /dev/null and b/public/favicon-16x16.png differ
26 diff --git a/public/favicon-32x32.png b/public/favicon-32x32.png
27new file mode 100644
28index 0000000..811ba56
29 Binary files /dev/null and b/public/favicon-32x32.png differ
30 diff --git a/public/favicon.ico b/public/favicon.ico
31new file mode 100644
32index 0000000..de83549
33 Binary files /dev/null and b/public/favicon.ico differ
34 diff --git a/public/img/codeberg.svg b/public/img/codeberg.svg
35new file mode 100644
36index 0000000..068702a
37--- /dev/null
38+++ b/public/img/codeberg.svg
39 @@ -0,0 +1,19 @@
40+ <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" id="svg-badge" height="168" width="564" viewBox="0 0 564 168">
41+ <defs>
42+ <linearGradient xlink:href="#a" id="b" gradientUnits="userSpaceOnUse" x1="42519.285" y1="-7078.789" x2="42575.336" y2="-6966.931" />
43+ <linearGradient id="a">
44+ <stop offset="0" stop-color="#fff" stop-opacity="0" />
45+ <stop offset=".495" stop-color="#71c2ff" />
46+ <stop offset="1" stop-color="#39aaff" />
47+ </linearGradient>
48+ </defs>
49+ <rect id="rect" ry="15.111" y="2" x="2" height="164" width="560" fill="none" stroke="#a6a6a6" stroke-width="4" stroke-linejoin="round" paint-order="fill stroke markers" />
50+ <text style="line-height:0%;-inkscape-font-specification:'Inter';marker:none" x="203.16" y="-85.813" transform="matrix(1.0087 0 0 .99138 -19.194 133.848)" color="#000" font-weight="400" font-size="11.814" font-family="Inter, 'DejaVu Sans', sans-serif" letter-spacing="0" word-spacing="0" overflow="visible" fill="#2185d0" stroke-width=".985">
51+ <tspan id="claim-svg" style="line-height:1;-inkscape-font-specification:'Inter'" x="203.16" y="-85.813" font-size="33.596">GET IT ON</tspan>
52+ </text>
53+ <path aria-label="Codeberg" d="M214.654 71.02c-8.453 0-15.047 2.79-19.803 8.369-4.803 5.577-7.215 12.943-7.215 22.096 0 7.034 1.764 13.158 5.281 18.372 4.862 7.275 12.274 10.912 22.2 10.912 6.907 0 12.922-2.516 18.049-7.548l-4.718-7.185c-4.57 2.85-8.512 4.275-11.844 4.275-5.069 0-9.112-1.91-12.12-5.729-2.847-3.638-4.271-8.004-4.271-13.097 0-5.76 1.211-10.428 3.613-14.005 2.773-4.183 6.694-6.274 11.747-6.274 3.65 0 7.684 1.574 12.11 4.728l4.734-7.546c-5.925-4.91-11.844-7.368-17.763-7.368zm167.7 0l-11.657 6.456v52.201h9.441l.925-4.091c2.843 3.455 6.844 5.183 12.03 5.183 5.238 0 9.638-1.548 13.224-4.64 4.56-4.061 6.85-10.033 6.85-17.914 0-6.122-1.547-11.033-4.634-14.732-3.523-4.184-8.38-6.275-14.612-6.275-2.226 0-4.266.418-6.105 1.274-2.348 1.09-4.176 2.607-5.462 4.546zm-62.745.183l-11.674 6.367v13.186c-2.895-2.304-6.471-3.455-10.722-3.455-4.93 0-9.16 1.606-12.667 4.82-4.692 4.304-7.056 10.427-7.056 18.37 0 5.638 1.466 10.247 4.362 13.824 3.454 4.304 8.486 6.456 15.085 6.456 2.343 0 4.622-.517 6.838-1.547 2.232-1.03 3.83-2.334 4.825-3.909l1.663 4.364h9.346zm-65.647 16.098c-6.057 0-10.956 1.878-14.718 5.636-4.139 4.123-6.206 9.52-6.206 16.188 0 5.88 1.855 10.854 5.553 14.916 4.134 4.486 9.272 6.73 15.371 6.73 5.255 0 9.84-1.759 13.783-5.275 4.75-4.183 7.125-9.641 7.125-16.371 0-5.758-1.599-10.638-4.808-14.641-3.826-4.79-9.192-7.183-16.1-7.183zm91.746 0c-5.988 0-10.914 1.94-14.819 5.82-4.314 4.245-6.477 9.609-6.477 16.096 0 6.61 1.923 11.792 5.744 15.552 4.017 4 9.596 6.002 16.758 6.002 6.647 0 12.205-1.94 16.641-5.822l-2.964-6.092c-4.368 2.426-8.56 3.637-12.572 3.637-2.842 0-5.302-.908-7.401-2.728-2.051-1.88-3.194-4.214-3.417-7.001h28.852v-4.183c0-6.003-1.6-10.885-4.809-14.643-3.693-4.427-8.884-6.638-15.536-6.638zm92.543 0c-5.978 0-10.909 1.94-14.803 5.82-4.326 4.245-6.472 9.609-6.472 16.096 0 6.61 1.907 11.792 5.733 15.552 4 4 9.585 6.002 16.753 6.002 6.658 0 12.205-1.94 16.652-5.822l-2.954-6.092c-4.389 2.426-8.587 3.637-12.588 3.637-2.837 0-5.308-.908-7.406-2.728-2.04-1.88-3.183-4.214-3.427-7.001h28.878v-4.183c0-6.003-1.605-10.885-4.814-14.643-3.709-4.427-8.879-6.638-15.552-6.638zm45.163 0c-1.838 0-3.672.485-5.462 1.455-1.727.908-2.901 2-3.512 3.272l-1.11-3.635h-9.9v41.286h11.477V100.03c.978-2.12 2.524-3.18 4.623-3.18 2.28 0 4.442 1.15 6.466 3.454l9.814-5.274c-2.71-5.154-6.844-7.73-12.396-7.73zm30.121 0c-4.883 0-9.107 1.606-12.683 4.82-4.691 4.304-7.024 10.427-7.024 18.37 0 5.577 1.435 10.186 4.336 13.824 3.4 4.304 8.188 6.456 14.351 6.456 5.064 0 8.974-2.032 11.759-6.094 0 9.094-3.342 13.642-10 13.642-4.697 0-8.921-1.213-12.683-3.638l-2.954 5.82c4.856 4.365 10.637 6.549 17.295 6.549 6.413 0 11.354-1.85 14.813-5.549 3.502-3.758 5.266-9.125 5.255-16.098v-37.01h-8.974l-.914 4.455c0-.604-.893-1.515-2.688-2.728-2.716-1.879-6.005-2.82-9.889-2.82zm-167.923 8.094c5.553 0 8.496 2.97 8.794 8.912h-17.869c.675-5.942 3.704-8.912 9.075-8.912zm92.554 0c5.547 0 8.474 2.97 8.788 8.912h-17.858c.674-5.942 3.703-8.912 9.07-8.912zm-184.204.089c5.989 0 8.98 4.547 8.98 13.64 0 8.732-2.991 13.097-8.98 13.097-5.982 0-8.98-4.365-8.98-13.096 0-9.094 2.998-13.641 8.98-13.641zm45.748 0c2.04 0 3.794.67 5.282 2.002 1.53 1.272 2.518 2.908 2.943 4.909v11.55c-.318 2.243-1.408 4.243-3.315 6.002-1.913 1.698-3.985 2.547-6.2 2.547-5.989 0-8.98-4.516-8.98-13.55 0-4.123.924-7.396 2.778-9.82 1.85-2.426 4.347-3.64 7.492-3.64zm216.312 0c1.982 0 3.762.7 5.377 2.093 1.669 1.335 2.625 2.94 2.875 4.818v10.46c0 2.607-.935 4.878-2.785 6.82-1.854 1.878-4.043 2.819-6.572 2.819-6.047 0-9.075-4.516-9.075-13.55 0-4.123.924-7.396 2.779-9.82 1.849-2.426 4.325-3.64 7.401-3.64zm-124.322.094c2.832 0 5.048 1.211 6.663 3.637 1.594 2.425 2.407 5.728 2.407 9.912 0 4.244-.866 7.58-2.598 10.006-1.727 2.424-4.07 3.637-7.019 3.637-2.295 0-4.31-.76-6.03-2.274-1.68-1.518-2.604-3.396-2.769-5.637v-9.916c0-2.606.893-4.818 2.673-6.637 1.854-1.817 4.075-2.728 6.673-2.728z" style="line-height:1.25;-inkscape-font-specification:'Tajawal Bold';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal" font-weight="700" font-size="17.899" font-family="Tajawal" letter-spacing="-.285" word-spacing="0" fill="#2185d0" />
54+ <g paint-order="stroke markers fill">
55+ <path style="font-variation-settings:normal" d="M42519.285-7078.79a.76.568 0 00-.738.675l33.586 125.888a87.182 87.182 0 0039.381-33.763l-71.565-92.52a.76.568 0 00-.664-.28z" transform="matrix(.75692 0 0 .74393 -32088.397 5317.32)" opacity=".5" fill="url(#b)" />
56+ <path d="M93.742 20.95A65.99 64.857 0 0028 85.807a65.99 64.857 0 0010.076 34.447l55.019-69.909a1.03.756 0 011.785 0l55.022 69.912a65.99 64.857 0 0010.078-34.45A65.99 64.857 0 0093.99 20.95a65.99 64.857 0 00-.248 0z" fill="#2185d0" />
57+ </g>
58+ </svg>
59\ No newline at end of file
60 diff --git a/public/img/logo.png b/public/img/logo.png
61new file mode 100644
62index 0000000..93e608e
63 Binary files /dev/null and b/public/img/logo.png differ
64 diff --git a/public/img/logo.svg b/public/img/logo.svg
65new file mode 100644
66index 0000000..cdc0267
67--- /dev/null
68+++ b/public/img/logo.svg
69 @@ -0,0 +1 @@
70+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200"><g transform="translate(0 -852.36)"><rect width="180" height="180" x="10" y="862.36" rx="8.546" ry="7.52" style="fill-opacity:.24215;fill:#e7eab7"/><path d="M159.21 52.277c0 12.686-11.082 22.97-24.752 22.97s-24.752-10.284-24.752-22.97 11.082-22.97 24.752-22.97 24.752 10.284 24.752 22.97z" style="fill-opacity:.89686;fill:#b3b3b3" transform="matrix(.6464 0 0 .69655 -38.912 967.95)"/><path d="M118.91 1020.4c.102-.453.25-.888.344-1.344a72.568 72.568 0 0 0 1.094-7.219c.248-2.444.375-4.927.375-7.437s-.127-4.993-.375-7.438-.61-4.851-1.094-7.218a72.281 72.281 0 0 0-1.813-6.97 72.276 72.276 0 0 0-2.437-6.687c-.92-2.175-1.943-4.283-3.063-6.343s-2.318-4.066-3.625-6-2.705-3.798-4.187-5.594a73.377 73.377 0 0 0-4.72-5.156c-1.644-1.645-3.36-3.237-5.155-4.72s-3.66-2.88-5.594-4.187c-1.934-1.306-3.94-2.505-6-3.625s-4.169-2.142-6.344-3.062a72.255 72.255 0 0 0-6.687-2.438 72.245 72.245 0 0 0-6.97-1.812 72.57 72.57 0 0 0-7.218-1.094c-2.445-.248-4.927-.375-7.437-.375s-4.993.127-7.438.375-4.852.61-7.219 1.094c-.456.093-.89.242-1.344.344v25.5c1.704-.552 3.345-1.23 5.125-1.594 1.595-.327 3.228-.583 4.875-.75s3.309-.25 5-.25 3.353.082 5 .25c1.648.167 3.28.423 4.875.75 3.19.652 6.257 1.604 9.188 2.844s5.737 2.77 8.344 4.53a49.125 49.125 0 0 1 7.25 5.97 49.138 49.138 0 0 1 5.969 7.25 49.135 49.135 0 0 1 4.53 8.343 48.502 48.502 0 0 1 2.845 9.188c.326 1.595.582 3.228.75 4.875s.25 3.308.25 5c0 1.691-.083 3.353-.25 5a49.126 49.126 0 0 1-.75 4.875c-.365 1.78-1.043 3.42-1.594 5.125h25.5z" style="fill-opacity:.89686;fill:#b3b3b3"/><path d="M48 874.36c-4.487 0-8.911.212-13.281.656-.92.094-1.805.294-2.719.407v29.562c1.894-.303 3.76-.68 5.688-.875 3.388-.345 6.833-.532 10.312-.532 3.478 0 6.924.187 10.312.532 3.388.344 6.72.86 10 1.53a99.75 99.75 0 0 1 18.906 5.844c3.014 1.275 5.956 2.699 8.812 4.25s5.632 3.252 8.313 5.063 5.261 3.727 7.75 5.781 4.876 4.252 7.156 6.531 4.478 4.668 6.531 7.157c2.054 2.488 3.97 5.069 5.781 7.75s3.511 5.456 5.063 8.312 2.975 5.798 4.25 8.813 2.393 6.094 3.375 9.25a99.975 99.975 0 0 1 2.469 9.656c.671 3.28 1.187 6.612 1.531 10 .344 3.388.531 6.834.531 10.313 0 3.479-.187 6.924-.531 10.312-.196 1.927-.572 3.794-.875 5.687h29.562c.112-.914.313-1.799.406-2.718.444-4.37.656-8.794.656-13.281 0-4.488-.212-8.911-.656-13.281-.444-4.37-1.134-8.675-2-12.906a129.23 129.23 0 0 0-3.187-12.47c-1.266-4.07-2.73-8.049-4.375-11.937a129.601 129.601 0 0 0-11.969-22.094c-2.336-3.458-4.85-6.79-7.5-10s-5.434-6.31-8.375-9.25-6.04-5.726-9.25-8.375-6.542-5.164-10-7.5a129.885 129.885 0 0 0-22.094-11.97 128.88 128.88 0 0 0-11.938-4.374 129.205 129.205 0 0 0-12.469-3.188c-4.231-.866-8.536-1.556-12.906-2-4.349-.48-8.773-.69-13.26-.69z" style="fill-opacity:.89686;fill:#b3b3b3"/></g></svg>
71\ No newline at end of file
72 diff --git a/public/img/minimal-favicon.png b/public/img/minimal-favicon.png
73new file mode 100644
74index 0000000..e7cdbde
75 Binary files /dev/null and b/public/img/minimal-favicon.png differ
76 diff --git a/public/img/minimal-minimal.png b/public/img/minimal-minimal.png
77new file mode 100644
78index 0000000..8f60a03
79 Binary files /dev/null and b/public/img/minimal-minimal.png differ
80 diff --git a/public/img/minimal-thumbnail.png b/public/img/minimal-thumbnail.png
81new file mode 100644
82index 0000000..e6c0478
83 Binary files /dev/null and b/public/img/minimal-thumbnail.png differ
84 diff --git a/public/img/sourcehut.svg b/public/img/sourcehut.svg
85new file mode 100644
86index 0000000..c7a12e9
87--- /dev/null
88+++ b/public/img/sourcehut.svg
89 @@ -0,0 +1,77 @@
90+ <?xml version="1.0" encoding="UTF-8" standalone="no"?>
91+ <!-- Created with Inkscape (http://www.inkscape.org/) -->
92+
93+ <svg
94+ width="300"
95+ height="80"
96+ viewBox="0 0 79.375001 21.166666"
97+ version="1.1"
98+ id="svg5"
99+ inkscape:version="1.1 (c68e22c387, 2021-05-23)"
100+ sodipodi:docname="sourcehut-black.svg"
101+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
102+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
103+ xmlns="http://www.w3.org/2000/svg"
104+ xmlns:svg="http://www.w3.org/2000/svg">
105+ <sodipodi:namedview
106+ id="namedview7"
107+ pagecolor="#505050"
108+ bordercolor="#ffffff"
109+ borderopacity="1"
110+ inkscape:pageshadow="0"
111+ inkscape:pageopacity="0"
112+ inkscape:pagecheckerboard="1"
113+ inkscape:document-units="px"
114+ showgrid="false"
115+ units="px"
116+ height="80px"
117+ inkscape:zoom="3.0930415"
118+ inkscape:cx="152.6006"
119+ inkscape:cy="77.75518"
120+ inkscape:window-width="1920"
121+ inkscape:window-height="1059"
122+ inkscape:window-x="0"
123+ inkscape:window-y="0"
124+ inkscape:window-maximized="1"
125+ inkscape:current-layer="layer1" />
126+ <defs
127+ id="defs2">
128+ <rect
129+ x="72.43578"
130+ y="4.989779"
131+ width="233.3009"
132+ height="93.363552"
133+ id="rect22993" />
134+ <rect
135+ x="76.460692"
136+ y="7.5029808"
137+ width="210.43456"
138+ height="46.880685"
139+ id="rect5098" />
140+ </defs>
141+ <g
142+ inkscape:label="Layer 1"
143+ inkscape:groupmode="layer"
144+ id="layer1">
145+ <path
146+ d="m 10.58314,1.3501934 c -5.1005652,0 -9.23314,4.1325746 -9.23314,9.2331386 0,5.100566 4.1325748,9.233141 9.23314,9.233141 5.100565,0 9.23314,-4.132575 9.23314,-9.233141 0,-5.100564 -4.132575,-9.2331386 -9.23314,-9.2331386 z m 0,16.6792216 c -4.1139596,0 -7.4460807,-3.332121 -7.4460807,-7.446083 0,-4.1139582 3.3321211,-7.4460793 7.4460807,-7.4460793 4.11396,0 7.446082,3.3321211 7.446082,7.4460793 0,4.113962 -3.332122,7.446083 -7.446082,7.446083 z"
147+ id="path49"
148+ style="stroke-width:0.0372303" />
149+ <text
150+ xml:space="preserve"
151+ transform="scale(0.26458333)"
152+ id="text22991"
153+ style="fill:black;fill-opacity:1;line-height:1.25;stroke:none;font-family:sans-serif;font-style:normal;font-weight:normal;font-size:40px;white-space:pre;shape-inside:url(#rect22993)" />
154+ <text
155+ xml:space="preserve"
156+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:11.2889px;line-height:1.25;font-family:'DejaVu Sans';-inkscape-font-specification:'DejaVu Sans, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583"
157+ x="22.349714"
158+ y="13.896598"
159+ id="text29885"><tspan
160+ sodipodi:role="line"
161+ id="tspan29883"
162+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:11.2889px;font-family:'DejaVu Sans';-inkscape-font-specification:'DejaVu Sans, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;stroke-width:0.264583"
163+ x="22.349714"
164+ y="13.896598">sourcehut</tspan></text>
165+ </g>
166+ </svg>
167 diff --git a/public/index.html b/public/index.html
168new file mode 100644
169index 0000000..f629f65
170--- /dev/null
171+++ b/public/index.html
172 @@ -0,0 +1,73 @@
173+ <!DOCTYPE html>
174+ <html lang="en-US">
175+ <head>
176+ <meta charset="UTF-8" />
177+ <meta http-equiv="X-UA-Compatible" content="IE=edge" />
178+ <meta name="viewport" content="width=device-width, initial-scale=1" />
179+ <title></title>
180+ <meta
181+ name="description"
182+ itemprop="about"
183+ content="ForgeFeed Specifications"
184+ />
185+ <link rel="stylesheet" href="https://forge-feed.org/styles.css" />
186+ </head>
187+
188+ <body>
189+ <div class="wrapper">
190+ <header>
191+ <a href="https://forge-feed.org">
192+ <img
193+ src="https://forge-feed.org/img/logo.svg"
194+ class="site-logo"
195+ alt="Logo"
196+ width="275px"
197+ height="auto"
198+ /></a>
199+
200+ <p>ForgeFeed Specifications</p>
201+
202+
203+ <a href="https://codeberg.org/ayllu/forge-feed">
204+ <img
205+ src="https://forge-feed.org/img/codeberg.svg"
206+ class="site-logo"
207+ alt="Logo"
208+ />
209+ </a>
210+
211+ <a href="https://git.sr.ht/~kevinschoon/forge-feed">
212+ <img
213+ src="https://forge-feed.org/img/sourcehut.svg"
214+ class="site-logo sourcehut"
215+ alt="Logo"
216+ />
217+ </a>
218+ </header>
219+
220+ <section>
221+ <h1>Forge-Feed</h1>
222+ <p><strong>Please note that these specifications are currently PROVISIONAL
223+ and should not be implemented.</strong></p>
224+ <p>ForgeFeed is a collection of specifications and recommendations which when
225+ implemented can enhance interoperability and content discovery of different
226+ <a href="https://en.wikipedia.org/wiki/Forge_(software)">code forges</a>
227+ across the internet.</p>
228+ <p>NOTE that all specifications provided below MAY be implemented indepedenantly
229+ at the descrescion of the developer however it is a recommended that a server
230+ implement them all for maximum effect.</p>
231+ <p>The following specifications are currently covered:</p>
232+ <ul>
233+ <li><a href="/webfinger-project">WebFinger Project Identification</a> - Identify Software Projects via WebFinger</li>
234+ <li><a href="/webfinger-repository">WebFinger Repository Identification</a> - Identify VCS Repository Content via WebFinger</li>
235+ <li><a href="/project-atom-feed">Atom Feed Project Discovery</a> - Subscribe to a forge over Atom</li>
236+ </ul>
237+
238+ </section>
239+
240+ <footer>
241+ <p><small>.</small></p>
242+ </footer>
243+ </div>
244+ </body>
245+ </html>
246 diff --git a/public/project-atom-feed/index.html b/public/project-atom-feed/index.html
247new file mode 100644
248index 0000000..376244e
249--- /dev/null
250+++ b/public/project-atom-feed/index.html
251 @@ -0,0 +1,170 @@
252+ <!DOCTYPE html>
253+ <html lang="en-US">
254+ <head>
255+ <meta charset="UTF-8" />
256+ <meta http-equiv="X-UA-Compatible" content="IE=edge" />
257+ <meta name="viewport" content="width=device-width, initial-scale=1" />
258+ <title></title>
259+ <meta
260+ name="description"
261+ itemprop="about"
262+ content="ForgeFeed Specifications"
263+ />
264+ <link rel="stylesheet" href="https://forge-feed.org/styles.css" />
265+ </head>
266+
267+ <body>
268+ <div class="wrapper">
269+ <header>
270+ <a href="https://forge-feed.org">
271+ <img
272+ src="https://forge-feed.org/img/logo.svg"
273+ class="site-logo"
274+ alt="Logo"
275+ width="275px"
276+ height="auto"
277+ /></a>
278+
279+ <p>ForgeFeed Specifications</p>
280+
281+
282+ <a href="https://codeberg.org/ayllu/forge-feed">
283+ <img
284+ src="https://forge-feed.org/img/codeberg.svg"
285+ class="site-logo"
286+ alt="Logo"
287+ />
288+ </a>
289+
290+ <a href="https://git.sr.ht/~kevinschoon/forge-feed">
291+ <img
292+ src="https://forge-feed.org/img/sourcehut.svg"
293+ class="site-logo sourcehut"
294+ alt="Logo"
295+ />
296+ </a>
297+ </header>
298+
299+ <section>
300+ <h1>Atom Feed</h1>
301+ <h1 id="atom-feeds">Atom Feeds</h1>
302+ <p>Your forge should expose an <a href="https://www.rfc-editor.org/rfc/rfc4287">Atom</a>
303+ feed in order for other peers to subscribe to interesting code projects that
304+ are developed on your forge. The server should expose projects ordered by those
305+ which have been recently updated. THe heuristic you use to determine what has
306+ been updated depends on your forge. A common way to do this may be to simply
307+ look at your VCS's concept of a commit and order updates with that.</p>
308+ <h2 id="determine-if-a-host-supports-forge-feed">Determine if a Host Supports Forge Feed</h2>
309+ <p>In order to participate in ForgeFeed your forge MUST present an HTML link
310+ element such as below at the root domain of your forge. For example,
311+ <code>code.example.org</code> MUST have a link element present in it's html header:</p>
312+ <pre data-lang="html" style="background-color:#2b303b;color:#c0c5ce;" class="language-html "><code class="language-html" data-lang="html"><span>&lt;</span><span style="color:#bf616a;">html</span><span>&gt;
313+ </span><span> &lt;</span><span style="color:#bf616a;">head</span><span>&gt;
314+ </span><span> &lt;</span><span style="color:#bf616a;">title</span><span>&gt;My Forge&lt;/</span><span style="color:#bf616a;">title</span><span>&gt;
315+ </span><span> &lt;</span><span style="color:#bf616a;">link
316+ </span><span> </span><span style="color:#d08770;">rel</span><span>=&quot;</span><span style="color:#a3be8c;">alternate</span><span>&quot;
317+ </span><span> </span><span style="color:#d08770;">type</span><span>=&quot;</span><span style="color:#a3be8c;">application/atom+xml</span><span>&quot;
318+ </span><span> </span><span style="color:#d08770;">title</span><span>=&quot;</span><span style="color:#a3be8c;">Recent Forge Activity</span><span>&quot;
319+ </span><span> </span><span style="color:#d08770;">href</span><span>=&quot;</span><span style="color:#a3be8c;">https://code.example.org/firehose.xml</span><span>&quot; /&gt;
320+ </span><span> </span><span style="color:#65737e;">&lt;!-- index-url refers to the RSS link on the current webpage which contains forge updates --&gt;
321+ </span><span> &lt;</span><span style="color:#bf616a;">meta </span><span style="color:#d08770;">name</span><span>=&quot;</span><span style="color:#a3be8c;">forge-feed:index-url</span><span>&quot; </span><span style="color:#d08770;">content</span><span>=&quot;</span><span style="color:#a3be8c;">https://code.example.org/firehose.xml</span><span>&quot;/&gt;
322+ </span><span> &lt;/</span><span style="color:#bf616a;">head</span><span>&gt;
323+ </span><span> &lt;</span><span style="color:#bf616a;">body</span><span>&gt;
324+ </span><span> ...
325+ </span><span> &lt;/</span><span style="color:#bf616a;">body</span><span>&gt;
326+ </span><span>&lt;/</span><span style="color:#bf616a;">html</span><span>&gt;
327+ </span></code></pre>
328+ <p>The link MAY have a title of "Recent Forge Activity" such that it uniquely
329+ identifies this feed as being related to forge updates. A server MUST provide a
330+ meta tag with the name forge-feed:index where the content of the tag matches
331+ the href of an Atom link listed on this page which should be used for indexing
332+ by external crawlers. Applications which rely on the forge-feed:index meta
333+ tag MUST stop crawling the serving website if this tag is no longer present
334+ in the pages HTML.</p>
335+ <h3 id="an-example-feed">An example Feed</h3>
336+ <p>Below is an example Atom feed with an optional repository section (described below).</p>
337+ <pre data-lang="xml" style="background-color:#2b303b;color:#c0c5ce;" class="language-xml "><code class="language-xml" data-lang="xml"><span>&lt;?</span><span style="color:#bf616a;">xml </span><span style="color:#d08770;">version</span><span>=&quot;</span><span style="color:#a3be8c;">1.0</span><span>&quot; </span><span style="color:#d08770;">encoding</span><span>=&quot;</span><span style="color:#a3be8c;">utf-8</span><span>&quot;?&gt;
338+ </span><span> &lt;</span><span style="color:#bf616a;">feed </span><span style="color:#d08770;">xmlns</span><span>=&quot;</span><span style="color:#a3be8c;">http://www.w3.org/2005/Atom</span><span>&quot;
339+ </span><span> </span><span style="color:#d08770;">xmlns:forge-feed</span><span>=&quot;</span><span style="color:#a3be8c;">http://forge-feed.org/project-atom-feed</span><span>&quot;&gt;
340+ </span><span>
341+ </span><span> &lt;</span><span style="color:#bf616a;">title</span><span>&gt;Acme Forge Firehose&lt;/</span><span style="color:#bf616a;">title</span><span>&gt;
342+ </span><span> &lt;</span><span style="color:#bf616a;">subtitle</span><span>&gt;Recent Project Updates @ Acme Forge&lt;/</span><span style="color:#bf616a;">subtitle</span><span>&gt;
343+ </span><span> &lt;</span><span style="color:#bf616a;">link </span><span style="color:#d08770;">href</span><span>=&quot;</span><span style="color:#a3be8c;">https://code.example.org/firehose.xml</span><span>&quot; </span><span style="color:#d08770;">rel</span><span>=&quot;</span><span style="color:#a3be8c;">self</span><span>&quot; /&gt;
344+ </span><span> &lt;</span><span style="color:#bf616a;">link </span><span style="color:#d08770;">href</span><span>=&quot;</span><span style="color:#a3be8c;">https://code.example.org/</span><span>&quot; /&gt;
345+ </span><span> &lt;</span><span style="color:#bf616a;">id</span><span>&gt;urn:uuid:44decbfc-ec17-42fa-994e-67dc13029072&lt;/</span><span style="color:#bf616a;">id</span><span>&gt;
346+ </span><span> &lt;</span><span style="color:#bf616a;">updated</span><span>&gt;2025-06-18T11:23:02Z&lt;/</span><span style="color:#bf616a;">updated</span><span>&gt;
347+ </span><span>
348+ </span><span> &lt;</span><span style="color:#bf616a;">entry</span><span>&gt;
349+ </span><span> &lt;</span><span style="color:#bf616a;">title</span><span>&gt;Spartacus Game&lt;/</span><span style="color:#bf616a;">title</span><span>&gt;
350+ </span><span> &lt;</span><span style="color:#bf616a;">link </span><span style="color:#d08770;">href</span><span>=&quot;</span><span style="color:#a3be8c;">https://code.example.org/spartacus</span><span>&quot; /&gt;
351+ </span><span> &lt;</span><span style="color:#bf616a;">id</span><span>&gt;urn:uuid:51b2ad2b-34ff-4a69-9f45-a300bf296d05&lt;/</span><span style="color:#bf616a;">id</span><span>&gt;
352+ </span><span> &lt;</span><span style="color:#bf616a;">published</span><span>&gt;2025-06-18T11:23:02Z&lt;/</span><span style="color:#bf616a;">published</span><span>&gt;
353+ </span><span> &lt;</span><span style="color:#bf616a;">updated</span><span>&gt;2025-06-18T11:23:02Z&lt;/</span><span style="color:#bf616a;">updated</span><span>&gt;
354+ </span><span> &lt;</span><span style="color:#bf616a;">summary</span><span>&gt;A Game Engine </span><span style="background-color:#bf616a;color:#2b303b;">&amp;</span><span> Text Adventure Written in FORTRAN 77&lt;/</span><span style="color:#bf616a;">summary</span><span>&gt;
355+ </span><span> &lt;</span><span style="color:#bf616a;">forge-feed:project</span><span>&gt;project:spartacus&lt;/</span><span style="color:#bf616a;">forge-feed:project</span><span>&gt;
356+ </span><span> &lt;/</span><span style="color:#bf616a;">entry</span><span>&gt;
357+ </span><span>&lt;/</span><span style="color:#bf616a;">feed</span><span>&gt;
358+ </span></code></pre>
359+ <h3 id="forgefeed-extension">ForgeFeed Extension</h3>
360+ <p>In order to facilitate discovery by external indexes it is highly recommended
361+ that your server implement the webfinger <a href="/webfinger-project">project specification</a>
362+ so that repository indexes may populate their state with rich information
363+ about code repositories hosted on your server.</p>
364+ <p>The extension currently supports only a single field called <code>project</code>.</p>
365+ <pre data-lang="xml" style="background-color:#2b303b;color:#c0c5ce;" class="language-xml "><code class="language-xml" data-lang="xml"><span>&lt;</span><span style="color:#bf616a;">forge-feed:project</span><span>&gt;project:spartacus&lt;/</span><span style="color:#bf616a;">forge-feed:project</span><span>&gt;
366+ </span></code></pre>
367+ <p>If the host section of the URI is included that is MUST match domain name
368+ of the server which is providing the feed.</p>
369+ <h3 id="security-concerns">Security Concerns</h3>
370+ <h4 id="private-projects">Private Projects</h4>
371+ <p>Forge-feed enabled Atom feeds have no support for sharing private projects
372+ and any project that is not shared publicly on the internet must be hidden
373+ from the Atom activity feed stream. If your forge provides the ability to change
374+ a project from public to private it must be understood that clients may
375+ already have cached versions of your project data.</p>
376+ <h3 id="recommendations-for-enumerating-project-events">Recommendations for Enumerating Project Events</h3>
377+ <h4 id="specify-a-maximum-timeframe">Specify a Maximum Timeframe</h4>
378+ <p>Your activity feed should not include project events that are older than 1
379+ week.</p>
380+ <h4 id="project-items-should-be-unique">Project Items SHOULD be Unique</h4>
381+ <p>Although it is permitted to return duplicate projects the feed SHOULD only
382+ return unique projects in a given window.</p>
383+ <h4 id="event-clamping">Event "Clamping"</h4>
384+ <p>It may be undesirable to enumerate project events items with the simple
385+ heuristic of</p>
386+ <pre style="background-color:#2b303b;color:#c0c5ce;"><code><span>end = time.now()
387+ </span><span>start = end - 6h
388+ </span><span>
389+ </span><span>events = project_events_between(start, end)
390+ </span></code></pre>
391+ <p>Because the oldest project events will fall out of the time window on
392+ subsequent queries by feed readers. This can cause some feed readers to
393+ frequently request new content from your server. Instead events can be
394+ "clamped" within a certain time period. For example you may choose to
395+ publish four buckets of updates per day:</p>
396+ <pre style="background-color:#2b303b;color:#c0c5ce;"><code><span>00:00:00 06:00:00
397+ </span><span>06:00:00 12:00:00
398+ </span><span>12:00:00 18:00:00
399+ </span><span>18:00:00 00:00:00
400+ </span><span>
401+ </span><span>For example if the current time is 2021-03-05 13:00:55 UTC you could use
402+ </span><span>the following example to return a summary of project events from the
403+ </span><span>previous time bucket.
404+ </span><span>
405+ </span><span>now = time.now()
406+ </span><span>start = now.set_time(&quot;06:00:00&quot;)
407+ </span><span>end = now.set_time(&quot;12:00:00&quot;)
408+ </span><span>
409+ </span><span>events = project_events_between(start, end)
410+ </span></code></pre>
411+ <p>This approach with a TTL value of 60 (minutes) will reduce excess requests
412+ from some readers but allow all clients to receive timely updates.</p>
413+
414+ </section>
415+
416+ <footer>
417+ <p><small>.</small></p>
418+ </footer>
419+ </div>
420+ </body>
421+ </html>
422 diff --git a/public/robots.txt b/public/robots.txt
423new file mode 100644
424index 0000000..a2e9da9
425--- /dev/null
426+++ b/public/robots.txt
427 @@ -0,0 +1,4 @@
428+ User-agent: *
429+ Disallow:
430+ Allow: /
431+ Sitemap: https://forge-feed.org/sitemap.xml
432 diff --git a/public/site.webmanifest b/public/site.webmanifest
433new file mode 100644
434index 0000000..06d341a
435--- /dev/null
436+++ b/public/site.webmanifest
437 @@ -0,0 +1,19 @@
438+ {
439+ "name": "",
440+ "short_name": "",
441+ "icons": [
442+ {
443+ "src": "/android-chrome-192x192.png",
444+ "sizes": "192x192",
445+ "type": "image/png"
446+ },
447+ {
448+ "src": "/android-chrome-512x512.png",
449+ "sizes": "512x512",
450+ "type": "image/png"
451+ }
452+ ],
453+ "theme_color": "#ffffff",
454+ "background_color": "#ffffff",
455+ "display": "standalone"
456+ }
457 diff --git a/public/sitemap.xml b/public/sitemap.xml
458new file mode 100644
459index 0000000..cc6fbee
460--- /dev/null
461+++ b/public/sitemap.xml
462 @@ -0,0 +1,15 @@
463+ <?xml version="1.0" encoding="UTF-8"?>
464+ <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
465+ <url>
466+ <loc>https://forge-feed.org/</loc>
467+ </url>
468+ <url>
469+ <loc>https://forge-feed.org/project-atom-feed/</loc>
470+ </url>
471+ <url>
472+ <loc>https://forge-feed.org/webfinger-project/</loc>
473+ </url>
474+ <url>
475+ <loc>https://forge-feed.org/webfinger-repository/</loc>
476+ </url>
477+ </urlset>
478 diff --git a/public/styles.css b/public/styles.css
479new file mode 100644
480index 0000000..85b557a
481--- /dev/null
482+++ b/public/styles.css
483 @@ -0,0 +1 @@
484+ .wrapper{width:860px;margin:0 auto}header{width:170px;float:left;position:fixed;-webkit-font-smoothing:subpixel-antialiased}body{background-color:#fff;padding:50px;font:14px/1.5 "Noto Sans","Helvetica Neue",Helvetica,Arial,sans-serif;color:#222;font-weight:400}h1,h2,h3,h4,h5,h6{color:#222;margin:0 0 20px}p,ul,ol,table,pre,dl{margin:0 0 20px}h1,h2,h3{line-height:1.1}h1{font-size:28px}a{color:#267cb9;text-decoration:none}a:hover,a:focus{color:salmon}a small{font-size:11px;color:#000;margin-top:-.3em;display:block}a:hover small{color:#777}strong{color:#222;font-weight:700}section{width:600px;float:right;padding-bottom:50px}small{font-size:11px}hr{border:0;background:#e5e5e5;height:1px;margin:0 0 20px}footer{width:270px;float:left;position:fixed;bottom:50px;-webkit-font-smoothing:subpixel-antialiased}pre{padding:8px 15px;border-radius:5px;border:1px solid #e5e5e5;overflow-x:auto}ul.downloads{list-style:none;height:40px;padding:0;background:#f4f4f4;border-radius:5px;border:1px solid #e0e0e0;width:270px}.downloads li{width:89px;float:left;border-right:1px solid #e0e0e0;height:40px}.downloads li:first-child a{border-radius:5px 0 0 5px}.downloads li:last-child a{border-radius:0 5px 5px 0}.downloads a{line-height:1;font-size:11px;display:block;text-align:center;padding-top:6px;height:34px}.downloads a:hover,.downloads a:focus{font-weight:bold}.downloads ul a:active{background-color:#f0f0f0}.downloads li+li+li{border-right:none;width:89px}.downloads a strong{font-size:14px;display:block;color:#222}.site-logo{margin-bottom:1rem;width:100%}@media print,screen and (max-width: 960px){div.wrapper{width:auto;margin:0}header,section,footer{float:none;position:static;width:auto}header{padding-right:320px}section{border:1px solid #e5e5e5;border-width:1px 0;padding:20px 0;margin:0 0 20px}header a small{display:inline}header ul{position:absolute;right:50px;top:52px}}@media print,screen and (max-width: 720px){body{word-wrap:break-word}header{padding:0}header ul,header p.view{position:static;margin:1rem auto}pre,code{word-wrap:normal;text-wrap:wrap}}@media print,screen and (max-width: 480px){body{padding:15px}.downloads{width:100%;margin:1rem auto}.downloads li,.downloads li+li+li{width:33%}}@media print{body{padding:.4in;font-size:12pt;color:#444}}::selection{background:#639;color:#fff}table{margin:1rem auto;border-collapse:collapse}table thead th,table tfoot th{color:#202020;background:rgba(0,0,0,.15)}table caption{padding:.5em}table th,table td{padding:.5em;border:1px solid #e5e5e5}pre,code{font-family:monospace}code{border-radius:3px}pre{overflow:auto}pre code{background-color:rgba(0,0,0,0);color:inherit}@media (prefers-color-scheme: dark){.sourcehut{filter:invert(100%)}body{background-color:#222;color:#fff}strong{color:#fff}h1,h2,h3,h4,h5,h6{color:#fff}a small{color:#fff}}
485\ No newline at end of file
486 diff --git a/public/webfinger-project/index.html b/public/webfinger-project/index.html
487new file mode 100644
488index 0000000..3e788dd
489--- /dev/null
490+++ b/public/webfinger-project/index.html
491 @@ -0,0 +1,289 @@
492+ <!DOCTYPE html>
493+ <html lang="en-US">
494+ <head>
495+ <meta charset="UTF-8" />
496+ <meta http-equiv="X-UA-Compatible" content="IE=edge" />
497+ <meta name="viewport" content="width=device-width, initial-scale=1" />
498+ <title></title>
499+ <meta
500+ name="description"
501+ itemprop="about"
502+ content="ForgeFeed Specifications"
503+ />
504+ <link rel="stylesheet" href="https://forge-feed.org/styles.css" />
505+ </head>
506+
507+ <body>
508+ <div class="wrapper">
509+ <header>
510+ <a href="https://forge-feed.org">
511+ <img
512+ src="https://forge-feed.org/img/logo.svg"
513+ class="site-logo"
514+ alt="Logo"
515+ width="275px"
516+ height="auto"
517+ /></a>
518+
519+ <p>ForgeFeed Specifications</p>
520+
521+
522+ <a href="https://codeberg.org/ayllu/forge-feed">
523+ <img
524+ src="https://forge-feed.org/img/codeberg.svg"
525+ class="site-logo"
526+ alt="Logo"
527+ />
528+ </a>
529+
530+ <a href="https://git.sr.ht/~kevinschoon/forge-feed">
531+ <img
532+ src="https://forge-feed.org/img/sourcehut.svg"
533+ class="site-logo sourcehut"
534+ alt="Logo"
535+ />
536+ </a>
537+ </header>
538+
539+ <section>
540+ <h1>Project Discovery via WebFinger</h1>
541+ <p>A project refers to a software project which may contain multiple repositories
542+ as well as other resources such as mailing lists, bug trackers, links to
543+ chatrooms, etc. NOTE that some forges do not make a distinction between a
544+ project and a repository. If your forge does not then you MAY choose to expose
545+ repositories as a project with a single repository resource link.</p>
546+ <h1 id="project-uri">Project URI</h1>
547+ <p>A project URI identifies a software project and optionally the host that is
548+ resides on. This value is similar to
549+ <a href="https://datatracker.ietf.org/doc/html/rfc7565">RFC7565</a>. The slug and hostname
550+ part MUST match the URI path specification as defined in
551+ <a href="https://www.rfc-editor.org/rfc/rfc3986#section-3.3">RFC3986-3.3</a> while the
552+ hostname, if specified, must match
553+ <a href="https://www.rfc-editor.org/rfc/rfc3986#section-3.2.2">RFC3986-3.2.2</a>.</p>
554+ <pre style="background-color:#2b303b;color:#c0c5ce;"><code><span>project-uri = prefix slug hostname
555+ </span><span>
556+ </span><span>prefix = &quot;project:&quot;
557+ </span><span>slug = rfc3986-path
558+ </span><span>hostname = [@ rfc3986-hostname]
559+ </span></code></pre>
560+ <h3 id="slug">Slug</h3>
561+ <p>The Slug represents a unique string that identifies a project at a particular code forge.</p>
562+ <h3 id="hostname">Hostname</h3>
563+ <p>If the hostname part is missing then the address of the server receiving the
564+ query is assumed. For example the following two queries are equivalent:</p>
565+ <pre data-lang="text" style="background-color:#2b303b;color:#c0c5ce;" class="language-text "><code class="language-text" data-lang="text"><span>https://example.org/.well-known/webfinger?resource=project:spartacus
566+ </span><span>https://example.org/.well-known/webfinger?resource=project:spartacus@example.org
567+ </span></code></pre>
568+ <p>TODO: Make this an actual spec, for now, some Python:</p>
569+ <pre data-lang="python" style="background-color:#2b303b;color:#c0c5ce;" class="language-python "><code class="language-python" data-lang="python"><span style="color:#b48ead;">from </span><span>urllib.parse </span><span style="color:#b48ead;">import </span><span>urlparse, quote_plus
570+ </span><span>
571+ </span><span style="color:#b48ead;">def </span><span style="color:#8fa1b3;">from_string</span><span>(</span><span style="color:#bf616a;">text</span><span>):
572+ </span><span> url = </span><span style="color:#bf616a;">urlparse</span><span>(text)
573+ </span><span> </span><span style="color:#b48ead;">if </span><span>not url.path:
574+ </span><span> </span><span style="color:#b48ead;">return </span><span>(</span><span style="color:#d08770;">None</span><span>, </span><span style="color:#d08770;">None</span><span>)
575+ </span><span> split = url.path.</span><span style="color:#bf616a;">split</span><span>(&quot;</span><span style="color:#a3be8c;">@</span><span>&quot;, </span><span style="color:#d08770;">1</span><span>)
576+ </span><span> </span><span style="color:#b48ead;">if </span><span style="color:#96b5b4;">len</span><span>(split) == </span><span style="color:#d08770;">2</span><span>:
577+ </span><span> </span><span style="color:#b48ead;">return </span><span>(split[</span><span style="color:#d08770;">0</span><span>], split[</span><span style="color:#d08770;">1</span><span>])
578+ </span><span> </span><span style="color:#b48ead;">return </span><span>(split[</span><span style="color:#d08770;">0</span><span>], </span><span style="color:#d08770;">None</span><span>)
579+ </span><span>
580+ </span><span style="color:#b48ead;">def </span><span style="color:#8fa1b3;">to_string</span><span>(</span><span style="color:#bf616a;">slug</span><span>, </span><span style="color:#bf616a;">domain</span><span>=</span><span style="color:#d08770;">None</span><span>):
581+ </span><span> </span><span style="color:#b48ead;">if </span><span>domain:
582+ </span><span> </span><span style="color:#b48ead;">return </span><span style="color:#bf616a;">quote_plus</span><span>(</span><span style="color:#b48ead;">f</span><span>&quot;</span><span style="color:#a3be8c;">project:</span><span>{slug}</span><span style="color:#a3be8c;">@</span><span>{domain}&quot;)
583+ </span><span> </span><span style="color:#b48ead;">else</span><span>:
584+ </span><span> </span><span style="color:#b48ead;">return </span><span style="color:#bf616a;">quote_plus</span><span>(</span><span style="color:#b48ead;">f</span><span>&quot;</span><span style="color:#a3be8c;">project:</span><span>{slug}&quot;)
585+ </span></code></pre>
586+ <h3 id="properties">Properties</h3>
587+ <h4 id="http-forge-feed-org-rel-repository">http://forge-feed.org/rel/repository</h4>
588+ <p>Reference to a VCS managed code repository.</p>
589+ <h4 id="http-feed-forge-org-ns-chatroom">http://feed-forge.org/ns/chatroom</h4>
590+ <p>Hint describing the backing type of chatroom. See <a href="https://www.iana.org/assignments/uri-schemes/uri-schemes.xhtml">uri-schemes</a>.</p>
591+ <pre style="background-color:#2b303b;color:#c0c5ce;"><code><span>matrix
592+ </span><span>irc
593+ </span><span>xmpp
594+ </span></code></pre>
595+ <h3 id="link-extension-types">Link Extension Types</h3>
596+ <h4 id="avatar">Avatar</h4>
597+ <p>Forges that allow users to configure a logo can expose this information as
598+ an avatar for use in other applications.</p>
599+ <pre data-lang="json" style="background-color:#2b303b;color:#c0c5ce;" class="language-json "><code class="language-json" data-lang="json"><span>{
600+ </span><span> &quot;</span><span style="color:#a3be8c;">rel</span><span>&quot;: &quot;</span><span style="color:#a3be8c;">http://webfinger.net/rel/avatar</span><span>&quot;,
601+ </span><span> &quot;</span><span style="color:#a3be8c;">href</span><span>&quot;: &quot;</span><span style="color:#a3be8c;">https://example.org/stylized-logo.png</span><span>&quot;
602+ </span><span>}
603+ </span></code></pre>
604+ <h4 id="homepage">Homepage</h4>
605+ <p>Link to an HTTP representation of the project homepage.</p>
606+ <pre data-lang="json" style="background-color:#2b303b;color:#c0c5ce;" class="language-json "><code class="language-json" data-lang="json"><span>{
607+ </span><span> &quot;</span><span style="color:#a3be8c;">rel</span><span>&quot;: &quot;</span><span style="color:#a3be8c;">http://feed-forge.org/rel/homepage</span><span>&quot;,
608+ </span><span> &quot;</span><span style="color:#a3be8c;">href</span><span>&quot;: &quot;</span><span style="color:#a3be8c;">https://example.org/example/spartacus</span><span>&quot;
609+ </span><span>}
610+ </span></code></pre>
611+ <h4 id="description">Description</h4>
612+ <p>A short text representation of the project.</p>
613+ <pre data-lang="json" style="background-color:#2b303b;color:#c0c5ce;" class="language-json "><code class="language-json" data-lang="json"><span>{
614+ </span><span> &quot;</span><span style="color:#a3be8c;">rel</span><span>&quot;: &quot;</span><span style="color:#a3be8c;">http://example.org/rel/description</span><span>&quot;,
615+ </span><span> &quot;</span><span style="color:#a3be8c;">titles</span><span>&quot;: {
616+ </span><span> &quot;</span><span style="color:#a3be8c;">en-us</span><span>&quot;: &quot;</span><span style="color:#a3be8c;">A Text Adventure Written in FORTRAN 77</span><span>&quot;,
617+ </span><span> &quot;</span><span style="color:#a3be8c;">es</span><span>&quot;: &quot;</span><span style="color:#a3be8c;">Una Aventura de Texto Escrita en FORTRAN 77</span><span>&quot;
618+ </span><span> }
619+ </span><span>}
620+ </span></code></pre>
621+ <h4 id="chat-links">Chat Links</h4>
622+ <p>Links to chatrooms: IRC, Matrix, XMPP, etc.</p>
623+ <pre data-lang="json" style="background-color:#2b303b;color:#c0c5ce;" class="language-json "><code class="language-json" data-lang="json"><span>{
624+ </span><span> &quot;</span><span style="color:#a3be8c;">rel</span><span>&quot;: &quot;</span><span style="color:#a3be8c;">http://feed-forge.org/rel/chatroom</span><span>&quot;,
625+ </span><span> &quot;</span><span style="color:#a3be8c;">href</span><span>&quot;: &quot;</span><span style="color:#a3be8c;">ircs://irc.libera.chat/#spartacus-game</span><span>&quot;,
626+ </span><span> &quot;</span><span style="color:#a3be8c;">properties</span><span>&quot;: {
627+ </span><span> &quot;</span><span style="color:#a3be8c;">http://feed-forge.org/ns/chatroom</span><span>&quot;: &quot;</span><span style="color:#a3be8c;">irc</span><span>&quot;
628+ </span><span> }
629+ </span><span>}
630+ </span></code></pre>
631+ <h4 id="mailing-lists">Mailing Lists</h4>
632+ <p>Links to associated mailing lists, forms, etc.</p>
633+ <pre data-lang="json" style="background-color:#2b303b;color:#c0c5ce;" class="language-json "><code class="language-json" data-lang="json"><span>{
634+ </span><span> &quot;</span><span style="color:#a3be8c;">rel</span><span>&quot;: &quot;</span><span style="color:#a3be8c;">http://feed-forge.org/rel/mailing-list</span><span>&quot;,
635+ </span><span> &quot;</span><span style="color:#a3be8c;">href</span><span>&quot;: &quot;</span><span style="color:#a3be8c;">mailto://list-name@mail.example.org</span><span>&quot;,
636+ </span><span> &quot;</span><span style="color:#a3be8c;">properties</span><span>&quot;: {
637+ </span><span> &quot;</span><span style="color:#a3be8c;">http://feed-forge.org/ns/mailing-list-subscribe</span><span>&quot;: &quot;</span><span style="color:#a3be8c;">mailto://subscribe+list-name@mail.example.org</span><span>&quot;,
638+ </span><span> &quot;</span><span style="color:#a3be8c;">http://feed-forge.org/ns/mailing-list-unsubscribe</span><span>&quot;: &quot;</span><span style="color:#a3be8c;">mailto://unsubscribe+list-name@mail.example.org</span><span>&quot;
639+ </span><span> }
640+ </span><span>}
641+ </span></code></pre>
642+ <h4 id="ticketing-systems">Ticketing Systems</h4>
643+ <p>Links to issue tracking systems.</p>
644+ <pre data-lang="json" style="background-color:#2b303b;color:#c0c5ce;" class="language-json "><code class="language-json" data-lang="json"><span>{
645+ </span><span> &quot;</span><span style="color:#a3be8c;">ref</span><span>&quot;: &quot;</span><span style="color:#a3be8c;">http://forge-feed.org/rel/ticketing-system</span><span>&quot;,
646+ </span><span> &quot;</span><span style="color:#a3be8c;">href</span><span>&quot;: &quot;</span><span style="color:#a3be8c;">https://example.org/bugs</span><span>&quot;,
647+ </span><span>}
648+ </span></code></pre>
649+ <h4 id="repository-links">Repository Links</h4>
650+ <p>Links of code repositories associated with this software project.</p>
651+ <pre data-lang="json" style="background-color:#2b303b;color:#c0c5ce;" class="language-json "><code class="language-json" data-lang="json"><span>{
652+ </span><span> &quot;</span><span style="color:#a3be8c;">rel</span><span>&quot;: &quot;</span><span style="color:#a3be8c;">http://example.org/rel/repository</span><span>&quot;,
653+ </span><span> &quot;</span><span style="color:#a3be8c;">href</span><span>&quot;: &quot;</span><span style="color:#a3be8c;">https://example.org/example/spartacus</span><span>&quot;,
654+ </span><span> &quot;</span><span style="color:#a3be8c;">properties</span><span>&quot;: {
655+ </span><span> &quot;</span><span style="color:#a3be8c;">http://forge-feed.org/rel/repository</span><span>&quot;: &quot;</span><span style="color:#a3be8c;">repository:example/spartacus</span><span>&quot;
656+ </span><span> }
657+ </span><span>}
658+ </span></code></pre>
659+ <h2 id="example-multi-repository-query">Example Multi-Repository Query</h2>
660+ <p>A <a href="https://webfinger.net/spec/">WebFinger</a> query may be used to identify
661+ detailed information about a public repository at a particular forge. Here is
662+ an example response about a fictitious project which has two code repositories
663+ associated with it as well as chat links, and a bug tracking system.</p>
664+ <p><code>GET https://example.org/.well-known/webfinger?resource=project:spartacus</code></p>
665+ <pre data-lang="json" style="background-color:#2b303b;color:#c0c5ce;" class="language-json "><code class="language-json" data-lang="json"><span>{
666+ </span><span> &quot;</span><span style="color:#a3be8c;">subject</span><span>&quot;: &quot;</span><span style="color:#a3be8c;">project:spartacus</span><span>&quot;,
667+ </span><span> &quot;</span><span style="color:#a3be8c;">aliases</span><span>&quot;: [
668+ </span><span> &quot;</span><span style="color:#a3be8c;">https://example.org</span><span>&quot;
669+ </span><span> ],
670+ </span><span> &quot;</span><span style="color:#a3be8c;">links</span><span>&quot;: [
671+ </span><span> {
672+ </span><span> &quot;</span><span style="color:#a3be8c;">rel</span><span>&quot;: &quot;</span><span style="color:#a3be8c;">http://webfinger.net/rel/avatar</span><span>&quot;,
673+ </span><span> &quot;</span><span style="color:#a3be8c;">href</span><span>&quot;: &quot;</span><span style="color:#a3be8c;">https://example.org/stylized-logo.png</span><span>&quot;
674+ </span><span> },
675+ </span><span> {
676+ </span><span> &quot;</span><span style="color:#a3be8c;">rel</span><span>&quot;: &quot;</span><span style="color:#a3be8c;">http://feed-forge.org/rel/homepage</span><span>&quot;,
677+ </span><span> &quot;</span><span style="color:#a3be8c;">href</span><span>&quot;: &quot;</span><span style="color:#a3be8c;">https://code.example.org/spartacus</span><span>&quot;
678+ </span><span> },
679+ </span><span> {
680+ </span><span> &quot;</span><span style="color:#a3be8c;">rel</span><span>&quot;: &quot;</span><span style="color:#a3be8c;">http://forge-feed.org/rel/description</span><span>&quot;,
681+ </span><span> &quot;</span><span style="color:#a3be8c;">titles</span><span>&quot;: {
682+ </span><span> &quot;</span><span style="color:#a3be8c;">en-us</span><span>&quot;: &quot;</span><span style="color:#a3be8c;">A Text Adventure Written in FORTRAN 77</span><span>&quot;,
683+ </span><span> &quot;</span><span style="color:#a3be8c;">es</span><span>&quot;: &quot;</span><span style="color:#a3be8c;">Una Aventura de Texto Escrita en FORTRAN 77</span><span>&quot;
684+ </span><span> }
685+ </span><span> },
686+ </span><span> {
687+ </span><span> &quot;</span><span style="color:#a3be8c;">rel</span><span>&quot;: &quot;</span><span style="color:#a3be8c;">http://forge-feed.org/rel/chatroom</span><span>&quot;,
688+ </span><span> &quot;</span><span style="color:#a3be8c;">href</span><span>&quot;: &quot;</span><span style="color:#a3be8c;">ircs://irc.libera.chat/#spartacus-game</span><span>&quot;,
689+ </span><span> &quot;</span><span style="color:#a3be8c;">properties</span><span>&quot;: {
690+ </span><span> &quot;</span><span style="color:#a3be8c;">http://feed-forge.org/ns/chatroom</span><span>&quot;: &quot;</span><span style="color:#a3be8c;">irc</span><span>&quot;
691+ </span><span> }
692+ </span><span> },
693+ </span><span> {
694+ </span><span> &quot;</span><span style="color:#a3be8c;">rel</span><span>&quot;: &quot;</span><span style="color:#a3be8c;">http://forge-feed.org/rel/ticketing-system</span><span>&quot;,
695+ </span><span> &quot;</span><span style="color:#a3be8c;">href</span><span>&quot;: &quot;</span><span style="color:#a3be8c;">https://example.org/bugs</span><span>&quot;
696+ </span><span> },
697+ </span><span> {
698+ </span><span> &quot;</span><span style="color:#a3be8c;">rel</span><span>&quot;: &quot;</span><span style="color:#a3be8c;">http://forge-feed.org/rel/label</span><span>&quot;,
699+ </span><span> &quot;</span><span style="color:#a3be8c;">properties</span><span>&quot;: {
700+ </span><span> &quot;</span><span style="color:#a3be8c;">http://feed-forge.org/ns/label</span><span>&quot;: &quot;</span><span style="color:#a3be8c;">fortran</span><span>&quot;
701+ </span><span> }
702+ </span><span> },
703+ </span><span> {
704+ </span><span> &quot;</span><span style="color:#a3be8c;">rel</span><span>&quot;: &quot;</span><span style="color:#a3be8c;">http://forge-feed.org/rel/label</span><span>&quot;,
705+ </span><span> &quot;</span><span style="color:#a3be8c;">properties</span><span>&quot;: {
706+ </span><span> &quot;</span><span style="color:#a3be8c;">http://feed-forge.org/ns/label</span><span>&quot;: &quot;</span><span style="color:#a3be8c;">text-adventure</span><span>&quot;
707+ </span><span> }
708+ </span><span> },
709+ </span><span> {
710+ </span><span> &quot;</span><span style="color:#a3be8c;">rel</span><span>&quot;: &quot;</span><span style="color:#a3be8c;">http://forge-feed.org/rel/repository</span><span>&quot;,
711+ </span><span> &quot;</span><span style="color:#a3be8c;">href</span><span>&quot;: &quot;</span><span style="color:#a3be8c;">https://code.example.org/spartacus/spartan-engine</span><span>&quot;,
712+ </span><span> &quot;</span><span style="color:#a3be8c;">titles</span><span>&quot;: {
713+ </span><span> &quot;</span><span style="color:#a3be8c;">en-us</span><span>&quot;: &quot;</span><span style="color:#a3be8c;">The Spartan Game Engine</span><span>&quot;
714+ </span><span> },
715+ </span><span> &quot;</span><span style="color:#a3be8c;">properties</span><span>&quot;: {
716+ </span><span> &quot;</span><span style="color:#a3be8c;">http://forge-feed.org/rel/repository-uri</span><span>&quot;: &quot;</span><span style="color:#a3be8c;">repository:spartacus/game-engine</span><span>&quot;
717+ </span><span> }
718+ </span><span> },
719+ </span><span> {
720+ </span><span> &quot;</span><span style="color:#a3be8c;">rel</span><span>&quot;: &quot;</span><span style="color:#a3be8c;">http://forge-feed.org/rel/repository</span><span>&quot;,
721+ </span><span> &quot;</span><span style="color:#a3be8c;">href</span><span>&quot;: &quot;</span><span style="color:#a3be8c;">https://code.example.org/spartacus/game</span><span>&quot;,
722+ </span><span> &quot;</span><span style="color:#a3be8c;">titles</span><span>&quot;: {
723+ </span><span> &quot;</span><span style="color:#a3be8c;">en-us</span><span>&quot;: &quot;</span><span style="color:#a3be8c;">Implementation of the Spartacus Text Adventure game</span><span>&quot;
724+ </span><span> },
725+ </span><span> &quot;</span><span style="color:#a3be8c;">properties</span><span>&quot;: {
726+ </span><span> &quot;</span><span style="color:#a3be8c;">http://forge-feed.org/rel/repository-uri</span><span>&quot;: &quot;</span><span style="color:#a3be8c;">repository:spartacus/game</span><span>&quot;
727+ </span><span> }
728+ </span><span> },
729+ </span><span> {
730+ </span><span> &quot;</span><span style="color:#a3be8c;">rel</span><span>&quot;: &quot;</span><span style="color:#a3be8c;">http://forge-feed.org/rel/repository</span><span>&quot;,
731+ </span><span> &quot;</span><span style="color:#a3be8c;">href</span><span>&quot;: &quot;</span><span style="color:#a3be8c;">https://code.example.org/spartacus/game</span><span>&quot;,
732+ </span><span> &quot;</span><span style="color:#a3be8c;">titles</span><span>&quot;: {
733+ </span><span> &quot;</span><span style="color:#a3be8c;">en-us</span><span>&quot;: &quot;</span><span style="color:#a3be8c;">Promotional Website for the Spartacus Game</span><span>&quot;
734+ </span><span> },
735+ </span><span> &quot;</span><span style="color:#a3be8c;">properties</span><span>&quot;: {
736+ </span><span> &quot;</span><span style="color:#a3be8c;">http://forge-feed.org/rel/repository-uri</span><span>&quot;: &quot;</span><span style="color:#a3be8c;">repository:spartacus/www</span><span>&quot;
737+ </span><span> }
738+ </span><span> }
739+ </span><span> ]
740+ </span><span>}
741+ </span></code></pre>
742+ <h2 id="example-single-repository-query">Example Single Repository Query</h2>
743+ <p>Here is an example of a project with only a single repository associated with it.</p>
744+ <pre data-lang="json" style="background-color:#2b303b;color:#c0c5ce;" class="language-json "><code class="language-json" data-lang="json"><span>{
745+ </span><span> &quot;</span><span style="color:#a3be8c;">subject</span><span>&quot;: &quot;</span><span style="color:#a3be8c;">project:fuu/bar</span><span>&quot;,
746+ </span><span> &quot;</span><span style="color:#a3be8c;">links</span><span>&quot;: [
747+ </span><span> {
748+ </span><span> &quot;</span><span style="color:#a3be8c;">rel</span><span>&quot;: &quot;</span><span style="color:#a3be8c;">http://forge-feed.org/rel/repository</span><span>&quot;,
749+ </span><span> &quot;</span><span style="color:#a3be8c;">href</span><span>&quot;: &quot;</span><span style="color:#a3be8c;">https://code.example.org/fuu/bar</span><span>&quot;,
750+ </span><span> &quot;</span><span style="color:#a3be8c;">titles</span><span>&quot;: {
751+ </span><span> &quot;</span><span style="color:#a3be8c;">en-us</span><span>&quot;: &quot;</span><span style="color:#a3be8c;">Baz Qux</span><span>&quot;
752+ </span><span> },
753+ </span><span> &quot;</span><span style="color:#a3be8c;">properties</span><span>&quot;: {
754+ </span><span> &quot;</span><span style="color:#a3be8c;">http://forge-feed.org/rel/repository-uri</span><span>&quot;: &quot;</span><span style="color:#a3be8c;">repository:fuu/bar</span><span>&quot;
755+ </span><span> }
756+ </span><span> }
757+ </span><span> ]
758+ </span><span>}
759+ </span></code></pre>
760+ <h3 id="security">Security</h3>
761+ <p>Projects which are not publicly available should not be identifiable by
762+ making webfinger queries at all. A project which is private MUST return
763+ the same response as a repository which does not exist when making a webfinger
764+ request.</p>
765+ <pre style="background-color:#2b303b;color:#c0c5ce;"><code><span>GET https://example.org/.well-known/webfinger?resource=project:example/spartacus
766+ </span><span>200
767+ </span><span>GET https://example.org/.well-known/webfinger?resource=project:example/private-project
768+ </span><span>404
769+ </span><span>GET https://example.org/.well-known/webfinger?resource=project:example/non-existent-project
770+ </span><span>404
771+ </span></code></pre>
772+
773+ </section>
774+
775+ <footer>
776+ <p><small>.</small></p>
777+ </footer>
778+ </div>
779+ </body>
780+ </html>
781 diff --git a/public/webfinger-repository/index.html b/public/webfinger-repository/index.html
782new file mode 100644
783index 0000000..d0f08a9
784--- /dev/null
785+++ b/public/webfinger-repository/index.html
786 @@ -0,0 +1,225 @@
787+ <!DOCTYPE html>
788+ <html lang="en-US">
789+ <head>
790+ <meta charset="UTF-8" />
791+ <meta http-equiv="X-UA-Compatible" content="IE=edge" />
792+ <meta name="viewport" content="width=device-width, initial-scale=1" />
793+ <title></title>
794+ <meta
795+ name="description"
796+ itemprop="about"
797+ content="ForgeFeed Specifications"
798+ />
799+ <link rel="stylesheet" href="https://forge-feed.org/styles.css" />
800+ </head>
801+
802+ <body>
803+ <div class="wrapper">
804+ <header>
805+ <a href="https://forge-feed.org">
806+ <img
807+ src="https://forge-feed.org/img/logo.svg"
808+ class="site-logo"
809+ alt="Logo"
810+ width="275px"
811+ height="auto"
812+ /></a>
813+
814+ <p>ForgeFeed Specifications</p>
815+
816+
817+ <a href="https://codeberg.org/ayllu/forge-feed">
818+ <img
819+ src="https://forge-feed.org/img/codeberg.svg"
820+ class="site-logo"
821+ alt="Logo"
822+ />
823+ </a>
824+
825+ <a href="https://git.sr.ht/~kevinschoon/forge-feed">
826+ <img
827+ src="https://forge-feed.org/img/sourcehut.svg"
828+ class="site-logo sourcehut"
829+ alt="Logo"
830+ />
831+ </a>
832+ </header>
833+
834+ <section>
835+ <h1>Repository Discovery via WebFinger</h1>
836+ <p>A repository refers to a version control managed source code which may be
837+ browsed over HTTP or downloaded with specific tooling.</p>
838+ <h2 id="repository-uri">Repository URI</h2>
839+ <p>A repository URI identifies a code repository and optionally the host that is
840+ resides on. This value is similar to
841+ <a href="https://datatracker.ietf.org/doc/html/rfc7565">RFC7565</a>. The slug and hostname
842+ part MUST match the URI path specification as defined in
843+ <a href="https://www.rfc-editor.org/rfc/rfc3986#section-3.3">RFC3986-3.3</a> while the
844+ hostname, if specified, must match
845+ <a href="https://www.rfc-editor.org/rfc/rfc3986#section-3.2.2">RFC3986-3.2.2</a></p>
846+ <pre style="background-color:#2b303b;color:#c0c5ce;"><code><span>repository-uri = prefix slug hostname
847+ </span><span>
848+ </span><span>prefix = &quot;repository:&quot;
849+ </span><span>slug = rfc3986-path
850+ </span><span>hostname = [@ rfc3986-hostname]
851+ </span></code></pre>
852+ <h3 id="slug">Slug</h3>
853+ <p>The Slug represents a unique string that identifies a repository at a
854+ particular code forge. Repository refers to a VCS managed codebase of some
855+ kind, e.g. a Git repository.</p>
856+ <h3 id="hostname">Hostname</h3>
857+ <p>If the hostname part is missing then the address of the server receiving the
858+ query is assumed. For example the following two queries are equivalent:</p>
859+ <pre data-lang="text" style="background-color:#2b303b;color:#c0c5ce;" class="language-text "><code class="language-text" data-lang="text"><span>https://example.org/.well-known/webfinger?resource=repository:spartacus/game
860+ </span><span>https://example.org/.well-known/webfinger?resource=repository:spartacus/game@example.org
861+ </span></code></pre>
862+ <p>TODO: Make this an actual spec, for now, some Python:</p>
863+ <pre data-lang="python" style="background-color:#2b303b;color:#c0c5ce;" class="language-python "><code class="language-python" data-lang="python"><span style="color:#b48ead;">from </span><span>urllib.parse </span><span style="color:#b48ead;">import </span><span>urlparse, quote_plus
864+ </span><span>
865+ </span><span style="color:#b48ead;">def </span><span style="color:#8fa1b3;">from_string</span><span>(</span><span style="color:#bf616a;">text</span><span>):
866+ </span><span> url = </span><span style="color:#bf616a;">urlparse</span><span>(text)
867+ </span><span> </span><span style="color:#b48ead;">if </span><span>not url.path:
868+ </span><span> </span><span style="color:#b48ead;">return </span><span>(</span><span style="color:#d08770;">None</span><span>, </span><span style="color:#d08770;">None</span><span>)
869+ </span><span> split = url.path.</span><span style="color:#bf616a;">split</span><span>(&quot;</span><span style="color:#a3be8c;">@</span><span>&quot;, </span><span style="color:#d08770;">1</span><span>)
870+ </span><span> </span><span style="color:#b48ead;">if </span><span style="color:#96b5b4;">len</span><span>(split) == </span><span style="color:#d08770;">2</span><span>:
871+ </span><span> </span><span style="color:#b48ead;">return </span><span>(split[</span><span style="color:#d08770;">0</span><span>], split[</span><span style="color:#d08770;">1</span><span>])
872+ </span><span> </span><span style="color:#b48ead;">return </span><span>(split[</span><span style="color:#d08770;">0</span><span>], </span><span style="color:#d08770;">None</span><span>)
873+ </span><span>
874+ </span><span style="color:#b48ead;">def </span><span style="color:#8fa1b3;">to_string</span><span>(</span><span style="color:#bf616a;">slug</span><span>, </span><span style="color:#bf616a;">domain</span><span>=</span><span style="color:#d08770;">None</span><span>):
875+ </span><span> </span><span style="color:#b48ead;">if </span><span>domain:
876+ </span><span> </span><span style="color:#b48ead;">return </span><span style="color:#bf616a;">quote_plus</span><span>(</span><span style="color:#b48ead;">f</span><span>&quot;</span><span style="color:#a3be8c;">repository:</span><span>{slug}</span><span style="color:#a3be8c;">@</span><span>{domain}&quot;)
877+ </span><span> </span><span style="color:#b48ead;">else</span><span>:
878+ </span><span> </span><span style="color:#b48ead;">return </span><span style="color:#bf616a;">quote_plus</span><span>(</span><span style="color:#b48ead;">f</span><span>&quot;</span><span style="color:#a3be8c;">repository:</span><span>{slug}&quot;)
879+ </span></code></pre>
880+ <h3 id="properties">Properties</h3>
881+ <h4 id="http-feed-forge-org-ns-vcs-type">http://feed-forge.org/ns/vcs-type</h4>
882+ <p>Identifies VCS types, valid strings are:</p>
883+ <pre style="background-color:#2b303b;color:#c0c5ce;"><code><span>bzr (GNU Bazaar) bazaar.canonical.com
884+ </span><span>darcs (Darcs) darcs.net
885+ </span><span>fossil (Fossil) fossil-scm.org
886+ </span><span>git (Git) git-scm.com
887+ </span><span>hg (Mercurial) mercurial-scm.org
888+ </span><span>pijul (Pijul) pijul.org
889+ </span><span>svn (Apache Subversion) subversion.apache.org
890+ </span></code></pre>
891+ <h4 id="http-feed-forge-org-ns-spdx-identifier">http://feed-forge.org/ns/spdx-identifier</h4>
892+ <p>Refers to a valid SPDX identifier, see <a href="https://spdx.org/licenses/">license-list</a></p>
893+ <h3 id="link-extension-types">Link Extension Types</h3>
894+ <h4 id="avatar">Avatar</h4>
895+ <p>Forges that allow users to configure a logo can expose this information as
896+ an avatar for use in other applications.</p>
897+ <pre data-lang="json" style="background-color:#2b303b;color:#c0c5ce;" class="language-json "><code class="language-json" data-lang="json"><span>{
898+ </span><span> &quot;</span><span style="color:#a3be8c;">rel</span><span>&quot;: &quot;</span><span style="color:#a3be8c;">http://webfinger.net/rel/avatar</span><span>&quot;,
899+ </span><span> &quot;</span><span style="color:#a3be8c;">href</span><span>&quot;: &quot;</span><span style="color:#a3be8c;">https://example.org/stylized-logo.png</span><span>&quot;
900+ </span><span>}
901+ </span></code></pre>
902+ <h4 id="homepage">Homepage</h4>
903+ <p>Link to an HTTP representation of the repository.</p>
904+ <pre data-lang="json" style="background-color:#2b303b;color:#c0c5ce;" class="language-json "><code class="language-json" data-lang="json"><span>{
905+ </span><span> &quot;</span><span style="color:#a3be8c;">rel</span><span>&quot;: &quot;</span><span style="color:#a3be8c;">http://feed-forge.org/rel/homepage</span><span>&quot;,
906+ </span><span> &quot;</span><span style="color:#a3be8c;">href</span><span>&quot;: &quot;</span><span style="color:#a3be8c;">https://example.org/spartacus/game</span><span>&quot;
907+ </span><span>}
908+ </span></code></pre>
909+ <h4 id="description">Description</h4>
910+ <p>A short text representation of the repository.</p>
911+ <pre data-lang="json" style="background-color:#2b303b;color:#c0c5ce;" class="language-json "><code class="language-json" data-lang="json"><span>{
912+ </span><span> &quot;</span><span style="color:#a3be8c;">rel</span><span>&quot;: &quot;</span><span style="color:#a3be8c;">http://example.org/rel/description</span><span>&quot;,
913+ </span><span> &quot;</span><span style="color:#a3be8c;">titles</span><span>&quot;: {
914+ </span><span> &quot;</span><span style="color:#a3be8c;">en-us</span><span>&quot;: &quot;</span><span style="color:#a3be8c;">A Text Adventure Written in FORTRAN 77</span><span>&quot;,
915+ </span><span> &quot;</span><span style="color:#a3be8c;">es</span><span>&quot;: &quot;</span><span style="color:#a3be8c;">Una Aventura de Texto Escrita en FORTRAN 77</span><span>&quot;
916+ </span><span> }
917+ </span><span>}
918+ </span></code></pre>
919+ <h4 id="license">License</h4>
920+ <p>A license SPDX identifier and link to the license's full text.</p>
921+ <pre data-lang="json" style="background-color:#2b303b;color:#c0c5ce;" class="language-json "><code class="language-json" data-lang="json"><span>{
922+ </span><span> &quot;</span><span style="color:#a3be8c;">rel</span><span>&quot;: &quot;</span><span style="color:#a3be8c;">http://feed-forge.org/rel/license</span><span>&quot;,
923+ </span><span> &quot;</span><span style="color:#a3be8c;">href</span><span>&quot;: &quot;</span><span style="color:#a3be8c;">https://example.com/example/spartacus/tree/LICENSE</span><span>&quot;,
924+ </span><span> &quot;</span><span style="color:#a3be8c;">properties</span><span>&quot;: {
925+ </span><span> &quot;</span><span style="color:#a3be8c;">http://feed-forge.org/ns/spdx-identifier</span><span>&quot;: &quot;</span><span style="color:#a3be8c;">GPL-2.0-or-later</span><span>&quot;
926+ </span><span> }
927+ </span><span>}
928+ </span></code></pre>
929+ <h4 id="clone-links">Clone Links</h4>
930+ <p>Clone links define how one can download a copy of the remote
931+ software onto their own server.</p>
932+ <pre data-lang="json" style="background-color:#2b303b;color:#c0c5ce;" class="language-json "><code class="language-json" data-lang="json"><span>{
933+ </span><span> &quot;</span><span style="color:#a3be8c;">rel</span><span>&quot;: &quot;</span><span style="color:#a3be8c;">http://feed-forge.org/rel/clone</span><span>&quot;,
934+ </span><span> &quot;</span><span style="color:#a3be8c;">href</span><span>&quot;: &quot;</span><span style="color:#a3be8c;">https://example.org/example/spartacus</span><span>&quot;,
935+ </span><span> &quot;</span><span style="color:#a3be8c;">properties</span><span>&quot;: {
936+ </span><span> &quot;</span><span style="color:#a3be8c;">http://feed-forge.org/ns/vcs-type</span><span>&quot;: &quot;</span><span style="color:#a3be8c;">git</span><span>&quot;
937+ </span><span> }
938+ </span><span>}
939+ </span></code></pre>
940+ <h2 id="webfinger-query">WebFinger Query</h2>
941+ <p>A <a href="https://webfinger.net/spec/">WebFinger</a> query may be used to identify
942+ detailed information about a public repository at a particular forge. Here is
943+ an example response about a fictitious repository:</p>
944+ <p><code>GET https://example.org/.well-known/webfinger?resource=repository:spartacus/game</code></p>
945+ <pre data-lang="json" style="background-color:#2b303b;color:#c0c5ce;" class="language-json "><code class="language-json" data-lang="json"><span>{
946+ </span><span> &quot;</span><span style="color:#a3be8c;">subject</span><span>&quot;: &quot;</span><span style="color:#a3be8c;">repository:spartacus/game</span><span>&quot;,
947+ </span><span> &quot;</span><span style="color:#a3be8c;">aliases</span><span>&quot;: [
948+ </span><span> &quot;</span><span style="color:#a3be8c;">https://example.org/spartacus/game</span><span>&quot;
949+ </span><span> ],
950+ </span><span> &quot;</span><span style="color:#a3be8c;">links</span><span>&quot;: [
951+ </span><span> {
952+ </span><span> &quot;</span><span style="color:#a3be8c;">rel</span><span>&quot;: &quot;</span><span style="color:#a3be8c;">http://webfinger.net/rel/avatar</span><span>&quot;,
953+ </span><span> &quot;</span><span style="color:#a3be8c;">href</span><span>&quot;: &quot;</span><span style="color:#a3be8c;">https://example.org/stylized-logo.png</span><span>&quot;
954+ </span><span> },
955+ </span><span> {
956+ </span><span> &quot;</span><span style="color:#a3be8c;">rel</span><span>&quot;: &quot;</span><span style="color:#a3be8c;">http://forge-feed.org/rel/description</span><span>&quot;,
957+ </span><span> &quot;</span><span style="color:#a3be8c;">titles</span><span>&quot;: {
958+ </span><span> &quot;</span><span style="color:#a3be8c;">en-us</span><span>&quot;: &quot;</span><span style="color:#a3be8c;">A Text Adventure Written in FORTRAN 77</span><span>&quot;,
959+ </span><span> &quot;</span><span style="color:#a3be8c;">es</span><span>&quot;: &quot;</span><span style="color:#a3be8c;">Una Aventura de Texto Escrita en FORTRAN 77</span><span>&quot;
960+ </span><span> }
961+ </span><span> },
962+ </span><span> {
963+ </span><span> &quot;</span><span style="color:#a3be8c;">rel</span><span>&quot;: &quot;</span><span style="color:#a3be8c;">http://feed-forge.org/rel/clone</span><span>&quot;,
964+ </span><span> &quot;</span><span style="color:#a3be8c;">href</span><span>&quot;: &quot;</span><span style="color:#a3be8c;">https://example.org/spartacus/game</span><span>&quot;,
965+ </span><span> &quot;</span><span style="color:#a3be8c;">properties</span><span>&quot;: {
966+ </span><span> &quot;</span><span style="color:#a3be8c;">http://feed-forge.org/ns/vcs-type</span><span>&quot;: &quot;</span><span style="color:#a3be8c;">git</span><span>&quot;
967+ </span><span> }
968+ </span><span> },
969+ </span><span> {
970+ </span><span> &quot;</span><span style="color:#a3be8c;">rel</span><span>&quot;: &quot;</span><span style="color:#a3be8c;">http://forge-feed.org/rel/license</span><span>&quot;,
971+ </span><span> &quot;</span><span style="color:#a3be8c;">href</span><span>&quot;: &quot;</span><span style="color:#a3be8c;">https://example.com/spartacus/game/tree/LICENSE</span><span>&quot;,
972+ </span><span> &quot;</span><span style="color:#a3be8c;">properties</span><span>&quot;: {
973+ </span><span> &quot;</span><span style="color:#a3be8c;">spdx-identifier</span><span>&quot;: &quot;</span><span style="color:#a3be8c;">GPL-2.0-or-later</span><span>&quot;
974+ </span><span> }
975+ </span><span> },
976+ </span><span> {
977+ </span><span> &quot;</span><span style="color:#a3be8c;">rel</span><span>&quot;: &quot;</span><span style="color:#a3be8c;">http://forge-feed.org/rel/label</span><span>&quot;,
978+ </span><span> &quot;</span><span style="color:#a3be8c;">properties</span><span>&quot;: {
979+ </span><span> &quot;</span><span style="color:#a3be8c;">http://feed-forge.org/ns/label</span><span>&quot;: &quot;</span><span style="color:#a3be8c;">fortran</span><span>&quot;
980+ </span><span> }
981+ </span><span> },
982+ </span><span> {
983+ </span><span> &quot;</span><span style="color:#a3be8c;">rel</span><span>&quot;: &quot;</span><span style="color:#a3be8c;">http://forge-feed.org/rel/label</span><span>&quot;,
984+ </span><span> &quot;</span><span style="color:#a3be8c;">properties</span><span>&quot;: {
985+ </span><span> &quot;</span><span style="color:#a3be8c;">http://feed-forge.org/ns/label</span><span>&quot;: &quot;</span><span style="color:#a3be8c;">text-adventure</span><span>&quot;
986+ </span><span> }
987+ </span><span> }
988+ </span><span> ]
989+ </span><span>}
990+ </span></code></pre>
991+ <h3 id="security">Security</h3>
992+ <p>Repositories which are not publicly available should not be identifiable by
993+ making webfinger queries at all. A repository which is private MUST return
994+ the same response as a repository which does not exist when making a webfinger
995+ request.</p>
996+ <pre style="background-color:#2b303b;color:#c0c5ce;"><code><span>GET https://example.org/.well-known/webfinger?resource=repository:spartacus/game
997+ </span><span>200
998+ </span><span>GET https://example.org/.well-known/webfinger?resource=repository:example/private-repository
999+ </span><span>404
1000+ </span><span>GET https://example.org/.well-known/webfinger?resource=repository:example/non-existent-repository
1001+ </span><span>404
1002+ </span></code></pre>
1003+
1004+ </section>
1005+
1006+ <footer>
1007+ <p><small>.</small></p>
1008+ </footer>
1009+ </div>
1010+ </body>
1011+ </html>