___ _ _ _ _ _____ _
/ _ \| |__ ___(_) __| (_) __ _ _ __| ___|_ ___ __ ___ _ __| |_ ___ _ __
| | | | '_ \/ __| |/ _` | |/ _` | '_ \ |_ \ \/ / '_ \ / _ \| '__| __/ _ \ '__|
| |_| | |_) \__ \ | (_| | | (_| | | | | _| > <| |_) | (_) | | | || __/ |
\___/|_.__/|___/_|\__,_|_|\__,_|_| |_|_| /_/\_\ .__/ \___/|_| \__\___|_|
|_|
Converts Obsidian vaults to importable packages for AppFlowy, Notion, and Outline. Preserves markdown content, internal document links, assets, and folder structure.
Obsidian uses a different format than other note-taking apps for links, content structure, and organization. Direct import between systems isn't possible without conversion.
This tool:
- Scans Obsidian vaults and extracts markdown files, assets, and wikilinks
- Transforms Obsidian-specific syntax (wikilinks, callouts, block references) to target formats
- Generates properly structured documents for each target system
- Creates importable packages (ZIP files) for easy migration
Step 1: Copy this repository to your computer
git clone https://github.com/username/ObsidianExporter.git
cd ObsidianExporterStep 2: Set up Python environment
python -m venv venv
# On Windows:
venv\Scripts\activate
# On Mac/Linux:
source venv/bin/activateStep 3: Install required packages
pip install -r requirements.txtStep 4: Convert your vault (replace with your vault path)
# For Outline:
python -m src.cli convert "C:\Users\YourName\Documents\MyVault" --format outline
# For AppFlowy:
python -m src.cli convert "C:\Users\YourName\Documents\MyVault" --format appflowy
# For Notion (via AppFlowy):
python -m src.cli convert "C:\Users\YourName\Documents\MyVault" --format notionStep 5: Import the ZIP file
- Find the generated ZIP file in the same folder
- Open your target app (Outline/AppFlowy/Notion)
- Go to Settings → Import
- Upload the ZIP file
Done! Your notes are now in your new app.
"Command not found" error:
- Make sure Python is installed:
python --version - Try
python3instead ofpython
"No module named src" error:
- Make sure you're in the ObsidianExporter folder:
cd ObsidianExporter - Make sure venv is activated (you should see
(venv)in your terminal)
Import fails in target app:
- For Outline: Try using preflight scripts (see section below)
- Check that your vault folder contains a
.obsidianfolder - Run with
--validate-onlyfirst to check for issues
Need help finding your vault path?
- Windows: Usually
C:\Users\YourName\Documents\ObsidianVault - Mac: Usually
/Users/YourName/Documents/ObsidianVault - In Obsidian: Settings → About → Vault path
git clone <repository-url>
cd ObsidianExporter
python -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activate
pip install -r requirements.txtChoose your target application with the --format option:
# AppFlowy (default)
python -m src.cli convert /path/to/vault --format appflowy
# Notion format (works with AppFlowy's Notion import)
python -m src.cli convert /path/to/vault --format notion
# Outline JSON format
python -m src.cli convert /path/to/vault --format outlineConvert your vault using the default AppFlowy format:
python -m src.cli convert /path/to/obsidian/vaultCreates vault-name-appflowy-export.zip in current directory.
python -m src.cli convert /path/to/vault --format outline --output my-notes.zip --name "My Notes"Validate your vault to see broken links and potential problems:
python -m src.cli convert /path/to/vault --format outline --validate-onlySee detailed progress during conversion:
python -m src.cli convert /path/to/vault --format outline --verbose# Check vault health first
python -m src.cli convert ~/Documents/MyVault --format outline --validate-only
# If validation passes, convert with progress
python -m src.cli convert ~/Documents/MyVault --format outline --output ~/Desktop/my-notes.zip --verbose
# Or use nested documents for better hierarchy
python -m src.cli convert ~/Documents/MyVault --format outline --nested-documents --output ~/Desktop/my-notes.zip- Markdown files: Content preserved with syntax transformation
- Internal links:
[[Page Name]]→ working document links in target system - Link aliases:
[[Document|Display Text]]→ preserves custom display text - Case-insensitive linking: Links work regardless of case differences
- Assets: Images and attachments copied to package
- Callouts: Obsidian callouts → equivalent formats where supported
- Block references:
^block-id→ target system format - Folder structure: Maintained as collections/folders in target system
- Frontmatter: YAML metadata converted to document properties
- Obsidian plugins and their data
- Canvas files
- Complex embedded content
- Plugin-specific syntax (Dataview, Templater, etc.)
- Run the converter with
--format appflowy - Open AppFlowy
- Go to Settings → Import
- Select the generated ZIP file
- Follow AppFlowy's import wizard
- Run the converter with
--format notion - Open AppFlowy
- Go to Settings → Import → Import from Notion
- Select the generated ZIP file
- Follow the import process
- Run the converter with
--format outline - Open your Outline instance
- Go to Settings → Import
- Choose "JSON Export" as import type
- Upload the generated ZIP file
For Outline exports, use the --nested-documents flag to create a hierarchical structure:
# Traditional: Each folder becomes a separate collection
python -m src.cli convert /path/to/vault --format outline
# Nested: Single collection with nested document hierarchy
python -m src.cli convert /path/to/vault --format outline --nested-documentsChanges with --nested-documents:
- Single collection instead of multiple collections
- Folders become documents with folder icons
- Uses Outline's
parentDocumentIdfor hierarchy - Preserves wikilinks to folders
- Creates nested structure in sidebar
When to use:
- Use
--nested-documentsfor vault-wide organization with folder hierarchy - Use default mode for independent collections per folder
For best results, clean up wikilinks before export:
- Fix broken links: Use Obsidian's "Broken links" core plugin to identify and fix missing targets
- Match filenames: Ensure
[[Link Name]]matches actual filenameLink Name.md - Check case sensitivity:
[[SurfaceStreams]]should matchSurfaceStreams.md, notsurface-streams.md - Use validation: Run with
--validate-onlyto see potential issues before conversion
Well-maintained vaults typically have <50 broken links. More indicates naming mismatches rather than missing content.
For Outline exports specifically, you may need to convert wikilinks to standard markdown format first. Use the preflight scripts in the preflight-scripts/ folder:
# Navigate to your vault directory
cd /path/to/your/obsidian/vault
# Convert wikilinks to standard markdown (TESTED WITH OUTLINE)
python /path/to/ObsidianExporter/preflight-scripts/convert_wikilinks_final.py
# If something goes wrong, restore original wikilinks
python /path/to/ObsidianExporter/preflight-scripts/restore_wikilinks.py- These scripts have been tested specifically with Outline exports
- Make a backup of your vault before running any conversion scripts
- The converter includes testing functionality - it will show you a preview before making changes
convert_wikilinks_final.pyconverts[[wikilinks]]to[standard markdown links](file.md)restore_wikilinks.pycan restore malformed conversions if needed
When to use preflight scripts:
- If Outline import doesn't handle wikilinks properly after export
- If you experience linking issues in the imported Outline documents
- Only use if the standard export process doesn't work for your use case
- Python 3.11+
- Valid Obsidian vault (contains
.obsidianfolder) - Target application (AppFlowy, Notion, or Outline) for import
python -m pytestUses hexagonal architecture with dependency injection:
- Domain: Core business logic (vault analysis, content transformation)
- Infrastructure: File system, parsers, package generation
- Application: Use cases orchestrating the conversion pipeline
- CLI: Command-line interface
MIT