Get AI summaries of any video or article — Sign up free
Obsidian - Create a Handlebar Template from JSON (JSON/CV Importer) thumbnail

Obsidian - Create a Handlebar Template from JSON (JSON/CV Importer)

Josh Plunkett·
6 min read

Based on Josh Plunkett's video on YouTube. If you like this content, support the original creators by watching, liking and subscribing to their content.

TL;DR

Install the Json CSV importer plugin (by filing 42) and use its Handlebars template support to control how JSON fields become Obsidian note content.

Briefing

A practical workflow for turning large JSON spell datasets into one Obsidian note per item hinges on writing a correct Handlebars template that matches the JSON’s structure—especially when fields are nested or repeat. The payoff is speed and control: once the template is right, importing hundreds or even thousands of spells becomes largely “set and forget,” with Obsidian notes generated in the layout the user wants.

The process starts with installing the “Json CSV importer” plugin (by filing 42) and using its Handlebars integration. The template isn’t generic: it must reflect how the JSON is shaped. For a concrete example, the walkthrough uses 5eTools data from GitHub (specifically the “spells-php.json” file inside a downloaded zip). That file contains thousands of lines, with each spell represented as a nested object keyed by spell name (e.g., “acid-splash”). The goal is to extract key fields—like name, level, school, casting time, range, and descriptive text—into a single note per spell.

To learn Handlebars syntax safely, the walkthrough leans on handlebarsjs.com’s live demo. Simple fields work via direct lookups like {{name}} and {{level}}. But nested objects require precise paths. For instance, casting time may be stored as time.number and time.unit, so a naive {{time}} returns “object object.” The template must drill down to the right subfields, and it must handle capitalization using the plugin’s built-in helpers (not the demo site’s limited environment). The walkthrough also highlights a common gotcha: capitalization and other helpers available in the Obsidian plugin won’t necessarily behave the same in the Handlebars demo.

Repeating structures introduce another layer. When JSON contains arrays (or “unknown counts” of items), the template needs looping constructs. The walkthrough uses each to iterate over time entries (so multiple casting-time actions can be rendered) and over class lists (so every class that can cast a spell becomes a comma-separated list). Descriptions are also treated as collections: spell text often arrives in multiple entries, so rendering requires looping through entries rather than assuming a single blob of text.

After building a template, the workflow tests with a small JSON subset (a manually extracted few spells saved as testimport.json). In Obsidian, the importer is configured with the JSON file, the Handlebars template, the field to use as the note name (name), and options like overriding existing notes. The resulting notes are then checked in reading mode, including optional styling via the ITS theme.

Finally, the walkthrough addresses cleanup and maintainability. Some outputs may include ugly placeholders like “object object” when a field path is wrong or a helper isn’t applied correctly. The suggested fix is iterative refinement: import a small sample, adjust the template line-by-line, then re-import. For broader cleanup, it recommends using find/replace across the generated notes (e.g., removing repeated “object object” artifacts) while being careful not to break other content.

The overall message is that JSON-to-notes isn’t about memorizing Handlebars—it’s about mapping the template to the JSON’s nesting and repetition patterns, then iterating until the import output matches the desired Obsidian note structure.

Cornell Notes

Turning 5eTools-style spell JSON into one Obsidian note per spell requires a Handlebars template that mirrors the JSON’s structure. Simple fields map directly (e.g., {{name}}, {{level}}), but nested objects (like casting time) must be accessed via precise paths (e.g., time.number and time.unit) or the template will output “object object.” Arrays and variable-length lists require loops using each, such as iterating over time entries or class lists to render multiple actions or multiple caster classes. The workflow is designed for iteration: test with a small JSON subset, import with the Json CSV importer plugin, inspect the generated notes, then refine the template until the output is clean. Once correct, the same template can generate large note batches quickly.

Why does a template sometimes output “object object” instead of a usable value?

“object object” appears when the template tries to print a whole nested object rather than a specific property inside it. For example, casting time may be stored as time.number and time.unit. Using {{time}} returns the entire time object, not a single field, so Handlebars can’t render it cleanly. The fix is to reference the correct nested path (e.g., {{time.number}} and {{time.unit}}) and format the result (including capitalization) using the plugin’s helpers.

