Post

My Blogging Setup

My blogging setup, aka how to create a blog with Obsidian and Chirpy (Jekyll theme)

My Blogging Setup

Though I use Jekyll, this should technically work with any blogging framework. This tutorial assumes that you are familiar with Jekyll, GitHub Pages, etc.

Requirements

Setup

Obsidian Theme

I’ve always been a fan of dark mode color scheme, especially solarized dark. I also prefer to avoid cluttered UI, which is why I use the Minimal Theme Settings plugin.

  1. Open Settings (Command ⌘ + ,) in Obsidian

  2. Go to Community plugins tab
  3. If it isn’t already, turn off Restricted mode to enable community plugins

  4. Click Browse, which is next to Community plugins

  5. Enter Minimal Theme Settings in the searchbar

  6. Click on Minimal Theme Settings, then click Install

  7. Once it’s installed, go to Appearance tab

  8. Next to Themes, select Minimal to apply the theme

  9. Go to Minimal Theme Settings tab

  10. Modify the settings to your liking

    Here are mine, for reference:

    color_scheme.png features.png layout_typography.png

Obsidian Mobile App

I use Obsidian’s iPhone app with iCloud, which I’ll walk through in this section, though Obsidian also offers Obsidian Sync as an alternative. If you don’t have an Apple device, iCloud isn’t applicable.

  1. Once the Obsidian app is downloaded, check your iCloud Drive: There should be an Obsidian folder; if not, make one

  2. Move all your vaults (i.e. directories) to Obsidian folder. E.g. my vault is named Writing, with path of iCloud Drive/Obsidian/Writing/ (which, in my case, points to $HOME/Library/Mobile Documents/iCloud~md~obsidian/Documents/Writing/)

Setup Enveloppe

  1. Launch Obsidian

  2. Open Settings (Command ⌘ + ,)

  3. Go to Community plugins tab

  4. Turn off Restricted mode to enable community plugins

  5. Click Browse, which is next to Community plugins

  6. Enter Enveloppe in the searchbar

  7. Click on Enveloppe, then click Install

  8. Once Enveloppe’s installed, go to its settings (i.e. under Community plugins section in the settings sidebar, click Enveloppe)

  9. Copy my Enveloppe settings

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    
     {
       "github": {
         "branch": "main",
         "automaticallyMergePR": true,
         "dryRun": {
           "enable": false,
           "folderName": "enveloppe"
         },
         "api": {
           "tiersForApi": "Github Free/Pro/Team (default)",
           "hostname": ""
         },
         "workflow": {
           "commitMessage": "[OBSIDIAN] Merge",
           "name": ""
         },
         "verifiedRepo": true
       },
       "upload": {
         "behavior": "fixed",
         "defaultName": "_posts",
         "rootFolder": "",
         "yamlFolderKey": "",
         "frontmatterTitle": {
           "enable": true,
           "key": "filename"
         },
         "replaceTitle": [
           {
             "regex": "/\\s+/",
             "replacement": "-",
             "type": "title"
           }
         ],
         "replacePath": [],
         "autoclean": {
           "includeAttachments": true,
           "enable": false,
           "excluded": []
         },
         "folderNote": {
           "enable": false,
           "rename": "index.md",
           "addTitle": {
             "enable": false,
             "key": "title"
           }
         },
         "metadataExtractorPath": ""
       },
       "conversion": {
         "hardbreak": false,
         "dataview": true,
         "censorText": [],
         "tags": {
           "inline": false,
           "exclude": [],
           "fields": []
         },
         "links": {
           "internal": true,
           "unshared": true,
           "wiki": true,
           "slugify": "strict",
           "unlink": true,
           "relativePath": true,
           "textPrefix": "/"
         }
       },
       "embed": {
         "attachments": true,
         "overrideAttachments": [],
         "keySendFile": [],
         "notes": false,
         "folder": "assets/img/obsidian",
         "convertEmbedToLinks": "keep",
         "charConvert": "->",
         "unHandledObsidianExt": [],
         "sendSimpleLinks": true,
         "forcePush": true,
         "useObsidianFolder": false
       },
       "plugin": {
         "shareKey": "share",
         "excludedFolder": [
           "templates"
         ],
         "copyLink": {
           "enable": false,
           "links": "",
           "removePart": [],
           "addCmd": false,
           "transform": {
             "toUri": true,
             "slugify": "lower",
             "applyRegex": []
           }
         },
         "setFrontmatterKey": "Set"
       }
     }
    
  10. Click Import settings and paste the copied enveloppe.json (from the previous step) where it says Paste configuration here..., then click Save

  11. Under GitHub config, enter your GitHub username, Repository name, and — if your main branch is not named mainMain branch name

  12. Generate a fine-grained personal access token for your GitHub repository in order to give Enveloppe necessary permissions to work by going to your GitHub settings

  13. Scroll down and click Developer settings

  14. Click Personal access tokens, click Fine-grained tokens, then click Generate new token

  15. Enter a descriptive Token name (e.g. Enveloppe (Obsidian)) and Description (e.g. Enveloppe (Obsidian Vault → GitHub Repo))

  16. Choose your GitHub account as Resource owner

  17. Select No expiration for Expiration

  18. Under Repository access, click Only select repositories then click Select repositories and select the GitHub repository for your Jekyll blog (e.g. lynkos/blog)

  19. Click Repository permissions under Permissions

  20. Always choose the minimal permissions necessary, so all options should be set to Access: No access, with the exception of the following:

    PermissionAccessReason
    ContentsRead and writeCreate branch
    MetadataRead-onlyMandatory
    Pull requestsRead and writeCreate and merge pull requests
    WorkflowsRead and writeCreate/update file
  21. Click Generate token

  22. Copy the generated GitHub personal access token; it should start with github_ followed by a long, random string of alphanumeric characters and underscores

  23. Back in Enveloppe settings, paste it in the GitHub token area

