Advanced Templater Techniques for Obsidian: Beyond Basic Templates
The Templater plugin transforms Obsidian from a static note-taking app into a dynamic knowledge workspace. While basic templates insert static text, Templater’s true power lies in its ability to execute JavaScript during template instantiation, enabling intelligent, context-aware notes.
What is Templater?
Templater is an Obsidian community plugin that adds template functionality with executable JavaScript. Unlike simple snippet expanders, Templater runs code when you apply a template, giving you access to:
- Obsidian’s API (
tpobject) - User-defined functions
- System utilities (file operations, date manipulation, etc.)
- User prompts for dynamic input
Advanced Example 1: Smart User Prompts
Move beyond static placeholders with intelligent prompting that adapts to context:
<%*
// Project setup template with validation
const projectName = tp.user.prompt("Project name:", "My New Project");
if (!projectName.trim()) {
throw new Error("Project name cannot be empty");
}
// Smart default for description based on project name
const defaultDesc = `A project focused on ${projectName}`;
const description = tp.user.prompt("Project description:", defaultDesc);
// Auto-sanitize for folder names
const safeName = projectName.toLowerCase().replace(/[^a-z0-9]+/g, "-");
// Create project folder structure
await tp.file.move(`/${safeName}/${safeName}.md`);
tp.file.create_new(tp.file.find_tpl("project-readme")[0], `${safeName}/README.md`);
tp.file.create_new(tp.file.find_tpl("project-todo")[0], `${safeName}/todo.md`);
%>
# <%= projectName %>
<%= description %>
This template validates input, creates intelligent defaults, and sets up an entire folder structure with related files—all triggered by a single template application.
Advanced Example 2: Dynamic Data Integration
Fetch and incorporate external data at note creation time:
<%*
// Weather-integrated daily note
const apiKey = "YOUR_OPENWEATHER_API_KEY"; // Store securely in user settings
const city = tp.user.prompt("City for weather:", "London");
const url = `https://api.openweathermap.org/data/2.5/weather?q=${encodeURIComponent(city)}&appid=${apiKey}&units=metric`;
try {
const response = await tp.net.httpFetch(url);
const weatherData = JSON.parse(await response.text);
const temp = Math.round(weatherData.main.temp);
const description = weatherData.weather[0].description;
const icon = weatherData.weather[0].icon;
tR += `## Weather in ${city}

**Temperature:** ${temp}°C
**Conditions:** ${description}
`;
} catch (e) {
tR += `> *Could not fetch weather data: ${e.message}*`;
}
%>
# Daily Note: <% tp.date.now("YYYY-MM-DD") %>
<%* await tp.user.weather_integration() %>
This example demonstrates real-time API integration, error handling, and dynamic content insertion—turning a simple daily note into a personalized dashboard.
Advanced Example 3: Template Chaining with User Functions
Create reusable workflow components by defining functions in your Templater user scripts folder:
User Script (~/Obsidian/Vault/Templater/user.js):
module.exports = {
createMeetingNote: async function(attendees, duration) {
const date = tp.date.now("YYYY-MM-DD HH:mm");
const endTime = tp.date.now("YYYY-MM-DD HH:mm", offset + (duration * 60));
return `
# Meeting: <% tp.file.title %>
**Date:** ${date} - ${endTime}
**Attendees:** ${attendees.join(", ")}
## Agenda
-
## Notes
-
## Action Items
- [ ]
`;
}
};
Template Usage:
<%*
const attendees = tp.user.prompt("Enter attendees (comma-separated):", "alice,bob,charlie")
.split(",")
.map(s => s.trim());
const duration = parseInt(tp.user.prompt("Meeting duration (minutes):", "60")) || 60;
tR += await tp.user.createMeetingNote(attendees, duration);
%>
This pattern promotes code reuse, separation of concerns, and complex workflow automation through modular user functions.
Advanced Example 4: Context-Aware Note Linking
Leverage the Obsidian API to intelligently link new notes to existing knowledge:
<%*
// Find related notes based on current selection or prompt
const searchTerm = tp.user.prompt("Search for related notes:", tp.selection_is_text ? tp.selected_text : "");
if (searchTerm.trim()) {
const results = await tp.db.search(searchTerm, {
fileTypes: ["markdown"],
limit: 5
});
if (results.files.length > 0) {
tR += "## Related Notes\n";
results.files.forEach(file => {
tR += `- [[${file.path}]]\n`;
});
} else {
tR += "> *No related notes found for:* `" + searchTerm + "`\n";
}
}
%>
# Note: <% tp.file.title %>
<%* await tp.user.find_related_notes() %>
This creates immediate contextual connections, helping build a more interconnected knowledge graph as you create content.
Best Practices for Advanced Templater Use
- Security First: Never hardcode API keys in templates—use Templater’s secure settings or environment variables.
- Modularize: Move complex logic to user.js files for reusability and easier maintenance.
- Handle Errors Gracefully: Always wrap async operations in try/catch blocks to prevent template failures.
- Performance: Avoid expensive operations in frequently used templates; consider caching results.
- User Experience: Provide clear prompts with sensible defaults to reduce friction.
Templater’s true strength emerges when you combine these techniques—creating templates that aren’t just passive inserts, but active participants in your knowledge workflow. By prompting for input, integrating external data, leveraging user functions, and interacting with the Obsidian API, you transform note creation into an intelligent, adaptive process that grows with your knowledge needs.
Master Templater to make your Obsidian vault not just a collection of notes, but a dynamic knowledge ecosystem that works for you.
