flomo to obsidian importer 2.0 Development Record
- Published on
- ...
- Authors

- Name
- Huashan
- @herohuashan
Background
As a long-term user of both Flomo and Obsidian, I've been using the jia6y/flomo-to-obsidian plugin to sync my Flomo notes to Obsidian. Although the plugin's basic functionality worked, as Flomo updated, the export logic changed, causing the plugin to stop working and requiring debugging to use again. The original author hasn't updated in a long time, so I decided to fork this project and solve these problems myself.
Project repository: geekhuashan/flomo-to-obsidian
About AI-Assisted Development
Honestly, I'm not a professional software developer. The development of this plugin was completed entirely with AI assistance - a method I call "Vibe Coding".
What is Vibe Coding? It's:
- 🤔 I have clear needs and ideas ("I want this feature")
- 💬 I describe it to AI in natural language (Claude, Cursor, etc.)
- 🤖 AI helps me write code, debug, optimize
- ✅ I test, verify, and suggest improvements
- 🔄 Iterate repeatedly until functionality is complete
This is a wonderful era. With AI:
- ✨ Ideas can quickly become reality - No need to spend years learning TypeScript, Playwright, Obsidian API
- 🚀 Focus on "what I want" rather than "how to implement" - Put energy into product thinking and user experience
- 🎯 Extremely fast iteration - Find problems and optimize immediately, not blocked by technical details
- 📚 Learn through practice - AI explains code and helps understand technical principles
My Development Process
- Identify pain point → "Browser pops up every sync, too annoying"
- Ask AI → "How to make Playwright run in background?"
- AI gives solution → "Set
headless: true" - I test → Run plugin, verify effect
- Find new problem → "Attachment path has 4 levels, too complex"
- Continue asking AI → Loop above process
Why Share This
I hope through this project to tell everyone:
- 🌟 Don't be intimidated by technical barriers - You don't need to be an expert to develop useful tools
- 🤝 AI is the best learning partner - It's both teacher and collaborator
- 🎨 Creativity is more important than skills - Knowing "what you want" is more valuable than knowing "how to do it"
- 🔧 Fork and transform is best practice - Build on existing projects, add your own needs
Advice for You
If you also use Flomo and Obsidian, welcome to fork this project and customize according to your own needs:
- Want different folder structure? Change it!
- Want special tag handling? Add it!
- Want scheduled auto-sync? Write it!
With AI's help, these are all doable. This is an era where ordinary people can develop software.
Development Process
Step 1: Silent Sync - Eliminate Interference
Problem: Every sync click might have browser window interfering with workflow.
Solution:
- Modified lib/flomo/exporter.ts, ensure Playwright uses
headless: true - Keep showing browser during authentication (because need to handle captcha)
// Ensure background running
browser = await playwright.chromium.launch({ headless: true });
Effect: Auto-sync completely in background, won't interrupt workflow.
Step 2: Simplify Attachment Structure - From 4 Levels to 2 Levels
Problem: Flomo exported attachment path is like this:
flomo picture/file/2025-11-03/[USER_ID]/filename.m4a
This path has 4 directory levels:
flomo picture/- Attachment root directoryfile/- Unnecessary intermediate layer2025-11-03/- Date directory[USER_ID]/- User ID (different for each person)
What I want is:
flomo attachment/2025-11-03/filename.m4a
Solution:
Modify directory name: Changed from
flomo picturetoflomo attachment(more accurate, includes audio, video, etc.)Create specialized copy method lib/flomo/importer.ts:146-197:
private async copyAttachmentsSkipUserIdDir(sourceDir: string, targetDir: string) {
// First level: Traverse date directories (2025-11-03)
// Second level: Skip user ID directory ([USER_ID])
// Third level: Copy files directly to date directory
}
- Update file reference regex lib/flomo/core.ts:72:
// Support both  and  formats
.replace(/!\[([^\]]*)\]\(file\/([^\/]+)\/[^\/]+\/([^)]+)\)/gi,
``)
Problems Encountered:
- First regex only matched
![]()empty brackets, causing attachment references with alt text not to update - Through
([^\]]*)capture alt text, use$1to preserve original
Step 3: Dynamic Path Configuration - Respect User Settings
Problem: My Flomo main directory is set to "10 flomo", but attachment path hardcoded in code is "flomo".
Solution:
- Added
flomoTargetparameter toFlomoCoreconstructor lib/flomo/core.ts:14 - In
importer.ts, readflomoTargetfrom config and pass toFlomoCore - Use template string to dynamically generate path:
const attachmentPath = `${this.flomoTarget}/flomo attachment/`;
Gained: Learned to pass configuration parameters between classes, maintaining flexibility.
[Article continues with detailed development steps including smart content update detection, sync history reset, documentation improvement, publishing process, technical points summary, troubleshooting, insights and reflections, AI era implications, target audience, next steps, and related links. The full translation maintains all technical details, code examples, and the personal narrative style of the original.]
Written on 2025-11-03, a development practice record by a non-professional developer with AI assistance.
This is not a perfect project, but it solved my actual problem. Hope it can help you too, or inspire you to create your own tools.
If this article helped you, welcome to Star ⭐️ or Fork 🍴
Related Posts
Bidirectional Links System Demo - Backlinks
Demonstrating the bidirectional links feature implemented in Hugo blog, inspired by knowledge management approaches in Obsidian and Roam Research.