![[IMG-Add Social Links to the Sidebar of an Obsidian Publish Site-20250624215017919.png|600]]
</br>
---
I recently came up with a method to add links to your social media profiles to modify my Obsidian site. Here’s a guide to walk you through what modifications I did to make this possible. This method uses a combination of JavaScript (to create the elements) and CSS (to style them).
**Preview of Social Links for Left Side Panel**</br>
![[IMG-Add Social Links to the Sidebar of an Obsidian Publish Site-20250624215018072.png|300]]
</br>
### Step 1: Create the JavaScript (`publish.js`)
The `publish.js` file is responsible for creating the HTML for the "Connect" box and its icons. It runs automatically every time a page is loaded on your site.
**Sample of my Obsidian vault opened in VS Code**</br>
![[IMG-Add Social Links to the Sidebar of an Obsidian Publish Site-20250624215018125.png|300]]
</br>
1. Use a code editor, like VS Code to open your Obsidian vault.
2. Inside that folder, create a file named `publish.js`.
3. Copy and paste the entire code block below into your `publish.js` file.
4. Inside code look for function insertSocialLinks(), and edit the social urls to match your own.
</br>
>[!Note]
>This is a modified code sample taken from:
> - https://lab.marconoris.com/obsidian/footer-customization
>
> This sample was discovered on the Obsidian discord channel.
> The code sample contains lots of examples of other social profiles.
</br>
** Code Block: Publish.js**
```js
/**
* @file publish.js
* @description This script enhances an Obsidian Publish site by dynamically inserting frontmatter properties
* @note origianl code modified from https://lab.marconoris.com/obsidian/footer-customization
*/
let publishIntervalId;
/**
* @function insertCustomProperties
* @description Checks for frontmatter in the current note and injects it as styled elements
* at the top of the page, below the main properties block.
* @returns {boolean} Returns true if the task is complete (or not needed), false if the required
* DOM elements are not yet available.
*/
function insertCustomProperties() {
const frontmatterEl = document.querySelector(".frontmatter");
if (!frontmatterEl) return true;
if (
frontmatterEl.nextElementSibling?.classList.contains(
"custom-properties-container"
)
)
return true;
const frontmatter = app.site.cache.cache[app.currentFilepath]?.frontmatter;
if (!frontmatter) return true;
const author = frontmatter["author"];
const published = frontmatter["published"];
const updated = frontmatter["updated"];
const tags = frontmatter["tags"];
const authorUrl = "https://davidrusho.com/about_me";
const propertiesToDisplay = [];
if (author)
propertiesToDisplay.push(
`<div class="property-item">
<a href="${authorUrl}" class="property-tag" target="_blank" rel="noopener"
>Author: ${author}</a
>
</div>`
);
if (published)
propertiesToDisplay.push(
`<div class="property-item">
<a href="#" class="property-tag" target="_blank" rel="noopener"
>Published: ${published.replaceAll("-", ".")}</a
>
</div>`
);
if (updated)
propertiesToDisplay.push(
`<div class="property-item">
<a href="#" class="property-tag" target="_blank" rel="noopener"
>updated: ${updated.replaceAll("-", ".")}</a
>
</div>`
);
if (tags && Array.isArray(tags) && tags.length > 0) {
const tagLinks = tags
.map(
(tag) =>
`<a
href="/#${encodeURIComponent(tag)}"
class="tag"
target="_blank"
rel="noopener"
>#${tag}</a>`
)
.join(" ");
propertiesToDisplay.push(
`<div class="property-item property-tags-container">
<span class="tags-label">Tags:</span
><span class="tags-values">${tagLinks}</span>
</div>`
);
}
if (propertiesToDisplay.length > 0) {
frontmatterEl.insertAdjacentHTML(
"afterend",
`<div class="custom-properties-container">${propertiesToDisplay.join(
""
)}</div>`
);
}
return true;
}
/**
* @function insertSocialLinks
* @description Finds the theme-toggle button in the sidebar and injects a styled "Connect" box
* with social media icons directly after it.
* @returns {boolean} Returns true if the task is complete (or not needed), false if the required
* DOM elements are not yet available.
*/
function insertSocialLinks() {
const siteThemeToggleEl = document.querySelector(
".site-body-left-column-site-theme-toggle"
);
if (!siteThemeToggleEl) {
return false;
}
if (document.querySelector(".sidebar-social-container")) {
return true;
}
// >>> EDIT YOUR SOCIAL MEDIA LINKS HERE <<<
const socials = [
{
url: "https://github.com/drusho", // >>> REPLACE URL WITH YOUR OWN
name: "GitHub",
svg: `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" role="img">
<path
d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0 0 16 8c0-4.42-3.58-8-8-8z"
></path>
</svg>`,
},
{
url: "https://linkedin.com/in/davidrusho", // >>> REPLACE URL WITH YOUR OWN
name: "LinkedIn",
svg: `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" role="img">
<path
d="M0 1.146C0 .513.526 0 1.175 0h13.65C15.474 0 16 .513 16 1.146v13.708c0 .633-.526 1.146-1.175 1.146H1.175C.526 16 0 15.487 0 14.854V1.146zm4.943 12.248V6.169H2.542v7.225h2.401zm-1.2-8.212c.837 0 1.358-.554 1.358-1.248-.015-.709-.52-1.248-1.342-1.248-.822 0-1.359.54-1.359 1.248 0 .694.521 1.248 1.327 1.248h.016zm4.908 8.212V9.359c0-.216.016-.432.08-.586.173-.431.568-.878 1.232-.878.869 0 1.216.662 1.216 1.634v3.865h2.401V9.25c0-2.22-1.184-3.252-2.764-3.252-1.274 0-1.845.7-2.165 1.193v.025h-.016a5.54 5.54 0 0 1 .016-.025V6.169h-2.4c.03.678 0 7.225 0 7.225h2.4z"
></path>
</svg>
`,
},
];
const socialLinksHTML = `<div class="sidebar-social-container">
<h3 class="sidebar-social-title">Connect</h3>
<div class="sidebar-social-links">
${socials
.map(
(s) => `<a
href="${s.url}"
target="_blank"
rel="noopener"
aria-label="${s.name}"
title="${s.name}"
>${s.svg}</a
>`
)
.join("")}
</div>
</div>
`;
siteThemeToggleEl.insertAdjacentHTML("afterend", socialLinksHTML);
return true;
}
/**
* @function runScriptsAndClearInterval
* @description A controller function that runs all enhancement scripts. When all scripts
* confirm they are finished, it clears the master interval timer.
*/
function runScriptsAndClearInterval() {
try {
const propertiesDone = insertCustomProperties();
const socialLinksDone = insertSocialLinks();
if (propertiesDone && socialLinksDone) {
clearInterval(publishIntervalId);
}
} catch (e) {
console.error("Publish script error:", e);
clearInterval(publishIntervalId);
}
}
/**
* @function onChangeDOM
* @description A callback for the MutationObserver that detects when a page navigation occurs
* in Obsidian Publish and re-runs the scripts.
* @param {MutationRecord[]} mutationsList - A list of mutations that were observed.
* @param {MutationObserver} observer - The observer instance.
*/
const onChangeDOM = (mutationsList, observer) => {
const pageChanged = mutationsList.some((mutation) =>
Array.from(mutation.addedNodes).some(
(node) =>
node.nodeType === 1 &&
(node.matches(".page-header") || node.querySelector(".page-header"))
)
);
if (pageChanged) {
clearInterval(publishIntervalId);
publishIntervalId = setInterval(runScriptsAndClearInterval, 100);
}
};
// --- Script Initialization ---
const targetNode = document.querySelector(
".markdown-preview-sizer.markdown-preview-section"
);
if (targetNode) {
const observer = new MutationObserver(onChangeDOM);
observer.observe(targetNode, {
childList: true,
subtree: true,
});
}
// Initial run for the first page load.
publishIntervalId = setInterval(runScriptsAndClearInterval, 100);
```
</br>
### Step 2: Add the Styling (`publish.css`)
The CSS code is used to add style to the "Connect" title, and icons.
1. Just as we did with `publish.js` , create a `publish.css` in your root folder using a code editor like VS Code.
2. Copy and paste the code below into `publish.css`. There isn’t anything to modify in the section, but feel free to play around with setting to make them fit your sites style.
```css
/*
|--------------------------------------------------------------------------
|-- Sidebar Social Links Styling
|--------------------------------------------------------------------------
| Styles for the "Connect" box containing social media icons,
| injected below the theme toggle in the left sidebar.
*/
/* The main container box for the social links section */
.sidebar-social-container {
border: 1px solid var(--background-modifier-border);
border-radius: 8px;
padding: 8px 12px;
margin-top: 1.5em;
display: flex;
align-items: center;
justify-content: flex-start;
gap: 16px;
}
/* The "Connect" title */
.sidebar-social-title {
font-size: var(--font-small);
font-weight: 500;
color: var(--text-muted);
letter-spacing: 0.05em;
text-transform: uppercase;
margin: 0;
}
/* The container for the icons */
.sidebar-social-links {
display: flex;
align-items: center;
gap: 12px;
}
/* Style the SVG icons themselves */
.sidebar-social-links svg {
width: 20px;
height: 20px;
fill: var(--text-muted);
transition: all 0.2s ease-in-out;
}
/* Add a hover effect to the icons */
.sidebar-social-links a:hover svg {
fill: var(--text-accent);
transform: scale(1.1);
}
```
</br>
### Step 3: Upload and Publish
1. Make sure to save the files (`publish.js` and `publish.css` inside your code editor.
2. Open Obsidian and go to **Settings** -> **Publish**.
3. In the "Publish changes" dialog, make sure your new/updated `publish.js` and `publish.css` files are selected for upload.
4. Click **"Publish"**.
**Sample of Obsidian Publish Menu**</br>
![[IMG-Add Social Links to the Sidebar of an Obsidian Publish Site-20250624215018257.png|500]]
Your site should now display the "Connect" box with your social links in the sidebar on every page.</br>
![[IMG-Add Social Links to the Sidebar of an Obsidian Publish Site-20250624215018072.png|400]]
---
## Resources
</br>
### Related Articles
Check out the other articles from **Obsidian Publish Recipes** series:
%% DATAVIEW_PUBLISH_CONVERT start
```dataview
LIST WITHOUT ID
"**" + file.link + "** </br>" + description + "</br></br>"
FROM "07 - Publish - Obsidian"
WHERE
publish = true
AND file.name != "About Me"
AND file.name != "Home"
AND series = "Obsidian Publish Recipes"
SORT date DESC
```
%%
- **[[07 - Publish - Obsidian/Articles/Add Social Links to the Footer of an Obsidian Publish Site.md|Add Social Links to the Footer of an Obsidian Publish Site]]** </br>How to customize an Obsidian Publish site by adding a social media links to the footer. This guide uses simple JavaScript and CSS to "hijack" your theme's default footer, creating a clean footer that appears on every page.</br></br>
- **[[07 - Publish - Obsidian/Articles/Add Social Links to the Sidebar of an Obsidian Publish Site.md|Add Social Links to the Sidebar of an Obsidian Publish Site]]** </br>Customize your Obsidian Publish site by adding social media icons to the sidebar. This step-by-step guide uses simple CSS and JavaScript to create a "Connect" box that appears on every page, enhancing your site's professional look.</br></br>
- **[[07 - Publish - Obsidian/Articles/Obsidian Publish Workflow - Automating Publication Prep.md|Obsidian Publish Workflow - Automating Publication Prep]]** </br>Walkthrough of a Templater script to automate Obsidian Publish workflow. The script manages frontmatter properties and converts Dataview queries to static Markdown.</br></br>
- **[[07 - Publish - Obsidian/Posts/Series/Series - Obsidian Publish Recipes.md|Series - Obsidian Publish Recipes]]** </br>Articles related to customizing Obsidian Publish sites using javascript and css.</br></br>
%% DATAVIEW_PUBLISH_CONVERT end %%