Mkdocs Obsidian

Mkdocs Obsidian is an association between a python script and a Material mkdocs template to get a personal wiki site based on your Obsidian Vault.

Showcase
My blog (fr)

Screenshot




TLDR

  1. Install / update with pip install obs2mk --upgrade
  2. Template the blog, clone it and configure the blog.
  3. Configure the script (first run)
  4. Add share: true in Obsidian’s note frontmatter
  5. Customize the category key in Obsidian’s note frontmatter
  6. Run the script obs2mk

Prerequisites

You need :

Quick installation tutorial

  1. Click on use this template[^7]
  2. Use the name of your choice.
  3. Click on code → SSH ; Copy the link
  4. Run (in terminal):
git clone [[PASTE THE LINK HERE]] publish_blog
pip install obs2mk --upgrade

Creating the blog

Customization

In your new publish_blog folder, you will spot a mkdocs.yml. This file allows you to customize your blog! The most important to edit :

  1. site_name
  2. site_description
  3. site_url (critical) : By default, it’s https://github_username.io/repo_name[^8]

To edit the logo and the favicon, first put the chosen file in assets/logo, and change logo and favicon :

  1. logo: assets/logo/logo_name.png
  2. favicon: assets/logo/favicon.png

You can customize :

  • Font
  • Color scheme, palette, icons
  • Language

Check the documentation to get more information

You don’t need to touch anything in features ; markdown_extensions…

Local testing (optional)

To run locally the blog, you need to install the requirements and run mkdocs serve.

cd publish_blog
pip install -r requirements.txt
mkdocs serve

The blog will be published through GitHub Page using the gh-page branch. Everything is already configured by the template for that.

Obs2mk : Obsidian to Mkdocs

The script’s goal is to move an authorized file (or multiple authorized file) from your Obsidian’s vault to your blog’s repository. It will :

Furthermore, it will also carry :

File’s front matter

The script relies on the front matter** of the notes you want to publish.

  1. share: true allow publishing the file[^2]
  2. category to choose where the file will be after conversion ; allowing categorization for the blog.[^6]
    • category: false will hide the file from navigation.
    • category: hidden will do the same.
    • category: folder1/folder2/ will move the file in folder2, under folder1
    • category: folder1/folder2/filename will rename the file index and allow support of section’s index page
  3. update: false prevent to update the file after the first publication
  4. description : Add a description to the file (for meta-tag sharing)[^3]
  5. title : Change the title in the navigation.
  6. image : Add an image for meta-tags sharing.[^3] It needs to be the name of the file, as image.png.

Usage

The script can be use :

The supported system are :

Configuration

At the first run, you will be asked to configure some key and specific path.

  1. Vault : Use the file dialog to choose your vault folder.
  2. Publish repository folder : As vault path, use the file dialog.
  3. share : You can change the share key. By default, it’s share
  4. Index key: Support for citation of pagination index pages. By default, it uses (i)
  5. Default blog folder: By default, the notes will be in docs/notes but you can change that, or use / for root.

The file will be in site-packages/mkdocs_obsidian/.mkdocs_obsidian (unless for Pyto : the .env will be directly in site_package/.mkdocs_obsidian)

Terminal

Global options :

  • --git : No commit and push to git ;
  • --mobile : Use mobile shortcuts instead of --git
  • --meta : Update frontmatter of source files
  • --keep : Don’t delete files in blog folder
  • --shell : Remove Rich printing

Commands and specific options :

  • config : (it will ignore --use configuration_name)
    • --new configuration_name : Create a specific configuration for some files
  • all : Share all vault
    • --force : Force updating (ignore the difference between the source and blog file)
    • --vault : Share all vault file, ignoring the share state.
  • file [file*] : Share only one file
usage: __main__.py [-h] [--mobile | --git] [--meta] [--keep] [--use configuration_name] {config,all,file} ...

positional arguments:
  {config,all,file}
    config              Configure the script : Add or edit your vault and blog absolute path, change some keys.
    all                 Publish multiple files
    file                Publish only one file

