diff --git a/README.md b/README.md
index a42a0b9..31991e6 100644
--- a/README.md
+++ b/README.md
@@ -210,6 +210,7 @@ Want to learn more?
- ๐จ **[THEMES.md](documentation/THEMES.md)** - Theme customization and creating custom themes
- โจ **[FEATURES.md](documentation/FEATURES.md)** - Complete feature list and keyboard shortcuts
- ๐ท๏ธ **[TAGS.md](documentation/TAGS.md)** - Organize notes with tags and combined filtering
+- ๐ **[TEMPLATES.md](documentation/TEMPLATES.md)** - Create notes from reusable templates with dynamic placeholders
- ๐งฎ **[MATHJAX.md](documentation/MATHJAX.md)** - LaTeX/Math notation examples and syntax reference
- ๐ **[MERMAID.md](documentation/MERMAID.md)** - Diagram creation with Mermaid (flowcharts, sequence diagrams, and more)
- ๐ **[PLUGINS.md](documentation/PLUGINS.md)** - Plugin system and available plugins
diff --git a/backend/main.py b/backend/main.py
index 8b2539e..ad60af4 100644
--- a/backend/main.py
+++ b/backend/main.py
@@ -38,6 +38,9 @@ from .utils import (
validate_path_security,
get_all_tags,
get_notes_by_tag,
+ get_templates,
+ get_template_content,
+ apply_template_placeholders,
)
from .plugins import PluginManager
from .themes import get_available_themes, get_theme_css
@@ -777,6 +780,101 @@ async def get_notes_by_tag_endpoint(tag_name: str):
raise HTTPException(status_code=500, detail=safe_error_message(e, "Failed to get notes by tag"))
+# --- Template Endpoints ---
+
+@api_router.get("/templates")
+@limiter.limit("120/minute")
+async def list_templates(request: Request):
+ """
+ List all available templates from _templates folder.
+
+ Returns:
+ List of template metadata
+ """
+ try:
+ templates = get_templates(config['storage']['notes_dir'])
+ return {"templates": templates}
+ except Exception as e:
+ raise HTTPException(status_code=500, detail=safe_error_message(e, "Failed to list templates"))
+
+
+@api_router.get("/templates/{template_name}")
+@limiter.limit("120/minute")
+async def get_template(request: Request, template_name: str):
+ """
+ Get content of a specific template.
+
+ Args:
+ template_name: Name of the template (without .md extension)
+
+ Returns:
+ Template name and content
+ """
+ try:
+ content = get_template_content(config['storage']['notes_dir'], template_name)
+
+ if content is None:
+ raise HTTPException(status_code=404, detail="Template not found")
+
+ return {
+ "name": template_name,
+ "content": content
+ }
+ except HTTPException:
+ raise
+ except Exception as e:
+ raise HTTPException(status_code=500, detail=safe_error_message(e, "Failed to get template"))
+
+
+@api_router.post("/templates/create-note")
+@limiter.limit("60/minute")
+async def create_note_from_template(request: Request, data: dict):
+ """
+ Create a new note from a template with placeholder replacement.
+
+ Args:
+ data: Dictionary containing templateName and notePath
+
+ Returns:
+ Success status, path, and created content
+ """
+ try:
+ template_name = data.get('templateName', '')
+ note_path = data.get('notePath', '')
+
+ if not template_name or not note_path:
+ raise HTTPException(status_code=400, detail="Template name and note path required")
+
+ # Get template content
+ template_content = get_template_content(config['storage']['notes_dir'], template_name)
+
+ if template_content is None:
+ raise HTTPException(status_code=404, detail="Template not found")
+
+ # Apply placeholder replacements
+ final_content = apply_template_placeholders(template_content, note_path)
+
+ # Save the note
+ success = save_note(config['storage']['notes_dir'], note_path, final_content)
+
+ if not success:
+ raise HTTPException(status_code=500, detail="Failed to create note from template")
+
+ # Run plugin hooks
+ plugin_manager.run_hook('on_note_create', note_path=note_path, initial_content=final_content)
+
+ return {
+ "success": True,
+ "path": note_path,
+ "message": "Note created from template successfully",
+ "content": final_content
+ }
+ except HTTPException:
+ raise
+ except Exception as e:
+ raise HTTPException(status_code=500, detail=safe_error_message(e, "Failed to create note from template"))
+
+
# --- Notes Endpoints ---
@api_router.get("/notes")
diff --git a/backend/utils.py b/backend/utils.py
index 8459805..4d97d8b 100644
--- a/backend/utils.py
+++ b/backend/utils.py
@@ -647,3 +647,118 @@ def get_notes_by_tag(notes_dir: str, tag: str) -> List[Dict]:
return matching_notes
+
+# ============================================================================
+# Template Functions
+# ============================================================================
+
+def get_templates(notes_dir: str) -> List[Dict]:
+ """
+ Get all templates from the _templates folder.
+
+ Args:
+ notes_dir: Base notes directory
+
+ Returns:
+ List of template metadata (name, path, modified)
+ """
+ templates = []
+ templates_path = Path(notes_dir) / "_templates"
+
+ if not templates_path.exists():
+ return templates
+
+ # Security check: ensure _templates folder is within notes directory
+ if not validate_path_security(notes_dir, templates_path):
+ print(f"Security: Templates directory is outside notes directory: {templates_path}")
+ return templates
+
+ try:
+ for template_file in templates_path.glob("*.md"):
+ try:
+ # Security check: ensure each template is within notes directory
+ if not validate_path_security(notes_dir, template_file):
+ print(f"Security: Skipping template outside notes directory: {template_file}")
+ continue
+
+ stat = template_file.stat()
+ templates.append({
+ "name": template_file.stem,
+ "path": str(template_file.relative_to(notes_dir).as_posix()),
+ "modified": datetime.fromtimestamp(stat.st_mtime).isoformat()
+ })
+ except Exception as e:
+ print(f"Error reading template {template_file}: {e}")
+ continue
+ except Exception as e:
+ print(f"Error accessing templates directory: {e}")
+
+ return sorted(templates, key=lambda x: x['name'])
+
+
+def get_template_content(notes_dir: str, template_name: str) -> Optional[str]:
+ """
+ Get the content of a specific template.
+
+ Args:
+ notes_dir: Base notes directory
+ template_name: Name of the template (without .md extension)
+
+ Returns:
+ Template content or None if not found
+ """
+ template_path = Path(notes_dir) / "_templates" / f"{template_name}.md"
+
+ if not template_path.exists():
+ return None
+
+ # Security check: ensure template is within notes directory
+ if not validate_path_security(notes_dir, template_path):
+ print(f"Security: Template path is outside notes directory: {template_path}")
+ return None
+
+ try:
+ with open(template_path, 'r', encoding='utf-8') as f:
+ return f.read()
+ except Exception as e:
+ print(f"Error reading template {template_name}: {e}")
+ return None
+
+
+def apply_template_placeholders(content: str, note_path: str) -> str:
+ """
+ Replace template placeholders with actual values.
+
+ Supported placeholders:
+ {{date}} - Current date (YYYY-MM-DD)
+ {{time}} - Current time (HH:MM:SS)
+ {{datetime}} - Current datetime (YYYY-MM-DD HH:MM:SS)
+ {{timestamp}} - Unix timestamp
+ {{title}} - Note name without extension
+ {{folder}} - Parent folder name
+
+ Args:
+ content: Template content with placeholders
+ note_path: Path of the note being created
+
+ Returns:
+ Content with placeholders replaced
+ """
+ now = datetime.now()
+ note = Path(note_path)
+
+ replacements = {
+ '{{date}}': now.strftime('%Y-%m-%d'),
+ '{{time}}': now.strftime('%H:%M:%S'),
+ '{{datetime}}': now.strftime('%Y-%m-%d %H:%M:%S'),
+ '{{timestamp}}': str(int(now.timestamp())),
+ '{{title}}': note.stem,
+ '{{folder}}': note.parent.name if str(note.parent) != '.' else 'Root',
+ }
+
+ result = content
+ for placeholder, value in replacements.items():
+ result = result.replace(placeholder, value)
+
+ return result
+
diff --git a/docs/index.html b/docs/index.html
index e9f3244..f8dbcc8 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -7,8 +7,8 @@
NoteDiscovery - Your Self-Hosted Knowledge Base
-
-
+
+
@@ -17,7 +17,7 @@
-
+
@@ -28,7 +28,7 @@
-
+
@@ -509,7 +509,7 @@
Take Control of Your Notes
-
A lightweight, privacy-focused note-taking application with powerful features: LaTeX math equations, Mermaid diagrams, code highlighting, and more. Write, organize, and discover your notes with a beautiful, modern interfaceโall running on your own server.
+
A lightweight, privacy-focused note-taking application with powerful features: LaTeX math equations, Mermaid diagrams, smart tags, custom templates, code highlighting, and more. Write, organize, and discover your notes with a beautiful, modern interfaceโall running on your own server.
Get Started on GitHub โ
@@ -568,6 +568,18 @@
Syntax highlighting for popular coding languages. Developer-friendly notes.
+
+
๐ท๏ธ
+
Smart Tags
+
Organize with YAML frontmatter tags. Filter and discover notes instantly.
+
+
+
+
๐
+
Note Templates
+
Create from custom templates with dynamic placeholders. Meeting notes, journals, and more.
+
+
๐
Simple Storage
@@ -642,7 +654,15 @@
๐
Internal Links
- Connect notes with markdown links
+ Connect notes with backlinks
+
+
+
+
+
๐ผ๏ธ
+
+ Image Support
+ Drag & drop images directly
diff --git a/documentation/API.md b/documentation/API.md
index 96385bd..fd3c567 100644
--- a/documentation/API.md
+++ b/documentation/API.md
@@ -295,6 +295,120 @@ Self-documenting endpoint listing all available API routes.
---
+## ๐ท๏ธ Tags
+
+### List All Tags
+`GET /api/tags`
+
+Returns all tags found in notes with their usage counts.
+
+**Response:**
+```json
+{
+ "tags": {
+ "python": 5,
+ "tutorial": 3,
+ "backend": 2
+ }
+}
+```
+
+### Get Notes by Tag
+`GET /api/tags/{tag_name}`
+
+Returns all notes that have a specific tag.
+
+**Response:**
+```json
+{
+ "tag": "python",
+ "notes": [
+ {
+ "path": "tutorials/python-basics.md",
+ "name": "python-basics",
+ "folder": "tutorials",
+ "tags": ["python", "tutorial"]
+ }
+ ]
+}
+```
+
+---
+
+## ๐ Templates
+
+### List Templates
+`GET /api/templates`
+
+Returns all available note templates from the `_templates` folder.
+
+**Response:**
+```json
+{
+ "templates": [
+ {
+ "name": "meeting-notes",
+ "path": "_templates/meeting-notes.md",
+ "modified": "2025-11-26T10:30:00"
+ },
+ {
+ "name": "daily-journal",
+ "path": "_templates/daily-journal.md",
+ "modified": "2025-11-26T10:25:00"
+ }
+ ]
+}
+```
+
+### Get Template Content
+`GET /api/templates/{template_name}`
+
+Returns the content of a specific template.
+
+**Parameters:**
+- `template_name` - Template name (without .md extension)
+
+**Response:**
+```json
+{
+ "name": "meeting-notes",
+ "content": "# Meeting Notes\n\nDate: {{date}}\n..."
+}
+```
+
+### Create Note from Template
+`POST /api/templates/create-note`
+
+Creates a new note from a template with placeholder replacement.
+
+**Request Body:**
+```json
+{
+ "templateName": "meeting-notes",
+ "notePath": "meetings/weekly-sync.md"
+}
+```
+
+**Placeholders:**
+- `{{date}}` - Current date (YYYY-MM-DD)
+- `{{time}}` - Current time (HH:MM:SS)
+- `{{datetime}}` - Current datetime
+- `{{timestamp}}` - Unix timestamp
+- `{{title}}` - Note name without extension
+- `{{folder}}` - Parent folder name
+
+**Response:**
+```json
+{
+ "success": true,
+ "path": "meetings/weekly-sync.md",
+ "message": "Note created from template successfully",
+ "content": "# Meeting Notes\n\nDate: 2025-11-26\n..."
+}
+```
+
+---
+
## ๐ Response Format
All endpoints return JSON responses:
diff --git a/documentation/FEATURES.md b/documentation/FEATURES.md
index 7509ef7..9b6be0a 100644
--- a/documentation/FEATURES.md
+++ b/documentation/FEATURES.md
@@ -7,6 +7,7 @@
- **Three view modes**: Edit, Split, Preview
- **Auto-save** - Never lose your work
- **Undo/Redo** - Ctrl+Z / Ctrl+Y support
+- **Note templates** - Create notes from templates with dynamic placeholders
- **Syntax highlighting** for code blocks (50+ languages)
- **Copy code blocks** - One-click copy button on hover
- **LaTeX/Math rendering** - Beautiful mathematical equations with MathJax (see [MATHJAX.md](MATHJAX.md))
@@ -162,6 +163,51 @@ graph TD
๐ **See the [MERMAID](MERMAID.md) note for diagram examples and syntax reference.**
+## ๐ Note Templates
+
+Create notes from reusable templates with dynamic placeholder replacement.
+
+### Creating Templates
+1. Create markdown files in `data/_templates/` folder
+2. Use placeholders for dynamic content
+3. Templates appear in the "New from Template" menu
+
+### Available Placeholders
+- `{{date}}` - Current date (YYYY-MM-DD)
+- `{{time}}` - Current time (HH:MM:SS)
+- `{{datetime}}` - Current date and time
+- `{{timestamp}}` - Unix timestamp
+- `{{title}}` - Note name (without extension)
+- `{{folder}}` - Parent folder name
+
+### Example Template
+```markdown
+---
+tags: [meeting]
+date: {{date}}
+---
+
+# {{title}}
+
+**Created:** {{datetime}}
+
+## Notes
+
+```
+
+### Using Templates
+1. Click the "New" dropdown button
+2. Select "New from Template"
+3. Choose a template and enter a note name
+4. The new note will be created with placeholders replaced
+
+### Built-in Templates
+- **meeting-notes** - Template for meeting notes
+- **daily-journal** - Daily journal with morning goals and evening reflection
+- **project-plan** - Project planning template with objectives and timeline
+
+๐ **See [TEMPLATES.md](TEMPLATES.md)** for detailed documentation and example templates you can copy to your instance.
+
## โก Keyboard Shortcuts
### General
diff --git a/documentation/TEMPLATES.md b/documentation/TEMPLATES.md
new file mode 100644
index 0000000..fb88c5a
--- /dev/null
+++ b/documentation/TEMPLATES.md
@@ -0,0 +1,135 @@
+# ๐ Note Templates
+
+Create notes from reusable templates with dynamic placeholder replacement.
+
+## Overview
+
+Templates allow you to quickly create notes with predefined structures and content. Perfect for recurring note types like meeting notes, daily journals, project plans, and more.
+
+## How to Use Templates
+
+### 1. Create Template Files
+
+Templates are stored in the `data/_templates/` folder as markdown files. You will need to create such folder if it doesn't exist:
+
+```
+data/
+โโโ _templates/
+ โโโ meeting-notes.md
+ โโโ daily-journal.md
+ โโโ project-plan.md
+```
+
+### 2. Access Templates
+
+Click the **"New"** button (or **+** on any folder) and select **"New from Template"**:
+
+1. Choose a template from the dropdown
+2. Enter a name for your new note
+3. Click "Create Note"
+
+The template will be copied with all placeholders replaced automatically!
+
+### 3. Use Placeholders
+
+Templates support dynamic placeholders that are replaced when you create a note:
+
+| Placeholder | Description | Example |
+|------------|-------------|---------|
+| `{{date}}` | Current date | `2025-11-26` |
+| `{{time}}` | Current time | `14:30:45` |
+| `{{datetime}}` | Current date and time | `2025-11-26 14:30:45` |
+| `{{timestamp}}` | Unix timestamp | `1732632645` |
+| `{{title}}` | Note name (without .md) | `Weekly Meeting` |
+| `{{folder}}` | Parent folder name | `Projects` |
+
+### Example Template
+
+```markdown
+---
+tags: [meeting]
+date: {{date}}
+---
+
+# Meeting Notes - {{title}}
+
+**Date:** {{datetime}}
+**Participants:**
+-
+
+## Agenda
+-
+
+## Discussion
+
+
+## Action Items
+- [ ]
+
+## Next Steps
+
+
+```
+
+When you create a note called "Team Sync" from this template, it becomes:
+
+```markdown
+---
+tags: [meeting]
+date: 2025-11-26
+---
+
+# Meeting Notes - Team Sync
+
+**Date:** 2025-11-26 14:30:45
+**Participants:**
+-
+
+## Agenda
+-
+
+## Discussion
+
+
+## Action Items
+- [ ]
+
+## Next Steps
+
+
+```
+
+## Example Templates
+
+We provide three example templates in `documentation/templates/` that you can copy to your `data/_templates/` folder:
+
+1. **meeting-notes.md** - Structured meeting notes with agenda, discussion, and action items
+2. **daily-journal.md** - Daily journal with morning goals and evening reflection
+3. **project-plan.md** - Project planning template with objectives, timeline, and status tracking
+
+### Using Example Templates
+
+**Option 1: Copy Manually**
+```bash
+cp documentation/templates/*.md data/_templates/
+```
+
+**Option 2: Create Your Own**
+1. Create a `.md` file in `data/_templates/`
+2. Add content and placeholders
+3. Save and it's ready to use!
+
+## Tips
+
+- โ
Templates can include YAML frontmatter for tags and metadata
+- โ
Use descriptive template names (they appear in the dropdown)
+- โ
Templates work in any folder - the context is preserved
+- โ
You can edit templates anytime - changes apply to new notes only
+- โ
Combine templates with tags for powerful organization
+
+---
+
+**See also:**
+- [Tags Documentation](TAGS.md) - Learn about organizing with tags
+- [Features Overview](FEATURES.md) - All application features
+
diff --git a/documentation/templates/daily-journal.md b/documentation/templates/daily-journal.md
new file mode 100644
index 0000000..f3843e9
--- /dev/null
+++ b/documentation/templates/daily-journal.md
@@ -0,0 +1,25 @@
+---
+tags: [journal, daily]
+date: {{date}}
+---
+
+# Daily Journal - {{date}}
+
+## ๐
Morning
+**Time:** {{time}}
+
+### Goals for Today
+- [ ]
+- [ ]
+- [ ]
+
+## ๐ Notes
+
+
+## ๐ Evening Reflection
+
+
+## ๐ก Ideas
+
+
+
diff --git a/documentation/templates/meeting-notes.md b/documentation/templates/meeting-notes.md
new file mode 100644
index 0000000..220ec44
--- /dev/null
+++ b/documentation/templates/meeting-notes.md
@@ -0,0 +1,24 @@
+---
+tags: [meeting]
+date: {{date}}
+---
+
+# Meeting Notes - {{title}}
+
+**Date:** {{datetime}}
+**Participants:**
+-
+
+## Agenda
+-
+
+## Discussion
+
+
+## Action Items
+- [ ]
+
+## Next Steps
+
+
+
diff --git a/documentation/templates/project-plan.md b/documentation/templates/project-plan.md
new file mode 100644
index 0000000..25cee3d
--- /dev/null
+++ b/documentation/templates/project-plan.md
@@ -0,0 +1,34 @@
+---
+tags: [project]
+created: {{datetime}}
+folder: {{folder}}
+---
+
+# Project: {{title}}
+
+## ๐ Overview
+
+
+## ๐ฏ Objectives
+-
+
+## ๐
Timeline
+- **Start Date:** {{date}}
+- **Target Completion:**
+
+## ๐ฆ Deliverables
+-
+
+## ๐ฅ Team
+
+
+## ๐ Status
+- [ ] Planning
+- [ ] In Progress
+- [ ] Review
+- [ ] Completed
+
+## ๐ Notes
+
+
+
diff --git a/frontend/app.js b/frontend/app.js
index 6e3bc15..811f718 100644
--- a/frontend/app.js
+++ b/frontend/app.js
@@ -99,6 +99,14 @@ function noteApp() {
// Dropdown state
showNewDropdown: false,
+ dropdownTargetFolder: '', // Folder context for "New" dropdown (empty = root)
+ dropdownPosition: { top: 0, left: 0 }, // Position for contextual dropdown
+
+ // Template state
+ showTemplateModal: false,
+ availableTemplates: [],
+ selectedTemplate: '',
+ newTemplateNoteName: '',
// Homepage state
selectedHomepageFolder: '',
@@ -258,6 +266,7 @@ function noteApp() {
await this.loadThemes();
await this.initTheme();
await this.loadNotes();
+ await this.loadTemplates();
await this.checkStatsPlugin();
this.loadSidebarWidth();
this.loadEditorWidth();
@@ -591,6 +600,72 @@ function noteApp() {
this.applyFilters();
},
+ // ========================================================================
+ // Template Methods
+ // ========================================================================
+
+ // Load available templates from _templates folder
+ async loadTemplates() {
+ try {
+ const response = await fetch('/api/templates');
+ const data = await response.json();
+ this.availableTemplates = data.templates || [];
+ } catch (error) {
+ ErrorHandler.handle('load templates', error, false); // Don't show alert, templates are optional
+ }
+ },
+
+ // Create a new note from a template
+ async createNoteFromTemplate() {
+ if (!this.selectedTemplate || !this.newTemplateNoteName.trim()) {
+ return;
+ }
+
+ try {
+ // Determine the note path based on dropdown context
+ let notePath = this.newTemplateNoteName.trim();
+ if (!notePath.endsWith('.md')) {
+ notePath += '.md';
+ }
+
+ // If we have a target folder context, create in that folder
+ if (this.dropdownTargetFolder || this.selectedHomepageFolder) {
+ const targetFolder = this.dropdownTargetFolder || this.selectedHomepageFolder;
+ notePath = `${targetFolder}/${notePath}`;
+ }
+
+ // Create note from template
+ const response = await fetch('/api/templates/create-note', {
+ method: 'POST',
+ headers: { 'Content-Type': 'application/json' },
+ body: JSON.stringify({
+ templateName: this.selectedTemplate,
+ notePath: notePath
+ })
+ });
+
+ if (!response.ok) {
+ const error = await response.json();
+ alert(error.detail || 'Failed to create note from template');
+ return;
+ }
+
+ const data = await response.json();
+
+ // Close modal and reset state
+ this.showTemplateModal = false;
+ this.selectedTemplate = '';
+ this.newTemplateNoteName = '';
+
+ // Reload notes and open the new note
+ await this.loadNotes();
+ await this.loadNote(data.path);
+
+ } catch (error) {
+ ErrorHandler.handle('create note from template', error);
+ }
+ },
+
// Clear all tag filters
clearTagFilters() {
this.selectedTags = [];
@@ -908,17 +983,11 @@ function noteApp() {
๐
- ๐
+ title="Add item here"
+ >+
window.innerWidth) {
+ left = rect.right - dropdownWidth;
+ }
+ if (top + dropdownHeight > window.innerHeight) {
+ top = rect.top - dropdownHeight - 4;
+ }
+
+ this.dropdownPosition = { top, left };
+ }
},
closeDropdown() {
this.showNewDropdown = false;
+ this.dropdownTargetFolder = ''; // Reset folder context
},
// =====================================================
// UNIFIED CREATION FUNCTIONS (reusable from anywhere)
// =====================================================
- async createNote(folderPath = '') {
+ async createNote(folderPath = null) {
+ // Use provided folder path, or dropdown target folder context
+ const targetFolder = folderPath !== null ? folderPath : this.dropdownTargetFolder;
this.closeDropdown();
- const promptText = folderPath
- ? `Create note in "${folderPath}".\nEnter note name:`
+ const promptText = targetFolder
+ ? `Create note in "${targetFolder}".\nEnter note name:`
: 'Enter note name (you can use folder/name):';
const noteName = prompt(promptText);
@@ -1926,8 +2017,8 @@ function noteApp() {
}
let notePath;
- if (folderPath) {
- notePath = `${folderPath}/${sanitizedName}.md`;
+ if (targetFolder) {
+ notePath = `${targetFolder}/${sanitizedName}.md`;
} else {
notePath = sanitizedName.endsWith('.md') ? sanitizedName : `${sanitizedName}.md`;
}
@@ -1947,8 +2038,8 @@ function noteApp() {
});
if (response.ok) {
- if (folderPath) {
- this.expandedFolders.add(folderPath);
+ if (targetFolder) {
+ this.expandedFolders.add(targetFolder);
}
await this.loadNotes();
await this.loadNote(notePath);
@@ -1960,11 +2051,13 @@ function noteApp() {
}
},
- async createFolder(parentPath = '') {
+ async createFolder(parentPath = null) {
+ // Use provided parent path, or dropdown target folder context
+ const targetFolder = parentPath !== null ? parentPath : this.dropdownTargetFolder;
this.closeDropdown();
- const promptText = parentPath
- ? `Create subfolder in "${parentPath}".\nEnter folder name:`
+ const promptText = targetFolder
+ ? `Create subfolder in "${targetFolder}".\nEnter folder name:`
: 'Create new folder.\nEnter folder path (e.g., "Projects" or "Work/2025"):';
const folderName = prompt(promptText);
@@ -1976,7 +2069,7 @@ function noteApp() {
return;
}
- const folderPath = parentPath ? `${parentPath}/${sanitizedName}` : sanitizedName;
+ const folderPath = targetFolder ? `${targetFolder}/${sanitizedName}` : sanitizedName;
// Check if folder already exists
const existingFolder = this.allFolders.find(folder => folder === folderPath);
@@ -1993,8 +2086,8 @@ function noteApp() {
});
if (response.ok) {
- if (parentPath) {
- this.expandedFolders.add(parentPath);
+ if (targetFolder) {
+ this.expandedFolders.add(targetFolder);
}
this.expandedFolders.add(folderPath);
await this.loadNotes();
diff --git a/frontend/index.html b/frontend/index.html
index 0e890c5..9d89623 100644
--- a/frontend/index.html
+++ b/frontend/index.html
@@ -615,6 +615,12 @@
}
/* Mobile Responsive Styles */
+ /* Z-index hierarchy (for reference):
+ - Mobile sidebar: 1000
+ - Mobile overlay: 999
+ - Template modal: 1100 (must be above sidebar)
+ - Dropdown menu: 50 (below everything)
+ */
@media (max-width: 768px) {
/* Hide sidebar by default on mobile */
.mobile-sidebar {
@@ -897,9 +903,9 @@
-
+
-
-
-
-
-
- ๐
- New Note
-
-
- ๐
- New Folder
-
-
-
@@ -1141,6 +1110,22 @@
+
+
+
+
+ ๐
+ New Note
+
+
+ ๐
+ New Folder
+
+
+ ๐
+ New from Template
+
+
+
+
+
+
+
+
+
Create from Template
+
+
+
+
+ Select Template
+
+
+ -- Choose a template --
+
+
+
+
+
+
+
+
+
+ Note Name
+
+
+
+
+
+
+ Available placeholders:
+ {{date}},
+ {{time}},
+ {{datetime}},
+ {{title}},
+ {{folder}}
+
+
+
+
+ No templates found. Create templates in the _templates folder.
+
+
+
+
+
+ Create Note
+
+
+ Cancel
+
+
+
+
+