**Isso** is an[ open source](https://github.com/isso-comments/isso), Python powered comment system that you can spin up on your own webserver and embed on any page. I tinkered with embedding **Disqus** before this, but since it loads in an `iframe` you have very little control over it’s look. Isso, on the other hand, can be fully styled with CSS. ^preview
## Initial Setup
The following assumes you already have Isso up and running on a webserver. The [Quick Start](https://isso-comments.de/docs/guides/quickstart/) guide should be all you need—there is no special setup required for Obsidian, but of course you already need to be comfortable messing around in a webserver of your own.
## Embedding Isso
Below is the JS I used to do the embedding. This set up allows you to create a frontmatter property called `comments` and set it to `on` to control which pages load Isso. It essentially does the following:
1. Observe some element on the page to know when Obsidian has loaded content.
> [!info]
> Obsidian does not generate static HTML to serve the main content area—it seems to hydrate the page shortly after load. If you try to access certain DOM elements or window properties too early, you will get nothing. Below, I observe the frontmatter element, but it could be anything in the content area.
2. Check the value of the `comments` frontmatter property, which should be accessible from the Obsidian `app` property attached to the window.
3. We then add Isso’s content div if it doesn’t exist. If it does, comments need to be reloaded, so we unload the Isso script to make sure it refreshes the comments based on the current page.
4. We then load the Isso script, which should populate the content div.
5. Finally, I personally didn’t like the placement of the action buttons below the text area, so I use some JS to move the buttons above the text area instead.
```js
function observeFrontMatter() {
const observer = new MutationObserver((mutations, obs) => {
if (document.querySelector('.frontmatter')) {
console.log('frontmatter loaded')
setTimeout(issoComments, 100);
obs.disconnect();
}
});
observer.observe(document.body, {
childList: true,
subtree: true,
});
}
function issoComments() {
if (window.app?.render?.renderer?.frontmatter?.comments != 'on')
return;
console.log('loading isso');
const d = document;
if (!d.getElementById('isso-thread')) {
const e = d.createElement('section');
e.id = 'isso-thread';
e.className = 'comments';
(d.getElementsByClassName('mod-footer')[0]).appendChild(e);
} else {
d.getElementById('isso-script').remove();
}
if (!d.getElementById('isso-script')) {
const s = d.createElement('script');
s.id='isso-script';
s.src = '//comments.metaphist.com/js/embed.min.js';
s.setAttribute('data-isso', '//comments.metaphist.com/');
(d.head || d.body).appendChild(s);
}
// adjustments
const i = setInterval(function() {
if (!d.getElementsByClassName('isso-form-wrapper')[0])
return;
clearInterval(i);
const form = d.getElementsByClassName('isso-form-wrapper')[0];
const ta = d.getElementsByClassName('isso-textarea-wrapper')[0];
const buttons = d.getElementsByClassName('isso-post-action');
console.log('adjusting isso', form, ta, buttons);
for (const b of buttons) {
form.insertBefore(b, ta);
}
}, 100);
}
```
## Styling
The main goal was to use existing colors to make Isso fit in with the current theme. At the time of writing, this was Minimal’s “Ayu” theme.
```css
section#isso-thread {
margin-top: 48px;
padding-top: 10px;
border-top: 1px solid var(--background-modifier-border);
}
#isso-thread h4.isso-thread-heading {
color: var(--h4-color);
}
#isso-thread .isso-textarea-wrapper {
clear: both;
}
#isso-thread .isso-input-wrapper {
max-width: 32%;
margin-right: 2%;
margin-top: 0;
}
#isso-thread .isso-input-wrapper:last-of-type {
margin-right: 0;
}
@media screen and (max-width: 600px) {
#isso-thread .isso-input-wrapper {
max-width: 100%;
margin: 0 0 1em;
}
#isso-thread .isso-textarea {
margin-bottom: .6em;
}
}
#isso-thread .isso-input-wrapper input,
#isso-thread .isso-textarea {
background-color: var(--sidebar-left-background);
border-color: var(--background-modifier-border);
border-radius: var(--input-radius);
color: var(--text-normal);
}
#isso-thread .isso-post-action > input {
border: 1px solid var(--background-modifier-border);
padding: .5em;
border-radius: .5em;
background-color: var(--bg2);
color: var(--tx2);
}
#isso-thread .isso-author {
color: var(--tx2);
}
```