options:
  -h, --help            show this help message and exit
  --mobile, --shortcuts
                        Use mobile shortcuts, without push
  --git, --g, --G       No commit and no push to git
  --meta, --m, --M      Update the frontmatter of the source file, adding the note blog's link
  --keep, --k, --K      Keep deleted file from vault and removed shared file
  --use configuration_name, --config configuration_name
                        Use a different config from default

The commands order is :
obs2mk (global_options) [all|config|file FILEPATH] (specific_options)
Where :

  • Global and specific options are optional
  • all, config and file[^9] are required
    You can use the command without argument with obs2mk to share every share: true file in your vault.

Share one file : obs2mk file FILEPATH

It will :

  • Update the share state in original file
  • Convert one file, regardless of what is the share state.

Share all file : obs2mk all or obs2mk

You can share multiple documents at once with scanning your Vault, looking for the share: true. It will convert automatically these files.
Only file with modification since the last sharing will be updated.

You can :

  • Share entirely your vault (that’s ignore the share state) with : obs2mk all --vault
  • Ignore the difference between the source file and the blog’s file with : obs2mk all --force
    Also, you can combine the two options.

Configuration

You can use and create multiple configuration files. This allows to have multiple site based on one vault, or different vault accross one site…

  1. To create a new configuration file : obs2mk config --new configuration_name
  2. To use a configuration use : --use configuration_name
    For example : obs2mk --use configuration_name

Obsidian Shell Configuration

You could create :

  1. A command to publish everything : alias Publish with obs2mk --obsidian
  2. A command to publish one specific file : alias Publish {{title}} with obs2mk --obsidian file {{file_path:absolute}}
  3. Event shortcuts for file menu event : Publish {{event_file_name}}: obs2mk --obsidian file "{{event_file_path:absolute}}
  4. Folder Note event (folder menu event): Publish {{event_folder_name}}: obs2mk --obsidian file "{{event_folder_path:relative}}\{{event_folder_name}}.md"

You can create a button with :

IOS

The script support IOS using :

The option mobile will never push. You need to use Working Copy to push the converted file.

You can :

  1. Share the entire vault : obs2mk --mobile all --vault
  2. Share a specific file, using its name : obs2mk --mobile file "filename".[^5] This option can be used especially with Shortcuts

Customization

  • You can prevent the script to share file in specific folder, with editing folder list in exclude.yml
  • You can prevent the script to delete some file with editing file list in the same file.
  • You can, also, create some CSS customization with hashtag, with editing docs/assets/css/custom_attributes.css. See Custom Attribute for some example.

Blog : Customization

Custom attribute example

You can create Inline Markdown Attribute using hashtags in Obsidian. For example, to align some text to right :

  1. Add
#right {
 display: inline-block;
 width: 100%;
 text-align: right;
 font-weight: normal;
}
  1. Add #right on the last part of a line :
Lorem ipsum dolor sit amet, consectetur adipiscing elit. In mollis, libero porttitor gravida accumsan, justo metus pulvinar nulla, vitae dictum odio ligula non nisl. Vivamus id venenatis nulla. Nullam sed euismod ligula. Pellentesque tempor elit felis, lobortis vulputate risus gravida et. Curabitur auctor sed libero nec consectetur. Nam placerat rhoncus risus, euismod sagittis eros bibendum ac. Maecenas tellus libero, porttitor ac purus sit amet, viverra suscipit dolor. Proin id nisl velit. Ut at tincidunt libero, ac pharetra mi. Integer non luctus nisi. #right

It will appear as:

Folder note

You can create a folder note if you use a category front matter key that have the last folder with the same name as the file. For example :
category: folder1/folder2/filename. The file filename will be renamed index and the folder will be named filename.

To support the citation and link to these page, you need to use an index key (cf configuration).

Some examples of citation and their transformation :

In Obsidian In Publish
[[Real File\|(i) Alias]] [[index\|Alias]]
[[Real File\|(i)]] [[index\|Real File]]
[(i) Alias](Real file) [Alias](index)
[(i)](real file) [real file](index)

Obsidian

Some useful plugin to support the script :

Metacopy

Using metacopy you can quickly copy a link to a shared page, without using this option (so, yes, the script does not edit your source file !).
To create a link, you need to configure :

  1. category in key
  2. Add your set_url in base link
  3. Add category in key link

Also, you can remove the metacopy from your file menu using a key, so you can activate metacopy only for share: true. Metacopy also support the folder note.

