---
This article details some of the automations I've set up for prepping files for publication using [Obsidian Publish](https://obsidian.md/publish). Before creating these scripts, I was manually performing these tasks across numerous notes, and it was becoming impossible to keep up.
![[IMG-Obsidian Publish Workflow - Automating Publication Prep-20250628175338739.gif|300]]
---
The primary challenge was transforming Dataview queries (tables and lists) into a Markdown format compatible with static websites, as these queries do not render in that environment. Another tedious tasks was maintaining consistent frontmatter properties across all notes. While not strictly mandatory, disorganization over time invariably led to errors and chaos.
![[IMG-Obsidian Publish Workflow - Automating Publication Prep-20250628175338769.gif|300]]
---
## Templater: "Prepare Notes for Publication" Macro
I automated this process using the Obsidian community plug-in, [Templater](https://silentvoid13.github.io/Templater/). It’s a tool I'm very familiar with and use daily to automate new note creation in specific folders. This new macro organizes my article notes and prepares them for publication.
---
When triggered, this macro provides two main jobs:
### Frontmatter Management
*(for designated "Article" folders)*
![[IMG-Obsidian Publish Workflow - Automating Publication Prep-20250628175338829.png|center|400]]
</br>
1. **Ensures Default Properties:**
It automatically adds predefined frontmatter fields (like `title`, `description`, `author`, `publish`, `tags`, etc.) to your notes if they are missing, using sensible defaults.
</br>
2. **Standardizes Date Formats:**
It ensures your `created`, `updated`, and `published` dates are consistently formatted.
</br>
3. **Automates Publish/Published Logic:**
When you set the `publish` flag to `true`, it can automatically timestamp the `published` date.
</br>
4. **Sorts Tags:**
Keeps your tags alphabetized for better organization.
</br>
5. **Orders Properties:**
Presents your frontmatter in a clean, predefined order, enhancing readability.
</br>
### **Dataview to Markdown Conversion:**
*(for designated folders or specific files)*
| | ![[IMG-Obsidian Publish Workflow - Automating Publication Prep-20250628175338882.png]] | </br></br></br></br>→ | ![[IMG-Obsidian Publish Workflow - Automating Publication Prep-20250628175338982.png\|300]] |
| --- | -------------------------------------------------------------------------------------------- | --------------------- | ------------------------------------------------------------------------------------------------- |
</br>
1. **Finds Dataview Queries:**
The script intelligently identifies Dataview code blocks within your notes.
</br>
2. **Executes Queries:**
It leverages the Dataview plugin (behind the scenes) to run these queries.
</br>
3. **Generates Static Markdown:**
It takes the live results of your tables and lists and converts them into standard Markdown. This ensures that your published notes display the correct information, even though the underlying queries are no longer active on the static site.
</br>
4. **Replaces Existing Markdown:**
Crucially, the script _replaces_ any previously generated Markdown from Dataview queries. This means your published content always reflects the latest results when you run the macro.
</br>
## Setting up the Macro
</br>
1. **Get the Tools:**
Make sure the [Dataview](https://blacksmithgu.github.io/obsidian-dataview/) and [Templater](https://silentvoid13.github.io/Templater/) community plugins are installed and enabled.
</br>
2. **Create a Script:**
Make a new note and paste the [[#Appendix|script code]] (see Appendix) into it.
</br>
3. **Modify the Script:**
Open the script and look at **Section 1: USER CONFIGURATION**. Point it to the right folders and configure the frontmatter to your preferences. No real coding required.
</br>
5. **Launch It!**
My preferred way to launch this macro is using Command Palette (`Ctrl/Cmd+P`).
</br>
6. **From the Command Palette:**
From Command Palette, type "template”, then select the option “Open Insert template modal” and press Enter.
</br>
![[IMG-Obsidian Publish Workflow - Automating Publication Prep-20250628175339078.png|500]]
</br>
7. **Select the Macro:**
Now select the new macro that was created: “Macro - Prepare Notes for Publication”
</br>
![[IMG-Obsidian Publish Workflow - Automating Publication Prep-20250628175339148.png|500]]
</br>
---
## Start Publishing
And just like that, a multi-step, once-tedious process is distilled into a single command. The macro runs, magic unfolds, and you're free to return to the truly enjoyable part: writing.
![[IMG-Obsidian Publish Workflow - Automating Publication Prep-20250628175339218.gif|300]]
---
## Appendix
Here’s the full Templater script discussed in this article. Modify and enjoy!
>[!important]- Templater Publish Template Code
>```js
><%*
>function formatYamlArrayValue(arr,
> indent = " ") {
> if (!arr || arr.length === 0) {
> return "[]";
> }
> return "\n" + arr.map((item) =>
> `${indent}- ${item}`).join(
> "\n");
>}
>
>// Function to generate a UUID (version 4)
>function generateUUID_for_permalink() {
> return ([1e7] + -1e3 + -4e3 + -8e3 +
> -1e11).replace(/[018]/g, (
> c) =>
> (
> c ^
> (crypto.getRandomValues(
> new Uint8Array(
> 1))[0] & (
> 15 >> (c / 4)))
> ).toString(16)
> );
>}
>
>// --- 1. Prompt for Title (Mandatory) ---
>let defaultTitleForPrompt = "";
>if (
> typeof tp.file.title === "string" &&
> tp.file.title.trim() !== "" &&
> !tp.file.title.toLowerCase()
> .startsWith("untitled")
>) {
> defaultTitleForPrompt = tp.file
> .title;
>}
>let titleForFrontmatter = await tp
> .system.prompt(
> "Blog Post Title:",
> defaultTitleForPrompt
> );
>
>if (!titleForFrontmatter ||
> titleForFrontmatter.trim() === "") {
> new Notice(
> "Title is required. Template processing aborted.",
> 7000);
> return;
>}
>
>// --- 2. Permalink Logic (Generate or Use Existing) ---
>let permalinkValueToInsert = "";
>let permalinkWasGenerated = false;
>const existingPermalinkInFile = tp
> .frontmatter
> ?.permalink; // Refers to frontmatter of the file *before* this template is applied>
>
>if (existingPermalinkInFile &&
> existingPermalinkInFile.trim() !==
> "") {
> permalinkValueToInsert =
> existingPermalinkInFile.trim();
> permalinkWasGenerated = false;
>}
>else {
> permalinkValueToInsert =
> generateUUID_for_permalink();
> permalinkWasGenerated = true;
>}
>
>// --- Frontmatter String ---
>const yamlFrontmatterString = `---
>title: ${titleForFrontmatter}
>description:
>author: David Rusho
>publish: false
>draft: true
>permalink: ${permalinkValueToInsert}
>created: ${tp.date.now("YYYY-MM-DD")}
>updated: ${tp.date.now("YYYY-MM-DD")}
>published:
>category:
>tags:
>series:
>cover:
>cover_alt:
>cssclasses: ["academia", "academia-rounded"]
>---`;
>
>tR = yamlFrontmatterString;
>await tp.file.rename("DRAFT_" +
> titleForFrontmatter);
>
>-%>
>```