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/feedThe 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
Open the Squarespace editor and navigate to the page where you want the feed to appear
Click the + button to add a new block
Select Code from the block menu
In the code editor that appears, make sure the mode is set to HTML (not Markdown)
Paste your code into the block
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.