How should nested fields be accessed when the JSON has multiple levels (e.g., range → distance → type/amount)?

Nested objects require dot-path navigation that matches the JSON depth. If range contains a distance object, and distance contains type and amount, the template must follow that chain. The walkthrough demonstrates that using a path like range.distance.type can return a concrete value (e.g., “feet”), while printing range.distance directly can still return an object. When both amount and unit are needed, the template pulls amount and type separately and combines them (e.g., “60 feet”), applying capitalization where appropriate.

When does the template need loops like each, and what do they solve?

Loops are needed when the JSON contains arrays or repeated sections where the count isn’t fixed. The walkthrough uses each for casting time entries so multiple actions can be rendered (e.g., “one action” and “two actions”). It also uses each for class lists, where a spell can be cast by an unknown number of classes. In both cases, each iterates through the collection and outputs a formatted fragment per item, with commas or line breaks added outside the loop to join results.

Why might capitalization work in Obsidian but not in the Handlebars demo site?

The plugin (by filing 42) provides built-in helpers such as capitalize, but the standalone Handlebars demo environment doesn’t necessarily implement those same helpers. The walkthrough notes that capitalize is available in the importer’s Handlebars context, so templates can rely on it there. When testing on handlebarsjs.com, removing the helper may be necessary to see raw values, then reintroducing the helper once running through the Obsidian importer.

What’s the recommended testing strategy before importing a full dataset?

Start with a tiny JSON subset—often by copying one spell object (or a handful) into a new file like testimport.json—and import that first. This makes it easier to debug template paths, helper usage, and loops. After the output looks correct for the sample, scale up by importing a larger set (e.g., 10 spells) and verifying that variations in the JSON structure don’t break the template.

How can generated notes be cleaned up when the template still leaves artifacts?

If the template produces unwanted placeholders (like “object object”) due to missing paths or unhandled cases, the walkthrough suggests cleaning after import using search/replace tools (e.g., find in files in a text editor). It also recommends targeted fixes: inspect where the artifact appears, adjust the template logic, and re-import. Because broad replacements can break content, patterns should be used carefully and ideally only where the artifact is known to occur.

Review Questions

  1. In what situations would you choose {{time.number}}/{{time.unit}} over {{time}} in a Handlebars template?
  2. How would you modify a template to render a comma-separated list of classes when the number of classes varies per spell?
  3. What iterative steps would you follow to debug a template that outputs “object object” for range or casting time fields?

Key Points

  1. 1

    Install the Json CSV importer plugin (by filing 42) and use its Handlebars template support to control how JSON fields become Obsidian note content.

  2. 2

    Match the Handlebars template to the JSON structure: direct fields like name/level work, but nested objects require dot-paths to specific properties.

  3. 3

    Avoid printing entire nested objects; when {{...}} targets an object rather than a property, output often becomes “object object.”

  4. 4

    Use each for arrays or variable-length lists (casting time entries, class lists, multi-paragraph description entries) so repeated sections render correctly.

  5. 5

    Test with a small JSON subset first, then scale up; variations across spells can break templates that worked for only one example.

  6. 6

    Use the plugin’s helpers (like capitalize and lookup-table logic) in Obsidian, but don’t assume the same helpers exist in external Handlebars demo environments.

  7. 7

    After import, clean up artifacts with careful find/replace and/or template fixes, then re-import until the output is consistent.

Highlights

The template must reflect JSON nesting: printing a whole nested object (e.g., time) produces “object object,” while printing specific subfields (e.g., time.number/unit) yields usable text.
Loops are essential for variable-length data: each turns arrays like casting-time entries and class lists into properly formatted output.
Plugin helpers (like capitalize and lookup-table) can’t be trusted to behave the same in generic Handlebars demo sites; validate inside the Obsidian importer.
A small “testimport.json” subset is the fastest way to debug template paths before importing thousands of spells.
When descriptions arrive as multiple entries, rendering requires looping through entries rather than assuming one continuous description field.

Topics

Mentioned