[{"data":1,"prerenderedAt":192},["ShallowReactive",2],{"project-\u002Fprojects\u002Fmivory":3},{"id":4,"title":5,"body":6,"description":178,"draft":179,"extension":180,"meta":181,"navigation":182,"path":183,"projectUrl":184,"pubDate":185,"repoUrl":186,"seo":187,"stem":188,"tags":189,"thumbnail":190,"updatedDate":186,"__hash__":191},"projects\u002Fprojects\u002Fmivory.md","Mivory",{"type":7,"value":8,"toc":167},"minimark",[9,13,16,33,38,41,44,47,51,54,57,79,82,86,89,92,95,99,107,114,117,125,128,131,135,138,141,144,148,151,154,157,161,164],[10,11,12],"p",{},"Mivory is a personal link library I built to solve a problem that sounds small until it becomes daily friction: we save useful links everywhere, then lose them across browser tabs, social feeds, chat messages, notes, and app-specific bookmarks.",[10,14,15],{},"The goal was not to build another place to dump URLs. I wanted Mivory to feel like an inbox for the internet: fast enough to capture a link from wherever I found it, structured enough to organize later, and smart enough to help me rediscover something even when I did not remember the exact title.",[10,17,18,19,26,27,32],{},"Mivory is available on the ",[20,21,25],"a",{"href":22,"rel":23},"https:\u002F\u002Fapps.apple.com\u002Fapp\u002Fid6741949955",[24],"nofollow","App Store"," and the ",[20,28,31],{"href":29,"rel":30},"https:\u002F\u002Fplay.google.com\u002Fstore\u002Fapps\u002Fdetails?id=com.mivory.app",[24],"Google Play Store",".",[34,35,37],"h2",{"id":36},"the-problem","The Problem",[10,39,40],{},"Most bookmarking workflows break at the moment they should be easiest.",[10,42,43],{},"If I find something useful on my phone, I do not want to open a separate app, copy the URL, paste it into a form, choose a folder, and clean up the title. If I find something in the browser, I do not want it buried in a browser-specific bookmark tree that I never search. If I save links for a project, I want other people to be able to access that collection without turning it into a document maintenance chore.",[10,45,46],{},"Mivory started from that observation: the capture step has to be nearly invisible, and the retrieval step has to be better than scrolling through a long list.",[34,48,50],{"id":49},"what-i-built","What I Built",[10,52,53],{},"Mivory is a full-stack application with a web app, a browser extension, and mobile support through Capacitor.",[10,55,56],{},"The product centers around a few simple concepts:",[58,59,60,64,67,70,73,76],"ul",{},[61,62,63],"li",{},"An inbox for links that have not been organized yet.",[61,65,66],{},"Collections for grouping links by topic, project, or use case.",[61,68,69],{},"A share-sheet workflow for saving links from mobile apps.",[61,71,72],{},"A browser extension for saving links from the desktop web.",[61,74,75],{},"Collaborative collections with invitations, roles, and members.",[61,77,78],{},"Search that combines exact text matching with semantic retrieval.",[10,80,81],{},"From a user's perspective, the main workflow is straightforward: find a link, share it to Mivory, let the app extract the useful metadata, then move it into the right collection when needed.",[34,83,85],{"id":84},"product-details","Product Details",[10,87,88],{},"The mobile experience was an important part of the project. A lot of links worth saving do not come from traditional websites anymore. They come from apps like Instagram, TikTok, YouTube, Reddit, or whatever else happens to be open at the time.",[10,90,91],{},"That pushed the app toward native-feeling details: share target support, safe areas, pull-to-refresh, haptics, keyboard handling, onboarding for the iOS share sheet, and small interactions that make the app feel less like a web page wrapped in a mobile shell.",[10,93,94],{},"The browser extension fills the same role on desktop. It gives Mivory a low-friction capture path from the web without forcing the user to switch context.",[34,96,98],{"id":97},"the-search-layer","The Search Layer",[10,100,101,102,106],{},"The most interesting technical part of Mivory is the ",[103,104,105],"strong",{},"search engine",", because the toughest part of bookmarking apps has always been the retrieval part.",[10,108,109,110],{},"That's why from the very beginning, I've been building the app with this goal in mind: ",[111,112,113],"em",{},"\"How good can a search engine get?\"",[10,115,116],{},"Mivory indexes bookmarks with two complementary approaches:",[58,118,119,122],{},[61,120,121],{},"PostgreSQL full-text search for precise keyword matching.",[61,123,124],{},"Vector search for semantic similarity, so results can match the meaning of a query even when the exact words differ.",[10,126,127],{},"When a bookmark is created, the app extracts metadata from the page, stores the title, description, site name, domain, image, and every other context it can find, then indexes the bookmark for search. The database uses full-text indexes and vector indexes so search remains fast as collections grow.",[10,129,130],{},"I also added AI-generated keywords and language detection to make the full-text index more useful.\nThe point is not to make the app feel like an AI product.\nThe point is to make it seemless to retrieve saved links later.",[34,132,134],{"id":133},"architecture","Architecture",[10,136,137],{},"The project is organized as a monorepo with shared packages for the web app, browser extension, API, and common types.",[10,139,140],{},"The stack includes Nuxt, TypeScript, oRPC, TanStack Query, Drizzle, PostgreSQL, Better Auth, WXT for the browser extension, and Capacitor for mobile builds.\nThe API handles authentication, bookmark creation, metadata extraction, collection permissions, collaboration, search, rate limiting, and safety checks.",[10,142,143],{},"I liked this architecture because it lets all the different clients share the same domain model and API contracts.\nThe web app, mobile app, and extension are different entry points into the same underlying system.\nIt has made the development process of this many sub-projects much easier for a solo dev like me.",[34,145,147],{"id":146},"what-this-project-demonstrates","What This Project Demonstrates",[10,149,150],{},"Mivory was a useful project because it forced me to work across the entire product stack.",[10,152,153],{},"It includes user-facing product decisions, mobile interaction details, browser-extension development, authentication, database modeling, role-based permissions, API design, search infrastructure, metadata extraction, analytics, and deployment concerns.",[10,155,156],{},"It also reflects the kind of engineering work I enjoy most: taking a common everyday frustration, reducing it to a simple product model, then building the infrastructure needed to make that model feel effortless.",[34,158,160],{"id":159},"next-steps","Next Steps",[10,162,163],{},"The next improvements I would focus on are better collection-level discovery, richer previews for different kinds of media, and more ways to turn saved links into something useful.",[10,165,166],{},"My vision would stay the same: Mivory should be a quiet, reliable place to save the internet you actually want to remember.",{"title":168,"searchDepth":169,"depth":169,"links":170},"",2,[171,172,173,174,175,176,177],{"id":36,"depth":169,"text":37},{"id":49,"depth":169,"text":50},{"id":84,"depth":169,"text":85},{"id":97,"depth":169,"text":98},{"id":133,"depth":169,"text":134},{"id":146,"depth":169,"text":147},{"id":159,"depth":169,"text":160},"A cross-platform personal link library for saving, organizing, and rediscovering web content.",false,"md",{},true,"\u002Fprojects\u002Fmivory","https:\u002F\u002Fmivory.app","2025-01-11",null,{"title":5,"description":178},"projects\u002Fmivory",[],"\u002Fprojects\u002Fmivory-cover.png","73mrH4749RFa1_s7I2rnENPRLnOMSEaWso-X1tiFpt0",1780855215469]