The final configuration of metacopy for mkdocs_obsidian will be :

So, in the end, a menu will appear on file with share: true and a category configured. This menu is on the left click and the file-menu. You can quickly copy a link from there, like a Google or notion sharing link!

Here is a demo :

click to get a video !

Front matter template

title:  
share: 
description:  
category:

Limitation

  • The plugin rely a lot on filename, without regarding the folder. Please use unique naming and use the title key if you need to.
  • The plugin will not delete the index files (cf Folder Note)
  • The script can be long on big vault.
  • The script will not manually move the file if you change a category : you need to delete it manually to prevent duplicate.
  • :warning:You must use shortlinks in Obsidian configuration.

If you have more question, don’t forget to read the Q&A !

[^1]: No support for nested admonition
[^2]: This key can be configured
[^3]: Meta tags are snippets of text that describe a page’s content; the meta tags don’t appear on the page itself, but only in the page’s source code. Meta tags are essentially little content descriptors that help tell search engines what a web page is about. Source
[^4]: Using Pyto you need to add the writing authorization for your vault and blog repository. You can access it in parameters > Runtime.
[^5]: Beware, if it exists a file with the same name, it will take the first found.
[^6]: You can customize the folder with Awesome Pages
[^7]: You must be connected to copy the template ! You can test locally through clone > https : git clone https://github.com/Mara-Li/mkdocs_obsidian_template.git or with downloading the ZIP
[^8]: You can found the link in Repository settings > Pages.
[^9]: For file you need to add the file path of the file you want to share : obs2mk (global_option) file "filepath" (specific_options)

5 Likes

Thanks for writing in details like this. It helps and gives me the motivation to try your setup.

Please teach me if I didnt understand correctly the 2 things as follows.

  1. After having installed mkdocs-material, in order to publish notes I have now 2 options:

    • manually copy notes that I want to publish from my Obsidian vault folder to my folder /docs located in my repo folder
    • or use your script mkdocs-obsidian to do the task programmatically.
  2. In order to make mkdocs-obsidian work for selective publishing, I need to specify an attribute share: true in the frontmatter of every notes that I want to publish.

I think you entirely understand!
The share: true key is when you want to share multiple file. But, if you want to just publish one file, you need to use obs2mk --f "Path/to/the/file"

Thanks for sharing this info this is useful keep it up.

1 Like

I was just scrolling and found some good information thanks for sharing this amazing post keep posting.

1 Like

Also, as I create MetaCopy to quickly copy a link from this workflow, here is a little tutorial to use it as I do.

Here is a demo

With that, you avoid to edit your source file and you can share a link as notion !

Hello
I added new options, including sharing the entire vault and mobile.

Mobile is intended to be used with IOS shortcuts.

usage: obs2mk [-h] [--git | --mobile] [--meta] [--keep] [--config]
                   [--force] [--filepath FILEPATH | --ignore]

Create file in docs and relative folder, move image in assets, convert
admonition code_blocks, add links and push.

optional arguments:
  -h, --help            show this help message and exit
  --git, --g, --G       No commit and no push to git
  --mobile, --shortcuts, --s, --S
                        Use mobile shortcuts fonction without push.
  --meta, --m, --M      Update the frontmatter with link
  --keep, --k, --K      Keep deleted file from vault and removed shared file
  --config, --c, --C    Edit the config file
  --force, --d, --D     Force conversion - only work if path not specified
  --filepath FILEPATH, --f FILEPATH
                        Filepath of the file you want to convert
  --ignore, --ignore-share, --no-share, --i, --vault
                        Convert the entire vault without relying on share
                        state.

Share the entire vault

Using the command --ignore will ignore the share state : you can share your entire vault using that, whatever the state is. By default, it will not overwrite file already exist (and not different), so the --force option can also be used.

usage: obs2mk [-h] [--git | --mobile] [--meta] [--keep] [--config] [--force] [--ignore]

Mobile option

The mobile option is similar to the git option but with some nuance. When used to publish a single file, you can use only the file name, without the path.

:warning: Be careful though, in case you have several files with the same name, the script will take the first file found.

This option can be used, especially with the “Shortcuts” application on IOS, to share a file directly from the share sheet.

