<!-- RSS Reader Embed - paste all of this into your Slashpage Custom HTML/Embed -->
<div id="rss-embed" style="max-width:900px;margin:0 auto;font-family:Inter,system-ui,Segoe UI,Roboto,Helvetica,Arial,sans-serif;">
<style>
/* Embedded reader styles (scoped using #rss-embed) */
#rss-embed .rp-header{display:flex;align-items:center;justify-content:space-between;margin:12px 0}
#rss-embed .rp-title{font-size:20px;font-weight:700}
#rss-embed .rp-controls{display:flex;gap:8px;align-items:center}
#rss-embed .rp-input{padding:8px 10px;border:1px solid #e3e7ee;border-radius:8px;width:320px}
#rss-embed .rp-list{display:grid;grid-template-columns:1fr;gap:12px;margin-top:14px}
#rss-embed .rp-card{display:flex;gap:12px;padding:12px;border-radius:12px;border:1px solid #eef2f6;background:#fff;box-shadow:0 6px 18px rgba(20,30,40,0.04);align-items:center}
#rss-embed .rp-thumb{width:110px;height:70px;border-radius:8px;object-fit:cover;flex:0 0 110px;background:#f4f7fb}
#rss-embed .rp-meta{display:flex;flex-direction:column;gap:6px}
#rss-embed .rp-title-link{font-size:15px;font-weight:600;color:#0b61ff;text-decoration:none}
#rss-embed .rp-desc{font-size:13px;color:#52606d;max-height:3.6em;overflow:hidden}
#rss-embed .rp-source{font-size:12px;color:#9aa6b2}
#rss-embed .rp-empty{padding:18px;text-align:center;color:#6b7280}
#rss-embed .rp-load{opacity:0.9;color:#374151}
@media (max-width:640px){
#rss-embed .rp-card{flex-direction:column;align-items:flex-start}
#rss-embed .rp-thumb{width:100%;height:160px;flex:1 1 auto}
#rss-embed .rp-input{width:100%}
}
</style>
<div class="rp-header">
<div class="rp-title">Feeds</div>
<div class="rp-controls">
<input class="rp-input" id="rp-feed-url" placeholder="Enter RSS feed URL, e.g. https://example.com/feed" />
<button id="rp-add" style="padding:8px 12px;border-radius:8px;background:#0b61ff;color:#fff;border:none;cursor:pointer">Add</button>
</div>
</div>
<div id="rp-status" class="rp-empty">Add a feed URL to show items.</div>
<div id="rp-list" class="rp-list" aria-live="polite"></div>
</div>
<script>
(function(){
// Configuration: public RSS->JSON proxy. Swap if you have another.
const PROXY = 'https://api.rss2json.com/v1/api.json?rss_url=';
// For more reliable service, consider rss2json with an API key or rss2email proxies.
const el = (sel) => document.querySelector('#rss-embed ' + sel);
const status = document.getElementById('rp-status');
const list = document.getElementById('rp-list');
const input = document.getElementById('rp-feed-url');
const addBtn = document.getElementById('rp-add');
function showStatus(txt){
status.textContent = txt;
status.className = 'rp-load';
}
function clearStatus(){
status.textContent = '';
status.className = '';
}
function createCard(item){
const card = document.createElement('article');
card.className = 'rp-card';
const thumb = document.createElement('img');
thumb.className = 'rp-thumb';
thumb.alt = '';
thumb.src = item.enclosure?.link || item.thumbnail || item.image || '';
const meta = document.createElement('div');
meta.className = 'rp-meta';
const title = document.createElement('a');
title.className = 'rp-title-link';
title.href = item.link || '#';
title.target = '_blank';
title.rel = 'noopener noreferrer';
title.textContent = item.title || 'Untitled';
const desc = document.createElement('div');
desc.className = 'rp-desc';
desc.innerHTML = (item.description || item.contentSnippet || '').replace(/<img[^>]*>/g,'');
const src = document.createElement('div');
src.className = 'rp-source';
src.textContent = item.author ? item.author + ' • ' + new Date(item.pubDate).toLocaleString() : new Date(item.pubDate).toLocaleString();
meta.appendChild(title);
meta.appendChild(desc);
meta.appendChild(src);
// if there's no image, hide img element to keep layout clean
if(!thumb.src) thumb.style.display = 'none';
card.appendChild(thumb);
card.appendChild(meta);
return card;
}
async function fetchFeed(url){
try{
showStatus('Loading feed…');
list.innerHTML = '';
const res = await fetch(PROXY + encodeURIComponent(url));
if(!res.ok) throw new Error('Network error');
const data = await res.json();
if(data.status === 'ok' && Array.isArray(data.items)){
if(data.items.length === 0){
status.textContent = 'No items found in that feed.';
return;
}
clearStatus();
data.items.slice(0,12).forEach(item => list.appendChild(createCard(item)));
} else {
throw new Error(data.message || 'Invalid feed');
}
}catch(err){
status.textContent = 'Failed to load feed. ' + (err.message || '');
}
}
addBtn.addEventListener('click', ()=>{
const url = (input.value || '').trim();
if(!url) return;
fetchFeed(url);
});
input.addEventListener('keydown',(e)=>{
if(e.key === 'Enter') addBtn.click();
});
// Example starter feeds
const example = 'https://rss.nytimes.com/services/xml/rss/nyt/Technology.xml';
input.value = example;
// auto-load example
fetchFeed(example);
})();
</script>