How to add a Substack feed to Squarespace

If you're publishing on Substack and running a website on Squarespace, you've probably wished you could display your latest posts directly on your site without copying and pasting them manually every time.

The good news? You can. With a small snippet of code added to a Squarespace Code Block, your Substack posts will appear automatically on your site, updating every time you publish something new.

This tutorial walks you through the whole process step by step.

Table of Contents

Why there's no built-in integration

Squarespace doesn't currently offer a native Substack block or direct integration. Substack also doesn't provide an official embed widget for third-party sites.

However, every Substack publication automatically generates an RSS feed a standard web format that lists your latest posts. We can use that feed to pull your posts into Squarespace using a Code Block.

How it works

Your Substack RSS feed lives at:

https://yourname.substack.com/feed

The code fetches that feed when a visitor loads your page, parses your posts, and displays them as styled cards with the post title, excerpt, image, date, and a link to read the full article on Substack.

No plugins, no third-party accounts, and no monthly fees required.

What you'll need

  • A Squarespace 7.1 website

  • A Substack publication with at least one published post

  • Access to the Squarespace editor

Step-by-step instructions

Step 1: Copy the code

Paste the following code into a text editor, replacing https://yourname.substack.com with your actual Substack URL:

<!-- Copyright Primitus Consultancy -->
<!-- Substack Feed Embed -->
<style>
  #substack-feed a { text-decoration: none; }

  .ss-card {
    background: #fdfcf7;
    border: 1px solid #e8e4d9;
    border-radius: 10px;
    overflow: hidden;
    margin-bottom: 16px;
    display: flex;
    flex-direction: row;
    align-items: stretch;
  }

  .ss-card-body {
    flex: 1;
    padding: 18px 20px;
    display: flex;
    flex-direction: column;
    justify-content: center;
    min-width: 0;
  }

  .ss-card-date { font-size: 12px; color: #999; margin: 0 0 6px; font-family: sans-serif; }
  .ss-card-title { font-size: 17px; font-weight: 700; color: #1a1a1a; line-height: 1.35; margin: 0 0 8px; display: block; }
  .ss-card-title:hover { text-decoration: underline; }
  .ss-card-excerpt { font-size: 14px; color: #666; line-height: 1.6; margin: 0 0 10px; font-family: sans-serif; }
  .ss-card-read { font-size: 13px; color: #888; font-family: sans-serif; }

  .ss-card-img-wrap {
    flex-shrink: 0;
    width: 220px;
    overflow: hidden;
    border-radius: 0 10px 10px 0;
  }

  .ss-card-img-wrap img {
    width: 100%;
    height: 100%;
    object-fit: contain;
    object-position: center;
    display: block;
    background: #f0ede6;
  }

  .ss-no-img .ss-card-img-wrap { display: none; }

  @media (max-width: 520px) {
    .ss-card { flex-direction: column; }

    .ss-card-img-wrap {
      width: 100%;
      height: auto;
      border-radius: 0 0 10px 10px;
    }

    .ss-card-img-wrap img {
      height: auto;
      object-fit: contain;
    }
  }
</style>

<div id="substack-feed" style="font-family: Georgia, serif; max-width: 680px; margin: 0 auto;">
  <p style="color:#888;font-size:14px;font-family:sans-serif;">Loading posts…</p>
</div>

<script>
(function () {

  const PC_SubstackBaseURL = "https://yourname.substack.com"; /* REPLACE WITH YOUR SUBSTACK URL */
  const PC_MaxPosts = 5;
  const PC_ShowExcerpt = true;
  const PC_ShowDate = false;

  const PC_Proxies = [
    "https://api.allorigins.win/get?url=" + encodeURIComponent(PC_SubstackBaseURL + "/feed"),
    "https://corsproxy.io/?" + encodeURIComponent(PC_SubstackBaseURL + "/feed")
  ];

  function PC_ExtractImageFromItem(item) {

    const enclosure = item.querySelector("enclosure[type^='image']");
    if (enclosure) return enclosure.getAttribute("url");

    const media = item.querySelector("*|content[medium='image'], *|thumbnail");
    if (media) return media.getAttribute("url");

    const description = item.querySelector("description")
      ? item.querySelector("description").textContent
      : "";

    const match = description.match(/src=["']([^"']+\.(?:jpg|jpeg|png|webp)[^"']*)/i);
    if (match) return match[1];

    return "";
  }

  function PC_ParseSubstackXML(xmlString) {

    const parser = new DOMParser();
    const xml = parser.parseFromString(xmlString, "text/xml");

    const items = Array.from(xml.querySelectorAll("item")).slice(0, PC_MaxPosts);

    return items.map(function (item) {
      return {
        title: item.querySelector("title") ? item.querySelector("title").textContent : "",
        link: item.querySelector("link") ? item.querySelector("link").textContent : "",
        pubDate: item.querySelector("pubDate") ? item.querySelector("pubDate").textContent : "",
        description: item.querySelector("description") ? item.querySelector("description").textContent : "",
        image: PC_ExtractImageFromItem(item)
      };
    });
  }

  function PC_RenderSubstackFeed(posts) {

    const feedEl = document.getElementById("substack-feed");

    if (!posts || !posts.length) {
      feedEl.innerHTML = "<p style='color:#888;font-family:sans-serif;'>No posts found.</p>";
      return;
    }

    feedEl.innerHTML = posts.map(function (post) {

      const hasImage = !!post.image;

      const imageHTML = hasImage
        ? "<div class='ss-card-img-wrap'><img src='" + post.image + "' alt='' loading='lazy' /></div>"
        : "";

      const dateHTML = PC_ShowDate && post.pubDate
        ? "<p class='ss-card-date'>" + new Date(post.pubDate).toLocaleDateString(
            "en-US",
            { year: "numeric", month: "long", day: "numeric" }
          ) + "</p>"
        : "";

      const cleanText = post.description
        .replace(/<[^>]+>/g, "")
        .replace(/&[a-z]+;/gi, " ")
        .trim();

      const excerptHTML = PC_ShowExcerpt && cleanText
        ? "<p class='ss-card-excerpt'>" + cleanText.substring(0, 160) + "…</p>"
        : "";

      return "<div class='ss-card" + (hasImage ? "" : " ss-no-img") + "'>"
        + "<div class='ss-card-body'>"
        + dateHTML
        + "<a href='" + post.link + "' target='_blank' class='ss-card-title'>" + post.title + "</a>"
        + excerptHTML
        + "<span class='ss-card-read'>Read →</span>"
        + "</div>"
        + imageHTML
        + "</div>";

    }).join("");
  }

  function PC_TryLoadSubstackFeed(proxyIndex) {

    if (proxyIndex >= PC_Proxies.length) {
      document.getElementById("substack-feed").innerHTML =
        "<p style='color:#888;font-family:sans-serif;'>Could not load posts.</p>";
      return;
    }

    fetch(PC_Proxies[proxyIndex])
      .then(function (response) {
        return response.json();
      })
      .then(function (data) {

        const xml = data.contents || data.body || "";
        const posts = PC_ParseSubstackXML(xml);

        if (posts.length) {
          PC_RenderSubstackFeed(posts);
        } else {
          PC_TryLoadSubstackFeed(proxyIndex + 1);
        }

      })
      .catch(function () {
        PC_TryLoadSubstackFeed(proxyIndex + 1);
      });
  }

  PC_TryLoadSubstackFeed(0);

})();
</script>
<!-- End Substack Feed Embed -->

Step 2: Replace the Substack URL

Find this line near the top of the script section:

javascript

Const PC_SubstackBaseURL = "https://yourname.substack.com";

Replace https://yourname.substack.com with your actual Substack publication URL. For example:

javascript

Const PC_SubstackBaseURL = "https://eliyalbert.substack.com";

Step 3: Add a Code Block in Squarespace

  1. Open the Squarespace editor and navigate to the page where you want the feed to appear

  2. Click the + button to add a new block

  3. Select Code from the block menu

  4. In the code editor that appears, make sure the mode is set to HTML (not Markdown)

  5. Paste your code into the block

  6. Click Apply

Step 4: Save and preview

Click Save in the editor. Switch to the live preview or visit your published page to see the feed in action.

Your Substack posts will appear as horizontal cards post title and excerpt on the left, thumbnail image on the right.

Customising the feed

You can adjust a few variables at the top of the script to change how the feed looks:

Number of posts shown

const PC_MaxPosts = 5;

Change 5 to however many posts you want to display.

Show or hide the excerpt

const PC_ShowExcerpt = true;

Set to false to hide the excerpt and show only the title.

Show or hide the date

const PC_ShowDate = false;

Set to true to display the publication date below each post title.

Card background colour

In the <style> section, find:

css

background: #fdfcf7;

Replace #fdfcf7 with any hex colour to match your site's palette.

Image width

css

.ss-card-img-wrap { width: 220px; ... }

Increase or decrease the 220px value to make the thumbnail larger or smaller.

Troubleshooting

The feed shows "Loading posts…" but never loads

This usually means the CORS proxy is slow or temporarily unavailable. The code automatically tries a second proxy if the first one fails. Wait a few seconds and refresh. If it persists, check that your Substack URL is correct and that your publication has at least one public post.

Posts show but no image appears

Not all Substack posts include a cover image. If your post doesn't have one, the card will display as text-only with no empty space — this is by design.

The feed loads slowly

The code fetches your RSS feed live on every page load, which takes a second or two depending on network conditions. If load speed is important, consider adding localStorage caching so repeat visitors see posts instantly.

"Could not load posts" appears

Double-check that your Substack URL is correct and that your publication is public (not behind a paywall or set to private). You can verify by visiting https://yourname.substack.com/feed directly in a browser you should see raw RSS XML.


Key Takeaways

  • Squarespace has no native Substack integration, but every Substack has a public RSS feed at /feed

  • A Code Block set to HTML mode lets you inject custom JavaScript into any Squarespace page

  • The feed fetches and parses RSS automatically no manual updates needed when you publish

  • The code uses two CORS proxy fallbacks to ensure reliable loading

  • You can customise the number of posts, colours, image size, and whether excerpts and dates are shown

FAQs

Will this work on Squarespace 7.0?
This code works on both Squarespace 7.0 and 7.1. The Code Block behaves the same way on both versions.

Will it update automatically when I publish a new post?
Yes. The feed is fetched live from your Substack RSS every time the page loads, so new posts appear automatically without any changes to your Squarespace site.

Will this show paywalled posts?
No. Substack's public RSS feed only includes posts you've made available to free subscribers. Paid-only posts will not appear.

Can I add this to multiple pages?
Yes. You can paste the same code block onto as many pages as you like.

Does this affect my site's SEO?
The posts are loaded via JavaScript after the page renders, so search engines may not index the post titles displayed by this feed. If SEO is a priority, consider also linking to your Substack profile from a regular text or button block.

Can I style it to match my Squarespace theme exactly?
Yes. All the styling is in the <style> section at the top of the code. You can adjust fonts, colours, border radius, padding, and spacing to match your site's design.



Conclusion

Embedding your Substack feed in Squarespace takes just a few minutes and keeps your website fresh without any extra work on your end. Every time you publish a new post on Substack, it automatically appears on your Squarespace page.

The approach uses your Substack's built-in RSS feed no plugins, no paid tools, and no ongoing maintenance required.

If you run into any issues or want help tweaking the design to better fit your site, feel free to get in touch.


If you have any questions or need any help with your Squarespace website design, you can book a 1:1 consultation.


All work in this guide is provided ‘as-is’. Other than as provided this guide makes no other warranties, expressed or implied, and hereby disclaims all implied warranties, including any warranty of fitness for a particular purpose.

If you require professional advice, you can book our consultation services.

Primitus Consultancy

We work with small and medium-sized businesses to help create a professional online presence. We provide a one shop full-service design studio in London, United Kingdom. 

https://primitusconsultancy.co.uk
Previous
Previous

How to create a “Read More” dropdown in Auto Layouts (Squarespace 7.1)

Next
Next

How to change the speed of your background video on Squarespace 7.1