Setup Comments

  1. If you haven’t already, make your blog’s GitHub repository public

  2. Enable your repository’s Discussions feature

  3. Install the Giscus app on GitHub

  4. Go to Giscus and fill out the form

  5. Copy the auto-generated <script> under Enable giscus

    Example code with my configuration:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    
     <script src="https://giscus.app/client.js"
         data-repo="<GITHUB_USERNAME>/<REPO>"
         data-repo-id="<REPO_ID>"
         data-category="Announcements"
         data-category-id="<CATEGORY_ID>"
         data-mapping="pathname"
         data-strict="0"
         data-reactions-enabled="1"
         data-emit-metadata="0"
         data-input-position="top"
         data-theme="preferred_color_scheme"
         data-lang="en"
         data-loading="lazy"
         crossorigin="anonymous"
         async>
     </script>
    
  6. Add the <script> tag

    • If you’re NOT using jekyll-theme-chirpy, to your website’s template where you want the comments to appear (Note: If an element with the giscus class exists, the comments will be placed there instead)
    • If you ARE using the Jekyll theme Chirpy, continue to the next section

OPTIONAL: ADD COMMENTS FEATURE TO jekyll-theme-chirpy

  1. Go to _config.yml in your repository

  2. Find the comments section

  3. Set provider to giscus

  4. Fill in all options under giscus with the values from the <script> you copied in Step #5

    Example code with my configuration for comments section:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    
    comments:
      # Global switch for the post-comment system. Keeping it empty means disabled.
      provider: giscus # [disqus | utterances | giscus]
      # The provider options are as follows:
      disqus:
        shortname: # fill with the Disqus shortname. › https://help.disqus.com/en/articles/1717111-what-s-a-shortname
      # utterances settings › https://utteranc.es/
      utterances:
        repo: # <gh-username>/<repo>
        issue_term: # < url | pathname | title | ...>
      # Giscus options › https://giscus.app
      giscus:
        repo: <GITHUB_USERNAME>/<REPO>
        repo_id: <REPO_ID>
        category: "Announcements"
        category_id: <CATEGORY_ID>
        mapping: # optional, default to 'pathname'
        strict: # optional, default to '0'
        input_position: "top" # optional, default to 'bottom'
        lang: # optional, default to the value of `site.lang`
        loading: lazy # comments loading will be deferred till user scrolls near comments container
        reactions_enabled: # optional, default to the value of `1`
        theme: preferred_color_scheme # comments theme
    

Setup Image Proxy

