Maintaining websites with Bear App and Quarto
The most important change I made to my productivity processes last year was to create a new process so I could edit this website using the Bear App.
I use the static website generator Quarto to generate this website. Of course there are other static website generators available, such as Hugo (which is very fast), and each has its pros and cons. I use Quarto because one of my main interests is information and data visualization, and Quarto is specifically designed for this. So I can write essays that include diagrams, animations and charts, and they are automatically handled by Quarto.
A standard tool to maintain a Quarto website is the programmer’s editor VS Code. I do like VS Code and use it regularly. But for writing? Ugh. It’s for programming, not for writing. I’m not sure why — perhaps it’s because programming principally requires a focused mindset rather than a diffuse one — but I just really dislike writing essays in VS Code. VS Code may work for writing for guru programmers — people who code every day and for whom programming is similar to speaking, but for me — for whom programming is definitely a system 2 task, VS code puts me in the wrong mindset. Whilst VS Code is a great code editor, it is not nice to use to write essays like this one. I wanted something that was both great for writing essays, and could also do technical stuff like incorporate bits of code, YAML front-matter, markdown, etcetera. I have tried many apps in the past for writing and keeping notes, and Bear App is by far my favorite1. It is also very markdown friendly, and has a great tagging system. Converting this website so that I can edit it in Bear had a huge positive effect on my productivity, and makes it a pleasure to write and publish new content. I don’t think I’ve ever been as productive as I am now.
1 You can read about other methods I have tried for writing and keeping notes (such as Obsidian, Notion, Craft, etc) here: My Personal Knowledge Management system
I am very pleased with some of the features my new system has. Here are some highlights:
- Bear is so nice to write in! It everything looks lovely and crisp.
- I can maintain multiple websites with a single instance of Bear.
- I can build the website by running a single script, and publish it with a second script.
- By adding
render: true
to the front-matter of a document, only that document will be processed, which is very quick. - I can make full use of many of the nice features in Bear, such as colored highlights, and they will appear on my web pages.
- I can also do fancy formatting with minimal effort using Quarto syntax (see details below).
- I can define things like a short-path for the note, a description, poster image, as well as add bespoke functionality, using simple front-matter at the top of notes.
- The system automatically creates thumbnail images for listings pages.
- I can use Wikilinks2 in Bear and they are maintained to other pages.
- I can use Bear tags, which are converted automatically to Quarto categories — this creates the button links you can see at the top of this page.
2 Wikilinks are a simple way to make internal links. You write two square brackets and start typing a word from a page title and Bear lists all the matching pages. You then select the one you want and the link is made.
I haven’t even started to fully exploit all the possibilities of this new set-up. If you want to try setting up something like this yourself, more details follow.
Details
I had used Bear App before to experiment keeping a website of notes, just by using the export HTML option. If you just want a simple clean website then its a great option — very easy to do and it looks great. You can read about my experiments doing that here: Creating a website with Bear app
My process uses Bear App and Quarto, but there are other combinations that may be more appropriate for other people. For example, Obsidian and Hugo make a great combination. Bear and Hugo would also work well. Hugo is much faster than Quarto when generating the pages. I use Quarto because it has features related to data visualization. If you don’t need those then Hugo may be a better option for generating the site as it’s fast.
Bear has a lovely method of tagging — tags can be nested in a way that is similar to a folder structure, and when you export the Markdown the exported files conform to that structure. This means that you can have your website reflect the structure of your Bear App setup (or vice-versa, depending on how you want to think about it.)

