ForgeFeed Specifications
Your forge should expose an Atom feed in order for other peers to subscribe to interesting code projects that are developed on your forge. The server should expose projects ordered by those which have been recently updated. THe heuristic you use to determine what has been updated depends on your forge. A common way to do this may be to simply look at your VCS's concept of a commit and order updates with that.
In order to participate in ForgeFeed your forge MUST present an HTML link
element such as below at the root domain of your forge. For example,
code.example.org
MUST have a link element present in it's html header:
<html>
<head>
<title>My Forge</title>
<link
rel="alternate"
type="application/atom+xml"
title="Recent Forge Activity"
href="https://code.example.org/firehose.xml" />
<!-- index-url refers to the RSS link on the current webpage which contains forge updates -->
<meta name="forge-feed:index-url" content="https://code.example.org/firehose.xml"/>
</head>
<body>
...
</body>
</html>
The link MAY have a title of "Recent Forge Activity" such that it uniquely identifies this feed as being related to forge updates. A server MUST provide a meta tag with the name forge-feed:index where the content of the tag matches the href of an Atom link listed on this page which should be used for indexing by external crawlers. Applications which rely on the forge-feed:index meta tag MUST stop crawling the serving website if this tag is no longer present in the pages HTML.
Below is an example Atom feed with an optional repository section (described below).
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom"
xmlns:forge-feed="http://forge-feed.org/project-atom-feed">
<title>Acme Forge Firehose</title>
<subtitle>Recent Project Updates @ Acme Forge</subtitle>
<link href="https://code.example.org/firehose.xml" rel="self" />
<link href="https://code.example.org/" />
<id>urn:uuid:44decbfc-ec17-42fa-994e-67dc13029072</id>
<updated>2025-06-18T11:23:02Z</updated>
<entry>
<title>Spartacus Game</title>
<link href="https://code.example.org/spartacus" />
<id>urn:uuid:51b2ad2b-34ff-4a69-9f45-a300bf296d05</id>
<published>2025-06-18T11:23:02Z</published>
<updated>2025-06-18T11:23:02Z</updated>
<summary>A Game Engine & Text Adventure Written in FORTRAN 77</summary>
<forge-feed:project>project:spartacus</forge-feed:project>
</entry>
</feed>
In order to facilitate discovery by external indexes it is highly recommended that your server implement the webfinger project specification so that repository indexes may populate their state with rich information about code repositories hosted on your server.
The extension currently supports only a single field called project
.
<forge-feed:project>project:spartacus</forge-feed:project>
If the host section of the URI is included that is MUST match domain name of the server which is providing the feed.
Forge-feed enabled Atom feeds have no support for sharing private projects and any project that is not shared publicly on the internet must be hidden from the Atom activity feed stream. If your forge provides the ability to change a project from public to private it must be understood that clients may already have cached versions of your project data.
Your activity feed should not include project events that are older than 1 week.
Although it is permitted to return duplicate projects the feed SHOULD only return unique projects in a given window.
It may be undesirable to enumerate project events items with the simple heuristic of
end = time.now()
start = end - 6h
events = project_events_between(start, end)
Because the oldest project events will fall out of the time window on subsequent queries by feed readers. This can cause some feed readers to frequently request new content from your server. Instead events can be "clamped" within a certain time period. For example you may choose to publish four buckets of updates per day:
00:00:00 06:00:00
06:00:00 12:00:00
12:00:00 18:00:00
18:00:00 00:00:00
For example if the current time is 2021-03-05 13:00:55 UTC you could use
the following example to return a summary of project events from the
previous time bucket.
now = time.now()
start = now.set_time("06:00:00")
end = now.set_time("12:00:00")
events = project_events_between(start, end)
This approach with a TTL value of 60 (minutes) will reduce excess requests from some readers but allow all clients to receive timely updates.