Using Obsidian as a CMS

Thu Dec 07 2023

Scripting

I need to write a script that will:

Copy all all notes tagged Public from my Obsidian vault into the blog directory in antipattern-obsidian

Copy the files from Vault to Astro project

cp is the command for copying files/directories in unix. It can be used with flags and [[Regular Expressions]] to perform complex copying actions.

Example: cp -u *.txt newdir The above example is all that is needed to:

I am going to combine the cp command to copy the output from my grep search into my blog directory inside my Astro project.

Note: when writing scripts, remember to give them execution permissions with chmod +x file_name

Make sure we only publish public notes

In order to make sure I’m only publishing notes that I’ve tagged as Public, I need to a regex to use with the grep command.

"- Public$"

This pattern will work perfectly for parsing through my Obsidian frontmatter.

Putting it all together

This post from StackOverflow was the perfect template for what I’m trying to do:

find . -name \*.pdf -exec cp --parents {} /new_path/ \;

With some small tweaks to the provided answer, Im able to copy all the Public tagged files from my Obsidian vault into my Astro blog directory

find . -type f -exec grep -le "- Public$" {} \; -exec cp {} $astro_posts_path \;

Building the Astro site

Thanks to [[Using Markdown with Astro|Astro’s extensive built-in markdown capabilities]], it’s the perfect framework to use for publishing content from Obsidian.

Configuring Astro’s markdown interpreter

This ended up being an absolute rabbit-hole to figure out. No example that I found online showed how to pass in config overrides to Astro’s remark plugin. I ended up using the remark-wiki-link to add support for Obsidian’s markdown format in my astro project.

astro.config.mjs

import { defineConfig } from 'astro/config';

export default defineConfig({
  markdown: {
    remarkPlugins: [
      ['remark-wiki-link', 
      {
        hrefTemplate: (permalink) => `${permalink}`, 
        pageResolver: (name) => [name.replace(/ /g, '-').toLowerCase()],
        aliasDivider: '|'
      }],
    ]
  }
});

The default behavior for remark-wiki-link didn’t work out of the box with the way my project was structured, so I needed to find a way to pass in config overrides.

Defining a blog content collection

Luckily, blogging with Astro is a common use case and using [[Astro Content collections |content collections]] to type-check my blog post markdown files ended up being very straight-forward. All I had to do was:

// 1. Import utilities from `astro:content`
import { defineCollection, z } from 'astro:content';
// 2. Define collection
const blogCollection = defineCollection({
  type: 'content',
  schema: z.object({
    title: z.string(),
    tags: z.array(z.string()),
  }),
});

export const collections = {
  'blog': blogCollection,
};

https://www.youtube.com/watch?v=v79VRrfVau8 https://pagefind.app/

  1. Install the pagefind dependency npm i -D pagefind

  2. Next, we need to add these tags to the <head> of our site:

<link href="/pagefind/pagefind-ui.css" rel="stylesheet">
<script src="/pagefind/pagefind-ui.js" is:inline></script>

Note: /pagefind/pagefind-ui.css and /pagefind/pagefind-ui.css will not exist when you first add these tags. They are generated after pagefind successfully indexes your site.>

  1. Define where you want your search bar to appear index.astro
<div id="search"></div>
<script>
	window.addEventListener('DOMContentLoaded', (event) => {
		new PagefindUI({ element: "#search", showSubResults: true });
	});
</script>

Note: typescript will show an error saying that it cannot find PagefindUI. This error can be ignored with a comment // @ts-ignore as the PagefindUI module will be defined once the head of our site is build.

  1. Update build script to also index your site for pagefind to search:
"build": "astro build && pagefind --site dist && cp -r dist/pagefind public/"

Adding the copy command at the end allows you to use pagefind when in dev mode. Otherwise it would only be accessible when running an astro build from your dist folder

In order to use Astro’s built-in ViewTransition API with pagefind, I needed to instantiate the PageFindUI element at astro:page-load lifecycle event.

astro:page-load documentation

Use Github as a CDN with Statically

https://statically.io/