# Behind the Blog If you're curious about how to build a digital garden using the same tools I do, you might find what you're looking for here. This page serves as a behind-the-scenes guide, walking you through the steps I took and giving insight into some of the customisations this site uses. > A quick **disclaimer** up front: I'm not a coder. Most of what you see here, especially the JavaScript, is heavily jerry-rigged and most definitely not best practice. Because of that, I won’t cover every technical detail, particularly where it gets messy. There are probably better, more efficient ways to implement some of what I’ve done and I’m open to any ideas and feedback! ## Obsidian [Obsidian](https://obsidian.md) is a free, powerful note-taking tool that works with plain Markdown files, making it ideal for building personal knowledge bases and structured note systems. One of its core features is the use of internal links. These let you easily connect individual notes, turning your ideas into a dynamic, interlinked network. That’s part of why Obsidian has become so popular: it allows you to organize and structure your thoughts in a flexible, non-linear way. For a [full overview of formatting and syntax](https://help.obsidian.md/syntax), you can check the official documentation. ## Obsidian Publish [Obsidian Publish](https://obsidian.md/publish) is a cloud-based hosting service that allows you to publish your Obsidian notes as a wiki, knowledge base, documentation hub, digital garden; or, perhaps less commonly, a personal blog. It works as an add-on service for Obsidian. To get started, you'll first need to [download Obsidian](https://obsidian.md/download) and create an [Obsidian account](https://obsidian.md/auth?returnto=%2Faccount%2Fpublish#signup). (Note: you don't need an account to use Obsidian itself, but it’s required for using Obsidian Publish.) To use Obsidian Publish, you’ll need to purchase a license, which is billed at $10/month or $8/month if paid yearly. Once you’ve purchased a plan: 1. Open Obsidian. 2. Go to **Settings > Account**, and log in. 3. In **Settings > Core Plugins**, enable **Publish**. Now, by clicking the ribbon icon, you’ll be able to select which notes you want to publish. Then just hit **Publish** to send them live. You can also open the settings gear icon in the publish menu to configure options such as your site name, homepage, logo, and other handy customisations. ## Setting up a custom domain By default, your Obsidian Publish site uses its own domain and the ID you choose during setup, resulting in a URL like: `https://publish.obsidian.md/your-id` However, you can also connect your own **custom domain**, as outlined in [Obsidian Publish's official documentation](https://help.obsidian.md/publish/setup). There are multiple ways to set this up, this guide focuses on the approach I used. I used **Cloudflare** to configure the custom domain and **Namecheap** as my domain registrar. ### Purchase your domain First, create an account at [Namecheap](https://www.namecheap.com/), check if your desired domain is available, and purchase it. ![[Screenshot 2025-07-05 at 11.26.43 AM.webp]] ### Add your domain to Cloudflare Create a [Cloudflare](https://cloudflare.com/) account, go to your dashboard, and click on  `Add Site`. ![[Screenshot 2024-07-20 at 18.08.00.webp]] ![[Screenshot 2024-07-20 at 18.08.10.webp]] Enter your domain name and select a plan (the **free plan** works perfectly for this). On Step 4 of the setup, you’ll receive Cloudflare-branded nameservers that look like this: ``` sasha.ns.cloudfare.com sullivan.ns.cloudfare.com ``` ![[Screenshot 2024-07-20 at 18.27.36.webp]] ### Update nameservers on Namecheap Go back to your domain on Namecheap, click **Manage**, scroll to the **Nameservers** section, and switch from `Namecheap BasicDNS` to `Custom DNS`. Paste the two Cloudflare nameservers. ![[Screenshot 2024-07-20 at 18.06.53.webp]] While you're here, also go to **Advanced DNS settings** and ensure **DNSSEC is turned off.** ![[Screenshot 2024-07-20 at 18.07.25.webp]] ### Update nameservers on Namecheap Complete the setup on Cloudflare. The activation can take up to 24 hours, but in my experience, it usually takes just a few minutes. Once your domain is active, Cloudflare will notify you and update your site's status on the dashboard. ![[Screenshot 2024-07-20 at 18.27.49.webp]] ### Set up CNAME records In your Cloudflare `DNS > Records`section, add two **CNAME** entries as required by Obsidian: ![[Screenshot 2024-07-20 at 18.35.17.webp]] ### Connect your domain in Obsidian Publish In your Obsidian workspace, open the **Publish** ribbon icon and go to: **Settings > Custom Domain (Configure)** Add your domain, e.g., `yourdomain.com`. You can also enable the option to **redirect** your `publish.obsidian.md/your-id` URL to your custom domain. ![[Screenshot 2025-07-05 at 10.25.46 AM2.webp]] ## Styling your page using CSS Obsidian Publish allows you to customise the appearance of your site using themes, custom CSS, and JavaScript. To apply custom code, you need to publish the following files alongside your notes: - `publish.css` – for custom CSS - `publish.js` – for custom JavaScript Both files must be saved in the **root directory** (`/`) of your Obsidian vault. Once added, these files won’t appear in Obsidian’s file explorer. To create and edit them, you’ll need to use an external code editor, such as Sublime Text, VS Code, or a similar tool. However, once you've made changes to these files, they will appear in the **Publish Changes** dialog, allowing you to push changes and updates live. ### Adding a custom theme The easiest way to start customising your site, and begin experimenting with custom CSS, is to use an existing theme as a base. This is also the approach I took when building my blog. I used **Kepano’s [Minimal](https://github.com/kepano/obsidian-minimal) theme** as the foundation for my site’s appearance. (Kepano is also the CEO of Obsidian.) You can download the `publish.css` file directly from the theme’s [GitHub repository](https://github.com/kepano/obsidian-minimal-publish) and use it as a starting point for your own customisations. Simply move it into the root directory (`/`) of your Obsidian vault and publish it to your site. ### Modifying a theme using custom CSS Once you’ve published your `publish.css`, you can start experimenting with your own customisations. The easiest way to explore and test changes is by using your browser’s **web inspector**. It allows you to inspect elements, identify their classes, and even edit CSS live on your site to preview the changes in real-time. To do this: 1. Open your browser’s developer tools (usually with `F12` or `Cmd + Option + I` on Mac). 2. Navigate to **Sources** > **Style Sheets** > `publish.css`. 3. You can now add or tweak CSS directly in the browser and see the changes immediately. ![[Screenshot 2025-07-05 at 11.42.55 AM.webp]] If you're ever curious about the exact custom CSS I use, everything is grouped between these separators in my `publish.css`: ``` /* -------------------------------------------------------------*/ /* ------------------- CUSTOM CSS BEGINNING -------------------*/ /* -------------------------------------------------------------*/ ... /* -------------------------------------------------------*/ /* ------------------- CUSTOM CSS END -------------------*/ /* -------------------------------------------------------*/ ``` Below, you can find some examples of the customisations I implemented. #### Adding a custom font Adding custom fonts is fairly easy, especially when using Google Fonts. For my blog, I chose to use **Crimson Text**. To implement it, I copied the `@import` rule from [Google Fonts](https://fonts.google.com/) and placed it at the top of my `publish.css` file: ```css @import url('https://fonts.googleapis.com/css2?family=Crimson+Text:ital,wght@0,400;0,600;0,700;1,400;1,600;1,700&display=swap'); ``` Then, I defined it in the body using CSS variables and the `font-family` property: ```css body { --font-default: 'Crimson Text', !important; --font-text-theme: 'Crimson Text'; font-family: var(--font-text-theme) !important; ... } ``` This will apply *Crimson Text* as the main font throughout your site. #### Changing colours Changing globally used colours in Obsidian Publish is fairly straightforward. Depending on whether you’re using the light or dark theme, you’ll find a corresponding `.theme-light` or `.theme-dark` class that defines the core colour variables. Since I only use the light theme, I’ll focus on that, but the process is identical for the dark theme. To change the **background colours** of your blog, you can edit variables like: - `--bg1`: the background colour of the **right content area** - `--bg2`: the background colour of the **left sidebar** The highlight colour used across the site (e.g. for links, buttons, or accents) is controlled by: - `--ax1`: this is the main accent colour In my case, it's set to a deep red: `#D10303`. Here’s an example of what the light theme section of my `publish.css` looks like: ```css .theme-light { --bg1:#F0F1F2; --bg2:#E9EAEB; --bg3:#E5E5E5; --ui1:#E6E6E6; --ui2:#D6D6D6; --ui3:#C2C2C2; --tx1:#0F0F0F; --tx2:#828282; --tx3:#B5B5B5; --ax1:#D10303; --ax2:#D10303; --ax3:#D10303; --hl1:hsla(201,50%,40%,30%); ``` >**Tip:** When experimenting with colours, use your browser’s web inspector to change these values live and preview the changes instantly. It makes colour tweaking much faster and more intuitive. #### Customising the site name I wanted the site’s logo to match the highlight colour (`--ax1`) on hover. To achieve this, I used the browser’s inspector to identify the logo's class and then targeted it using custom CSS. Here’s the snippet I used: ```css /* ------------------- SITENAME -------------------*/ .site-body-left-column-site-name { color: var(--h1); } .site-body-left-column-site-name { transition: color 0.5s ease; } .site-body-left-column-site-name:hover { color: var(--ax1); } ``` #### Customising the logo To change the size of your site’s logo (or adjust other styling), you can simply target its HTML class in your custom CSS and modify the relevant parameters. In my case, I adjusted the width like this: ```css /* ------------------- LOGO -------------------*/ .site-body-left-column-site-logo img { width: 190px; filter: var(--logo-mode); } .site-body-left-column-site-logo { text-align: left; } .site-header-logo { display: none; } ``` #### Customising the footer The footer, which by default displays “Powered by Obsidian Publish” and links to its website, can also be styled using custom CSS. In my case, I replaced it with a simple ©2025: ```css /* ------------------- SITE FOOTER -------------------*/ .site-footer a { display: none; } .site-footer::after { content: '© 2025'; color: grey; } .site-footer:hover::after { color: var(--ax1); transition: all 0.3s ease; } ``` As a little easter egg, I also made the footer clickable, linking to a hidden page (now you know my secret). This was done using JavaScript: ```js // Make footer a link const footer = document.querySelector(".site-footer"); if (footer) { footer.style.cursor = "pointer"; footer.addEventListener("click", () => { window.location.href = "https://chronicles-in-silence.com/You+found+a+secret+page"; }); } ``` ### Adding custom elements using HTML (& CSS) Many of the visual elements on my Obsidian Publish site are created using custom HTML and styled with CSS. One example is the profile element you see at the top of each of my entries, which looks like this: --- <div class="post-meta"> <div class="post-meta-avatar"></div> <div class="post-meta-text"> <div class="post-meta-author">Stephan</div> <div class="post-meta-date">DD Month YYYY, HH:MM AM</div> </div> </div> --- In Obsidian's editing mode, the corresponding HTML looks like this: ```html <div class="post-meta"> <div class="post-meta-avatar"></div> <div class="post-meta-text"> <div class="post-meta-author">Stephan</div> <div class="post-meta-date">DD Month YYYY, HH:MM AM</div> </div> </div> ``` And the CSS used to style it: ```css /* ------------------- PROFILE ELEMENT -------------------*/ .post-meta { display: flex; align-items: center; gap: 12px; margin: 1em 0; } .post-meta-avatar { width: 48px; height: 48px; border-radius: 50%; background-image: url("https://publish-01.obsidian.md/access/698e3f571f4ed9b907f1a90c79ced34c/Attachements/avatar.webp"); background-size: cover; background-position: center; border: 2px solid var(--bg2); box-shadow: 0 1px 3px rgba(0,0,0,0.1); } .post-meta-text { line-height: 1.2; } .post-meta-author { font-weight: 600; font-size: 15px; } .post-meta-date { font-size: 13px; color: #646464; } ``` Since `publish.css` only affects your **published site**, these custom elements won’t render correctly in **reading mode** inside the Obsidian app. One way to fix that is to load your custom CSS as a theme in Obsidian as well. To do this: 1. Create a folder inside `.obsidian/themes/your-theme-name` (note: `.obsidian` is a hidden folder). 2. Save your `publish.css` as `theme.css` inside that `your-theme-name` folder. 3. Create a `manifest.json` file in the same folder with the following content: ``` { "name": "name", "version": "0.0.0", "minAppVersion": "0.0.0", "author": "@author", "authorUrl": "https://twitter.com/author", "fundingUrl": "https://www.buymeacoffee.com/author" } ``` Then, go to **Settings > Appearance** in Obsidian and select your new theme. This way, you’ll be able to see your HTML-styled elements while working inside Obsidian too. Just note: if you continue making changes to `publish.css`, you’ll need to update your `theme.css` as well to keep both in sync. ## Adding additional functionalities using JavaScript As I mentioned earlier, I’m no coder, and a lot of the JavaScript powering this site is pretty jerry-rigged. That said, one feature I implemented which works flawlessly (and was genuinely important to me) is the **automatic expansion of the current year’s folder** in the file tree. By default, folders on your Obsidian Publish site are collapsed. For a blog like mine, where posts are grouped by year and not instantly visible, this can be a little annoying for readers. So I wrote a small script that ensures the current year (e.g., *2025*) is expanded automatically when the site loads. Here’s the code that makes that happen: ```js function tryExpand2025Folder(attempts = 0) { const folder = [...document.querySelectorAll('.tree-item')] .find(el => el.querySelector('.tree-item-inner')?.textContent.trim() === '2025'); if (folder) { const icon = folder.querySelector('.tree-item-icon.collapse-icon.is-collapsed'); if (icon) { icon.click(); console.log('Expanded 2025 folder on mobile'); } } else if (attempts < 10) { setTimeout(() => tryExpand2025Folder(attempts + 1), 500); } } ``` --- <div class="button-row"> <button id="like-button"> <span class="material-symbols-outlined" id="like-icon">favorite</span> <span id="like-count">0</span> </button> <a href="Write Something" class="bookmark-link internal-link"> <button id="comment"> <span class="material-symbols-outlined" id="comment-icon">chat_bubble</span> </button> </a> </div>