A custom Cloudflare Worker hotlinks images from sites that may restrict it; this way I can embed images from Twitter/X. Custom Ruby plugin _plugins/gallery.rb automatically prepends Twitter/X URLs within a gallery with the value of worker_base_url. Additional sites will be added as needed. This proxy currently only supports Twitter/X.

  1. Sign up and/or login to Cloudflare

  2. Go to your dashboard

  3. In the left pane, click Compute (Workers), then Workers & Pages

  4. Click the blue Create application button in the upper-right corner

  5. In the Workers tab, click the blue Get Started button to the right of Start with Hello World!

  6. Name the worker img-proxy

  7. Click Deploy

  8. You should be redirected to a page that says Success! Your project is deployed to Region: …

  9. Click the Edit Code button; you can also access this page later by going to Compute (Workers) > Workers & Pages, clicking the worker (i.e. img-proxy), then clicking the small icon </> in the upper-right corner

  10. This should open the Cloudflare Workers IDE; replace the default code in worker.js with the following code:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    
    export default {
      /**
       * @param  request
       */
      async fetch(request) {
        const url = new URL(request.url);
        const target = url.searchParams.get("url"); // i.e. ?url=https://pbs.twimg.com/media/...
    
        if (!target) {
          return new Response("Missing ?url= param", { status: 400 });
        }
    
        try {
          const resp = await fetch(target, {
            headers: { "User-Agent": "Mozilla/5.0" }
          });
    
          const headers = new Headers(resp.headers);
          headers.set("Access-Control-Allow-Origin", "*");
    
          return new Response(await resp.arrayBuffer(), {
            status: resp.status,
            headers
          });
        } catch (err) {
          return new Response("Fetch error: " + err.message, { status: 502 });
        }
      }
    };
    

    Test the worker in the Preview pane by adding ?url= and the link to an image on Twitter (e.g. https://pbs.twimg.com/media/GzPhoaKWoAA16uA?format=jpg&name=medium) following AFTER your worker’s URL (i.e. https://img-proxy.<YOUR_DOMAIN_NAME>.workers.dev/) in the input field

    So, in this example, the full URL is: https://img-proxy.<YOUR_DOMAIN_NAME>.workers.dev/?url=https://pbs.twimg.com/media/GzPhoaKWoAA16uA?format=jpg&name=medium

    Click the Reload button (circular arrow icon) to the right of the input field to test it; if successful, you should see the image in the Preview pane

  11. Click Deploy in the upper-right corner

  12. You can now use this worker as an image proxy by using the following URL format, where <YOUR_DOMAIN_NAME> is your Cloudflare domain (e.g. example.com) and <IMAGE_URL> is the full URL of the image you want to hotlink (e.g. https://pbs.twimg.com/media/GzPhoaKWoAA16uA?format=jpg&name=medium):

    1
    
    https://img-proxy.<YOUR_DOMAIN_NAME>.workers.dev/?url=<IMAGE_URL>
    

OPTIONAL: USE CUSTOM DOMAIN (e.g. img-proxy.<YOUR_ROOT_DOMAIN>)

  1. In the left pane, click DNS, then Records

  2. Click the blue + Add record button, then add a new record with the following details:
    • Type: CNAME
    • Name: img-proxy (or whatever subdomain you want to use)
    • IPv4 address: workers.dev
    • Proxy status: Proxied aka Enabled (orange cloud icon)
    • TTL: Auto
    • Comment: Map img-proxy worker (at img-proxy.<YOUR_DOMAIN_NAME>.workers.dev) to img-proxy.<YOUR_ROOT_DOMAIN>
  3. Click Save

  4. Click Workers Routes in the left pane, then click the blue Add route button in the HTTP Routes section

  5. In the Route field, enter img-proxy.<YOUR_ROOT_DOMAIN>/*

  6. Under Worker, select img-proxy worker (or whatever you named it) from the dropdown

  7. Click Save

  8. You can now use the custom domain for your image proxy at https://img-proxy.<YOUR_ROOT_DOMAIN>/?url=<IMAGE_URL> (e.g. https://img-proxy.example.com/?url=https://pbs.twimg.com/media/GzPhoaKWoAA16uA?format=jpg&name=medium)

Create Hotkeys

  1. Launch Obsidian

  2. Save the template in Default Template to your vault (e.g. templates/default.txt)

  3. Open Settings (Command ⌘ + ,)

  4. Go to Hotkeys tab

  5. Scroll to Templates: Insert template

  6. Click the + icon (says Customize this command when you hover over it)

  7. Press Command ⌘ + Shift ⇧ + T, or your preferred hotkey

  8. Scroll to Enveloppe: Upload single current active note

  9. Click the + icon (says Customize this command when you hover over it)

  10. Press Command ⌘ + Shift ⇧ + P, or your preferred hotkey

Now we can automatically apply the template to any new post and auto-publish your Obsidian post to your blog with those hotkeys!

Make sure share: true is in the frontmatter, otherwise it won’t post

Writing Posts

Default Template

You’ll need to add the following to the top of every Markdown post you make

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
---
share: false
title: {{title}}
date: {{date:YYYY-MM-DD}} {{time:HH:mm:ss ZZ}}
filename: "{{date:YYYY-MM-DD}}-{{title}}"
description: Post summary.
math: false
pin: false
toc: true
comments: true
categories: [top_category, sub_category]
tags: [tag]
image:
  path: /relative/path/to/image
  lqip: minified_image_encoded_in_base64
  alt: Image caption
---
KeyDescription
shareWhen true, it will push to Github
titlePost title
dateDate and time created; format yyyy-mm-dd hh:mm:ss utc_offset
filenameWhere your file will be saved in Github; format yyyy-mm-dd-title-here
descriptionOptional post description; will appear below post title and in previews
mathWhen true, enables MathJax for LaTeX processing
pinWhen true, it will pin this post on website
tocWhen false, the table of contents is hidden
commentsWhen false, the comments section is hidden
categoriesOptional list of categories; 1st element is main category, remaining elements are subcategories
tagsOptional list of tags
pathOptional path to preview image
lqipOptional preview image’s base64-encoded LQIP
altOptional caption and alt text for preview image (can be left blank)

Add Preview Image

To add a preview image to a post, make sure the following is in your Markdown file’s front matter

1
2
3
4
image:
  path: /path/to/image.png
  lqip: base64-encoded-lqip
  alt: Optional image caption and alt text

To generate a base64-encoded LQIP for the lqip field:

  1. Visit lqip generator

  2. Upload your preview image

  3. Customize the options as needed; here are my recommendations:
    • Placeholder Size: Small
    • Quality: 60
    • Blur Amount: 5px
  4. Click Generate LQIP

  5. Right-click the generated image that appears under LQIP (Scaled & Blurred)

  6. Depending on your browser, copy the image link directly (i.e. click Copy Image Link) OR open the image in a new tab (i.e. Open Image in New Tab) and copy the URL in the address bar

    Image link MUST be a base64 string that starts with data:content/type;base64

  7. Paste the base64 string (aka image link) in the lqip field of the front matter (i.e. use it to replace base64-encoded-lqip)

    To verify that the base64 string works, visit Base64 Image Viewer and paste the base64 string in the input field below Base64 Image String

Appendix

Sync Fork with Upstream

To keep fork up-to-date with original repository (i.e. Chirpy)

  1. Link the upstream (i.e. original) repository to fork

    1
    
     git remote add upstream https://github.com/cotes2020/jekyll-theme-chirpy.git
    

    Use this command if you’ve already linked the upstream repository and want to re-link it

    1
    
    git remote set-url upstream https://github.com/cotes2020/jekyll-theme-chirpy.git
    
  2. Confirm the remote URL with either command
    • Command #1
      1
      
      git remote show
      
    • Example Output #1
      1
      2
      
      origin
      upstream
      
    • Command #2
      1
      
      git remote -v
      
    • Example Output #2
      1
      2
      3
      4
      
      origin  https://github.com/lynkos/blog.git (fetch)
      origin  https://github.com/lynkos/blog.git (push)
      upstream        https://github.com/cotes2020/jekyll-theme-chirpy.git (fetch)
      upstream        https://github.com/cotes2020/jekyll-theme-chirpy.git (push)
      
  3. Fetch latest changes from upstream repository

    1
    
     git fetch upstream master
    
  4. Switch to master branch (so it’s recognized)

    1
    
     git checkout master
    
  5. Switch to the branch you want to sync

    1
    
     git checkout main
    
  6. Merge changes from upstream into local branch

    1
    
     git merge upstream/main
    
  7. Push changes to your fork

    1
    
     git push origin main
    

Contribute Upstream

Continue reading if you want to create a pull request in jekyll-theme-chirpy with only a subset of your commits. This is useful if you want to add a feature to upstream without committing all your changes.

  1. If you haven’t already, complete the steps in Sync Fork with Upstream section

  2. Create a new branch, e.g. BRANCH_NAME

    1
    
     git checkout -b BRANCH_NAME upstream/master
    
  3. Cherry pick the commit(s) you want to include in the PR

    1
    
     git cherry-pick COMMIT_HASH
    
  4. Push your branch

    1
    
     git push origin BRANCH_NAME
    
  5. If successful, the terminal should output something similar to this:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    
    Enumerating objects: 111, done.
    Counting objects: 100% (83/83), done.
    Delta compression using up to 16 threads
    Compressing objects: 100% (50/50), done.
    Writing objects: 100% (51/51), 8.50 KiB | 1.70 MiB/s, done.
    Total 51 (delta 36), reused 0 (delta 0), pack-reused 0 (from 0)
    remote: Resolving deltas: 100% (36/36), completed with 26 local objects.
    remote: 
    remote: Create a pull request for 'BRANCH_NAME' on GitHub by visiting:
    remote:      https://github.com/GITHUB_USERNAME/REPOSITORY_NAME/pull/new/BRANCH_NAME
    remote: 
    To https://github.com/GITHUB_USERNAME/REPOSITORY_NAME.git
     * [new branch]      BRANCH_NAME -> BRANCH_NAME
    
  6. Go to the originally forked repository, i.e. jekyll-theme-chirpy

  7. Click the New pull request button

  8. Complete the pull request template accordingly

  9. Click the Create pull request button

Credits

This post is licensed under CC BY 4.0 by the author.