One file usage : obs2mk --mobile --f "filename"
All file usage : obs2mk --mobile

Mobile supports all previous option, including --ignore.

1 Like

As I was bored, I updated the script to use Python Rich. So, now you have more information when you share all-share vault !
script_demo

1 Like

Hello everyone!
The template now supports tooltip. It’s a fork, waiting for a pull request.

To install it, use pip install git+git://github.com/Mara-Li/mkdocs-tooltipster-links-plugin

I adjust the CSS to be cool with the theme.

01-18-2022_22-53

If I success to contact the original author of the plugin (who is an Obsidian User !) I think I will use it to, also, add real embed citation in the blog.
After that, I think the blog can be considered as complete.

One day, maybe, it will be a mkdocs plugin and everything will be converted during the build :’).

1 Like

Okay !
I create a new mkdocs plugin to embed file in mkdocs !

I updated the template + the script to add the support of embed file like in obsidian !

2 Likes

Little question : Do you prefer to have the choice to use a menu, with a little application ? A simple menu to just insert your file, choice the command…
I prefer to use command line (as Obsidian Shell commands change everything for me), but maybe some users prefer to use an app?

Off topic question. How to configure the terminal as yours? Ie. separated color for each folder level

I use Oh my Posh.

1 Like

Hello everyone ! I updated the readme of this topic with the lasts changes :slight_smile:

1 Like

Thank you for the great work, especially considering the new price of obsidian publish. I have a question: Is there a way to add graph view via obsidian Mkdocs?

Unfortunately not. I already looking for a way to get graph and I don’t found any idea.

There is some limitation I found :

  • First, where I put it in the css? As I use a template I need to do a big edit in the css and I hate that.
  • I need to get a responsive graph and I don’t know how I can do that.

Also, construct an image using graphviz or juggle will broke the script for mobile and it will be not very good (because not responsible and without note link)

So, for the moment, there is no graph view.

Hello !
I updated the script, and reworked all commands.

Global options :

  • --git : No commit and push to git ;
  • --mobile : Use mobile shortcuts instead of --git
  • --meta : Update frontmatter of source files
  • --keep : Don’t delete files in blog folder
  • --shell : Remove Rich printing

Commands and specific options :

  • config : (it will ignore --use configuration_name)
    • --new configuration_name : Create a specific configuration for some files
  • all : Share all vault
    • --force : Force updating (ignore the difference between the source and blog file)
    • --vault : Share all vault file, ignoring the share state.
  • file [file*] : Share only one file

Secondly, you can now create multiple configuration. For example, you can push two different vault in a different site, or the same vault on a different site. Moreover, with different sharing key, you can push different file to different blog.

  1. To create a new configuration file : obs2mk config --new configuration_name
  2. To use a configuration use : --use configuration_name For example : obs2mk --use configuration_name

Hello ! New update.
Now the script will always pull the repo before anything.
The --G options is active also on that.

In case of pull error, the script will warn you but continue to work !

Hello !
Shiny new things : The script support the new callout / Admonition Microsoft’s Syntax.
It also supports custom callout.

The script support custom admonition. For that, you first need to edit custom_attributes with adding the support, as follow in Admonition’s docs.
For example, to add a dictionnary admonition:

:root {
    --md-admonition-icon--dictionnary: url('data:image/svg+xml;charset=utf-8, <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M18 22a2 2 0 0 0 2-2V4a2 2 0 0 0-2-2h-6v7L9.5 7.5 7 9V2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12z"/></svg>')
}
.md-typeset .admonition.dictionnary,
.md-typeset details.dictionnary {
  border-color: rgb(43, 155, 70);
}
.md-typeset .dictionnary > .admonition-title,
.md-typeset .dictionnary > .summary {
  background-color: rgba(43, 155, 70, 0.1);
  border-color: rgb(43, 155, 70);
}
.md-typeset .dictionnary > .admonition-title::before,
.md-typeset .dictionnary > summary::before {
  background-color: rgb(43, 155, 70);
  -webkit-mask-image: var(--md-admonition-icon--dictionnary);
          mask-image: var(--md-admonition-icon--dictionnary);

It will give you :

The dictionnary will be recognized, and converted!