This is what my website setup looks like in my Bear App
The Markdown export in Bear is very good, but there were various changes that I want to make so that it renders with all the functionality I want in Quarto.
Bear markdown processing
Following is the process I use to modify the markdown output to qmd files. I created the scripts using OpenAI GTP-4o. An example prompt is given at the end of this document. I created multiple scripts because I have found that GTP-4o is great at writing short scripts that do only one or a small number of things, it can often get them right first time if the prompt is good. Whoever, if you try to write longer scripts that do multiple things, it is more likely to have problems, and when it starts to have problems it is often best to just start again. So using lots of small scripts is efficient. It also makes it easy to remove steps from the process — I just remove that script from the list in the main master-script.
Keep the processing process on your local drive, not on the iCloud Drive. This is because if you create, modify and delete a lot of files very rapidly with Python, the iCloud system can get out of sync., and permanently screw your iCloud system up. I speak from bitter experience.
This is the directory structure for the scripts:
/input/quarto_template/
The base Quarto site
/input/raw_markdown/
The Bear export
/processing/processed_markdown/
The Bear Markdown after processing
/processing/quarto_combined/
The processed Markdown combined with the base Quarto site
/output/
The output of the Quarto render
Scripts
I have a simple master script that accepts the website name and then calls each of these scripts in turn.
There is no reason why all these scripts need to be in Python. Quite a few could be replaced with one-line shell commands.
1 Make Raw Markdown Dir
Renames the folder exported by Bear to raw_markdown
in the input
directory.
2 Tidy Up Previous Run
Deletes the contents of the processing
directory.
3 Copy Source To Dest
Copies files from the input/raw_markdown
directory to the processing/processed_markdown
directory
4 Rename Files And Folders
Loops through all the .md
files in the processing/processed_markdown
directory and:
- Ignores files already named
index.md
— these are the listing pages on my site. - With the other files, Bear App creates a
.md
file name based on the title of the note, as well as a subdirectory with the same name. I don’t like this as I prefer files to be named index so that URLs are clean and without html file names. So I copy the.md
file to the subdirectory (if it exists, create it if it doesn’t), and rename itindex.md
.
5 Subfolder Dashes
Bear exports markdown file and directory names which include spaces and non-URL friendly characters. Script recursively renames subdirectories changing spaces to dashes, and removing invalid characters.
6 Search And Replace
This script does a search and replace on all the Markdown files, making changes to the Bear markdown to make it compatible with Quarto. Specifically, it:
- Removes the nested tags I use for organizing content in Bear (the organization is already reflected in the exported directory structure).
- Removes any instances of `` — these are Quarto listing pages, the titles are defined in the YAML.
- Replaces
{“width":NUMBER}
with{width=NUMBER}
, so I can resize images in Bear and they will appear the correct size in Quarto. - Replaces the code Bear export for highlights to HTML
<mark>
tags, with the correct coloring. - Changes links to PDFs to embeds.
- Removes the directory path from the image path, since the linking note has moved into the directory containing the image.
7 Process YAML Headers
This adds YAML front matter to all .md
files that don’t have them, and modifies them if they do:
- If no title exists, use the first header in the markdown.
- If no date exists, use the first date in the markdown.
- Add categories to the front matter, based on Bear tags in the Markdown. (To make parsing simpler, in Bear I put each tag on a separate line).
- Removes the extracted title, date, and category lines
8 Add folder variables to the front matter
This adds the folder and subfolder names of the page to the YAML front matter. This means I can create listings based on the folder names. I also use this to create bespoke listings.
9 Rename .md
To .qmd
Goes through all the files and simply renames .md
files to .qmd
(Quarto Markdown).
10 Handle Wikilinks
Bear uses Wikilinks for inter-page links, which are page titles in two sets of square brackets. This script converts them to ordinary markdown links. This is a slightly tricky process. First the script makes a list of .qmd
files and their associated title, then it uses that list to update all the Wikilinks.
11 Short Paths
On some pages in Bear I add a variable short-path
to the YAML front matter. This is so that I can have short paths for pages, rather than paths based on the title. This script renames the parent directory of for all notes with a short path, and then updates all internal links with the new path.
12 Create thumbnails
This script creates thumbnail images to be used in the listings. I say thumbnails but they are actually quite large — 720 pixels width. This is about twice the resolution of the display size, so on screens with retina displays the image should appear crisp.
The script uses the command line version of the Clop app. The lifetime licence is 15 USD and is well worth it. I use the app all the time. It performs the following operation on every poster image. I use the image
variable in the front matter, this script updates the name to the thumbnail version. It writes the thumbnail a thumbnail folder in the input/quarto_template
folder. This means that the script only creates the thumbnail once, and not every time the scripts are run (which would be very time consuming).
13 Combine To New Website
This script combines the content so the input/quarto_template
and processing/processed_markdown
directories into a new directory called processing/quarto_combined
.
15 Render Quarto
This script looks through all the YAML front matter in the .qmd
files. If the YAML contains this directive:
render: true
then that file is rendered using the Quarto render
command.
If no files are found to render, the whole site is rendered.
16 View locally
This script runs a local webserver and displays the local version of the site, so that I can check any changes before publishing them.
17 Publish site
This updates the relevant GitHub repository, which automatically triggers CloudFlare to update the website. It makes just a few seconds.
Creating the scripts
Here is an example of a prompt with OpenAI GTP-4o to create the scripts:
I have a directory of markdown files to process. Each markdown file has a YAML header. We are going to be updating those YAML headers.
Write a Python script using the click and yaml modules.
Accept a command line argument, root_dir.
DIRECTORY_TO_PROCESS = os.path.join(root_dir, "processing", "processed_markdown")
Loop through all subdirectories of DIRECTORY_TO_PROCESS
For each index.md file, if the file is in a subdirectory of DIRECTORY_TO_PROCESS, add a key "folder" with the name of the folder, and if the file is in a sub-subdirectory of DIRECTORY_TO_PROCESS, add a key "subfolder" with the name of the subfolder.