RSS & Atom Feeds — powering real-time portfolios and integrations
Keeping your portfolio, website, or internal tools in sync with your latest photography should be simple. For that reason, Exposera provides RSS and Atom feeds for every user and album. These feeds offer an open, predictable way to consume photo metadata and media links for public content (no API keys required). Note: private or restricted items are not exposed in public feeds, and media may be served via a proxy or short-lived signed URLs depending on visibility and access controls. Feeds can be used by reader apps, static site generators, serverless automation, or custom integrations — any environment that understands XML and HTTP.
This post explains how these feeds work, what data they expose, and how to build real-time or build-time integrations that make your Exposera uploads visible everywhere else you publish.
Understanding the Feed Model
RSS (Really Simple Syndication) and Atom are mature web standards that predate the social media era but remain unmatched in their simplicity and resilience. Each feed is an XML document describing a list of recent items — in this case, your photographs or posts. The format includes both human-readable content and structured metadata that software can easily parse.
By exposing feeds for both users and albums, Exposera provides two complementary entry points:
-
User Feed —
https://exposera.com/u/:username/feed.xmlContains all recent uploads and posts from the specified user. -
Album Feed —
https://exposera.com/u/:username/albums/:slug/feed.xmlContains only the photos within a specific album.
Each item in these feeds includes standard fields (title, link, guid/id, pubDate/updated) along with additional structured information useful for automated processing:
- Canonical URLs to both the public photo page and a transformed-media link (served via our media proxy).
- Descriptive metadata including title, caption, publication date, and tags.
Images are supplied in the feed via the RSS <enclosure url="..." type="..." /> inside each <item>. Photo items include this field (post items do not). The enclosure URL points to our media proxy (/api/media/photos/...).
Feeds are delivered with cache-friendly headers. Currently responses include a Cache-Control policy of public, max-age=1800, s-maxage=3600 (30 minute browser cache, 1 hour CDN cache). We don’t set ETag/Last-Modified in the current implementation, though the feed generator does expose the newest item timestamp for use as a last-build date. The structure adheres to RSS 2.0 and is broadly Atom-compatible, allowing compatibility with existing libraries and infrastructure.
Why Feeds Still Matter
While APIs dominate modern integration design, RSS and Atom remain the most universally supported formats for synchronizing content. They require no API keys, have minimal failure modes, and work equally well for small hobbyist websites and complex automation pipelines.
For photographers, this means a single, stable URL can act as the bridge between Exposera and everything else: a portfolio generator, an archive job, or even a publishing bot.
Common Integration Patterns
1. Reader Applications
Any RSS or Atom reader can subscribe to your user feed and display your latest uploads just like a news feed. Each new photograph appears with its title and caption, linking back to its page on Exposera.
This is useful for peers, clients, or followers who prefer to track updates through their feed readers rather than social platforms.
2. Static Site Generators (SSG)
For users who host their own websites, feeds serve as an ideal bridge into build-time data pipelines. Whether you use Eleventy, Hugo, or Next.js, you can fetch your Exposera feed during the build and generate pages for your latest photographs automatically.
Because the feed is compact and cacheable, it can be fetched quickly at each build without heavy API integration or authentication logic.
3. Server-Side Synchronization
For more advanced workflows, you can deploy a small process or serverless function that polls your feed on a schedule and mirrors new items into your CMS or asset store. Each item’s guid provides a stable identifier, so you can easily detect new or updated entries.
This approach lets you maintain a synchronized copy of your Exposera content across systems — for example, replicating images into an internal DAM, or updating an artist’s portfolio hosted elsewhere.
4. Automation and Webhooks
Because feeds are regular HTTP resources, they can be watched by webhook triggers or automation platforms. Services such as IFTTT, Zapier, or custom cloud functions can poll for new entries and trigger downstream actions — posting to social media, notifying collaborators, or initiating backups.
Parsing and Consuming Feeds
Client-Side Rendering
For quick integrations or widgets, parse the feed and prefer the RSS <enclosure> element for images. The enclosure is written by our feed generator and contains the media proxy URL. Example (browser, DOMParser):
const res = await fetch('https://exposera.com/u/example/feed.xml');
const xml = await res.text();
const doc = new DOMParser().parseFromString(xml, 'application/xml');
const items = [...doc.querySelectorAll('item')].map(node => {
const enclosureEl = node.querySelector('enclosure');
return {
title: node.querySelector('title')?.textContent || '',
link: node.querySelector('link')?.textContent || '',
guid: node.querySelector('guid')?.textContent || '',
pubDate: node.querySelector('pubDate')?.textContent || '',
imageUrl: enclosureEl ? enclosureEl.getAttribute('url') : null,
imageType: enclosureEl ? enclosureEl.getAttribute('type') : null,
};
});
This uses the enclosure as the primary image source; fallbacks (parsing HTML in description/content) are possible but unnecessary for standard photo items.
Build-Time Integration for Static Sites
In Node-based static site generators, rss-parser maps enclosure to item.enclosure. Use it as the primary image source during builds:
const Parser = require('rss-parser');
const parser = new Parser();
async function fetchFeed(url) {
const feed = await parser.parseURL(url);
return feed.items.map(i => ({
id: i.guid || i.id,
title: i.title,
link: i.link,
published: i.pubDate
? new Date(i.pubDate)
: i.isoDate && new Date(i.isoDate),
content: i.contentSnippet || i.content || i.summary,
imageUrl: i.enclosure?.url || null,
imageType: i.enclosure?.type || null,
}));
}
(async () => {
const items = await fetchFeed(
'https://exposera.com/u/example/albums/travel/feed.xml'
);
// integrate items into your build pipeline (download/rehost enclosure URLs if you need long-term assets)
})();
Serverless Synchronization
For continuous updates, prefer the enclosure field as the authoritative image link; only parse HTML content as a fallback. Example sync that favors the enclosure URL:
const Parser = require('rss-parser');
const parser = new Parser();
async function syncFeed(url, lastSeenId) {
const feed = await parser.parseURL(url);
const newItems = (feed.items || []).filter(
i => i.guid && i.guid !== lastSeenId
);
for (const item of newItems.reverse()) {
const imageUrl = item.enclosure?.url || null;
// If imageUrl is present, download/rehost it for long-term use
await createOrUpdateInCMS({
id: item.guid || item.id,
title: item.title,
url: item.link,
image: imageUrl,
published: item.isoDate || item.pubDate,
});
lastSeenId = item.guid || item.id;
}
return lastSeenId;
}
This function can run on Cloudflare Workers, AWS Lambda, or any cron-based environment to keep external sites in sync.
Example Architecture: A Real-Time Portfolio
A minimal always-up-to-date portfolio might look like this:
- A scheduled serverless function polls
https://exposera.com/u/:username/feed.xmlevery ten minutes. - It checks the most recent
guidagainst a stored value to identify new uploads. - For each new item, it fetches the thumbnail or transformed image and stores it in a local CMS or object store.
- The portfolio website, either static or dynamic, reads from that local store to render the gallery.
This model decouples your external site from Exposera’s internal architecture while keeping the two synchronized. Because all data flows through open protocols, the system remains transparent and easily portable.
Security and Privacy
Feed visibility always mirrors the visibility of the underlying content. Public items appear in public feeds, while private or restricted items do not.
Closing Thoughts
RSS and Atom feeds are quiet technologies — nearly invisible but endlessly useful. In a landscape dominated by proprietary APIs and opaque integrations, they remain one of the last truly open conduits for content on the web.
At Exposera, we see them as connective tissue: a simple, standards-based mechanism that allows your work to travel beyond our platform without friction. Whether you want a reader that displays your latest images, a static site that rebuilds itself automatically, or a real-time mirror of your portfolio in another system, these feeds make it possible with just a few lines of code.
If you’d like guidance or examples for your own integration, reach out through the Exposera community forum or open an issue on our documentation repository. We’re always glad to help photographers build bridges between their tools, their sites, and their audiences — one feed at a time.
A home for your best work - built by photographers
Keep your originals, control who sees them, and share galleries that feel fast and crafted. No ads, no algorithmic tricks - just clean, high-fidelity presentation for photographers who care about craft.
Built to preserve your art - think of it as your online darkroom.