Sign In

RSS FEED

<!-- 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>