[{"data":1,"prerenderedAt":866},["ShallowReactive",2],{"blog-dev":3},[4,372,554,634],{"id":5,"title":6,"authorKey":7,"body":8,"category":352,"date":353,"dateFormatted":354,"description":355,"extension":356,"icon":357,"iconColor":357,"imagePath":358,"keywords":359,"meta":363,"navigation":364,"path":365,"readingTime":366,"relatedArticles":367,"seo":369,"stem":370,"__hash__":371},"blog/blog/migration-to-postgres.md","Scaling Capacities: Why we swapped Dgraph for PostgreSQL","luis",{"type":9,"value":10,"toc":334},"minimark",[11,15,41,50,54,61,64,82,89,93,96,101,104,107,127,130,150,154,165,190,194,201,205,208,238,242,265,277,283,286,289,293,296,307,311],[12,13,6],"h2",{"id":14},"scaling-capacities-why-we-swapped-dgraph-for-postgresql",[16,17,18,19,23,24,31,32,40],"p",{},"When building a ",[20,21,22],"em",{},"tool for thought"," like ",[25,26,30],"a",{"href":27,"rel":28},"https://capacities.io/",[29],"nofollow","Capacities",", the data model is the product. Our users literally create webs of connected notes, so choosing a graph database initially felt like the most authentic architectural decision to the founders. ",[25,33,36],{"href":34,"rel":35},"https://docs.dgraph.io/",[29],[37,38,39],"strong",{},"Dgraph"," was chosen because it promised native graph traversal and a schema that matched the user's mental model, it made it easy to move fast and express queries in a way that closely matched how we think about data.",[16,42,43,44,49],{},"However, as time went on, they realized that the \"perfect\" theoretical fit was becoming an operational nightmare and with the release of ",[25,45,48],{"href":46,"rel":47},"https://capacities.io/whats-new/release-45",[29],"Full Offline Mode",", Capacities was much less reliant on having a graph architecture on the backend. After joining the team, making a switch to a more efficient database became my first project as the new backend engineer.",[12,51,53],{"id":52},"the-problem-the-graph-tax","The Problem: The Graph Tax",[16,55,56,57,60],{},"Our primary challenge wasn't functionality, it was ",[37,58,59],{},"CPU consumption",". Dgraph’s resource usage was unpredictably high, even with modest datasets. We found ourselves at a crossroads: horizontally scale a complex cluster (without the traffic to justify it) or vertically scale our servers to much more expensive machines.",[16,62,63],{},"We weren't alone. Community reports confirmed our suspicions:",[65,66,67,75],"ul",{},[68,69,70],"li",{},[25,71,74],{"href":72,"rel":73},"https://github.com/dgraph-io/dgraph/issues/1938",[29],"Dgraph Issue #1938: High CPU usage",[68,76,77],{},[25,78,81],{"href":79,"rel":80},"https://discuss.dgraph.io/t/one-node-in-dgraph-cluster-showing-unusual-resource-usage/19832",[29],"Unusual resource usage discussions",[16,83,84,85,88],{},"After doing some research and having many discussions, we finally decided it was time to move to something \"boring\" and reliable: ",[37,86,87],{},"PostgreSQL on a cloud provider",".",[12,90,92],{"id":91},"redesigning-the-graph-in-a-relational-postgresql-database","Redesigning the Graph in a Relational PostgreSQL Database",[16,94,95],{},"Migrating from a loosely enforced graph schema to a strictly typed relational database is a massive normalization challenge. I worked closely with Steffen, our founder, to audit every assumption I had about the data. The migration wasn't just a data transfer; it was a complete structural redesign.\nMy first task was to deconstruct our Dgraph schema. We needed to translate \"nodes and edges\" into a performant relational model.",[97,98,100],"h3",{"id":99},"the-links-and-notes-schema","The \"Links\" and \"Notes\" Schema",[16,102,103],{},"The main challenge was normalization. Dgraph’s data model is inherently denormalized, but to take full advantage of PostgreSQL we had to redesign our schema around normalization principles. This forced us to rethink how we modeled data and to carefully review every backend query, ensuring we weren’t merely trading CPU bottlenecks in a graph database for greater response times in a relational system due to slow joins.",[16,105,106],{},"We eventually landed on a clean, highly indexed structure where tables could be categorized as:",[65,108,109,119],{},[68,110,111,118],{},[37,112,113,117],{},[114,115,116],"code",{},"objects"," tables",": Contains the core nodes and their properties.",[68,120,121,126],{},[37,122,123,117],{},[114,124,125],{},"links",": A dedicated table representing the edges (from node A to node B).",[16,128,129],{},"To safely replace the engine while the car was moving, we followed a three-step technical strategy:",[65,131,132,138,144],{},[68,133,134,137],{},[37,135,136],{},"The DatabaseService Interface",": We wrote an abstracted interface in our backend. This allowed us to rewrite Dgraph interactions in one place and provided a roadmap of every query we needed to port.",[68,139,140,143],{},[37,141,142],{},"Choosing Kysely to interact with Postgres",": It gave us the best of both worlds, strong TypeScript typing and the freedom to write raw-like SQL for complex traversals.",[68,145,146,149],{},[37,147,148],{},"Recursive Power",": Traversing connected notes in SQL is no small feat. We utilized WITH RECURSIVE Common Table Expressions (CTEs), heavily testing them with EXPLAIN ANALYZE to optimize our indexing strategy.",[12,151,153],{"id":152},"tooling-why-kysely","Tooling: Why Kysely?",[16,155,156,157,164],{},"We spent significant time evaluating ORMs and different alternatives. We ultimately chose ",[25,158,161],{"href":159,"rel":160},"https://kysely.dev/",[29],[37,162,163],{},"Kysely"," for three reasons:",[166,167,168,174,180],"ol",{},[68,169,170,173],{},[37,171,172],{},"Type safety",": It provides end-to-end type safety without a heavy runtime overhead.",[68,175,176,179],{},[37,177,178],{},"Raw SQL control",": Unlike traditional ORMs that hide the SQL, Kysely feels like writing raw SQL without losing strong typing.",[68,181,182,185,186,189],{},[37,183,184],{},"Compatibility with complex queries",": Our most critical queries, which traversed the graph, required the use of ",[114,187,188],{},"WITH RECURSIVE"," and good column indexing.",[97,191,193],{"id":192},"optimizing-with-explain-analyze","Optimizing with EXPLAIN ANALYZE",[16,195,196,197,200],{},"The recursive logic was the core of the new system. We spent days running ",[114,198,199],{},"EXPLAIN ANALYZE"," on our queries to determine the perfect indexing strategy. Kysely’s migration tool made it incredibly simple to iterate on these indexes as we discovered bottlenecks in our local Docker environments.",[12,202,204],{"id":203},"the-zero-downtime-rollout","The Zero-Downtime Rollout",[16,206,207],{},"We couldn't just turn off the lights. We followed a rigorous rollout plan:",[166,209,210,216,222,228],{},[68,211,212,215],{},[37,213,214],{},"Double Writing",": We modified our backend to write every change to both Dgraph and RDS.",[68,217,218,221],{},[37,219,220],{},"Consistency testing:"," During local and staging testing, we compared read results from both databases to ensure consistency in our queries.",[68,223,224,227],{},[37,225,226],{},"The Two-Week Migration",": We ran a background job that slowly moved historical data from Dgraph to Postgres. This took two weeks to ensure we didn't overwhelm the production instance.",[68,229,230,233,234,237],{},[37,231,232],{},"Feature Flags",": Using a flag system, we toggled individual ",[114,235,236],{},"DatabaseService"," modules from Dgraph to Postgres one by one. This allowed us to monitor real-world performance for specific queries and \"roll back\" instantly if we saw a spike.",[12,239,241],{"id":240},"the-dirty-data-challenge","The \"Dirty\" Data Challenge",[16,243,244,245,248,249,252,253,256,257,260,261,264],{},"When we moved to staging on RDS, we hit a wall: ",[37,246,247],{},"Legacy Data.","\nA few years ago, Capacities used string literals like ",[114,250,251],{},"\"default\"",", ",[114,254,255],{},"\"root\"",", or ",[114,258,259],{},"\"basic\""," where we now expected UUIDs. We wanted to keep our Postgres columns as strictly typed ",[114,262,263],{},"UUID"," types for performance, but we couldn't just delete old user data.",[16,266,267,270,271,276],{},[37,268,269],{},"The Solution:"," We built a custom ",[37,272,273],{},[114,274,275],{},"QueryBuilder"," module on top of Kysely. It included a literal mapper that swapped these legacy strings for \"fake\" but consistent UUID values. To ensure this was safe, we ran a background job on production to extract all unique legacy values and verify the set was small enough to map manually.",[16,278,279,280],{},"After this, we thought we were in the clear until we started the background migration job. Suddenly, the logs were filled with errors: ",[114,281,282],{},"invalid byte sequence for encoding \"UTF8\".",[16,284,285],{},"Dgraph, written in Go, was surprisingly permissive with what it stored. It had allowed \"broken\" Unicode values, null bytes, and certain malformed emoji sequences to sit in the database for years. PostgreSQL, however, is a strict guardian of data integrity. It rejected these values outright.",[16,287,288],{},"We had to build a sanitization layer into our migration script to strip out these \"ghost\" characters and fix malformed UTF-8 sequences, including broken emoji encodings on the fly. It was a stark reminder that moving data isn't just about moving bits; it's about translating between two different philosophies of data validation.",[12,290,292],{"id":291},"the-results-110th-of-the-cost","The Results: 1/10th of the Cost",[16,294,295],{},"The impact was immediate and dramatic. As we toggled each module, we watched the server CPU metrics drop.",[16,297,298,299,302,303,306],{},"By moving to Postgres, we were able to reduce our database costs to ",[37,300,301],{},"1/10th"," of their original price. This meant ",[37,304,305],{},"70% annual savings on overall infrastructure"," costs.",[97,308,310],{"id":309},"key-learnings","Key Learnings",[65,312,313,319,328],{},[68,314,315,318],{},[37,316,317],{},"Boring is Beautiful",": Postgres has decades of community support, documentation, and tooling. When things go wrong, the answer is usually one Google search away. Postgres can also be highly optimized for a wider range of use cases than other database technologies, so it made us feel safer because we could prototype different implementations and compare metrics without completely switching to another technology.",[68,320,321,324,325,327],{},[37,322,323],{},"Interfaces are your friend",": The ",[114,326,236],{}," abstraction was incredibly helpful for us to gather all calls of Dgraph throughout the codebase and understand exactly what functionality needed to be provided by a new PostgresService module. At Capacities we’re big fans of dependency injections, and this was just one more example where it proved tremendously useful.",[68,329,330,333],{},[37,331,332],{},"Managed Services > Self-Hosting",": For a small team, the \"premium\" of a managed database instance is a bargain compared to the engineering hours spent managing self-hosted Dgraph clusters. Capacities is not a database company, the focus is better spent innovating in knowledge work instead of in managing infrastructure.",{"title":335,"searchDepth":336,"depth":336,"links":337},"",2,[338,339,340,344,347,348,349],{"id":14,"depth":336,"text":6},{"id":52,"depth":336,"text":53},{"id":91,"depth":336,"text":92,"children":341},[342],{"id":99,"depth":343,"text":100},3,{"id":152,"depth":336,"text":153,"children":345},[346],{"id":192,"depth":343,"text":193},{"id":203,"depth":336,"text":204},{"id":240,"depth":336,"text":241},{"id":291,"depth":336,"text":292,"children":350},[351],{"id":309,"depth":343,"text":310},"dev","2026-01-12","Jan 12, 2026","How we achieved a 70% infrastructure cost reduction by migrating from a self-hosted graph database to a managed relational model.","md",null,"/blog/migration-to-postgres.jpg",[360,361,362],"databases","infrastructure","migration",{},true,"/blog/migration-to-postgres","7 min",[368],"building-capacities",{"title":6,"description":355},"blog/migration-to-postgres","kgphIaNQLkaCWAm1Hvs_Ex_4W0CrKP3k5bh_C1JeBNE",{"id":373,"title":374,"authorKey":375,"body":376,"category":352,"date":537,"dateFormatted":538,"description":539,"extension":356,"icon":357,"iconColor":357,"imagePath":540,"keywords":541,"meta":544,"navigation":364,"path":545,"readingTime":546,"relatedArticles":547,"seo":551,"stem":552,"__hash__":553},"blog/blog/cross-platform-approach.md","Our cross-platform approach","michael",{"type":9,"value":377,"toc":528},[378,382,387,390,393,396,400,403,447,450,453,457,460,464,467,470,473,499,503,506,509,512,516,519,522,525],[12,379,381],{"id":380},"going-cross-platform-as-a-small-team","Going Cross-Platform as a Small Team",[16,383,384],{},[20,385,386],{},"Updated September 19, 2024",[16,388,389],{},"We are developing Capacities using web technologies. Since the web is supported across all platforms, this enables us to maintain a single codebase for all our applications. This approach allows us to avoid duplicating code for implementing the same features across various platforms; we simply reuse the same code everywhere, writing customized code only for specific native features and interactions with the operating system, such as accessing the camera.",[16,391,392],{},"The web also offers rapid adoption of new technologies, a vast ecosystem of open-source libraries, and a strong community of developers.",[16,394,395],{},"In summary, web technologies empower a small team like us to operate efficiently and minimize maintenance overhead while supporting multiple platforms.",[12,397,399],{"id":398},"supported-platforms","Supported Platforms",[16,401,402],{},"We currently offer:",[65,404,405,431],{},[68,406,407,408,411,412,252,415,418,419,422,423,426,427,430],{},"A ",[37,409,410],{},"Desktop App"," for ",[37,413,414],{},"Mac",[37,416,417],{},"Windows"," and ",[37,420,421],{},"Linux",". Our ",[37,424,425],{},"web version"," on desktop supports ",[37,428,429],{},"all major browsers"," (we recommend using Chrome for optimal performance).",[68,432,407,433,436,437,418,440,411,443,446],{},[37,434,435],{},"Mobile App"," available in the ",[37,438,439],{},"iOS App Store",[37,441,442],{},"Google Play Store",[37,444,445],{},"Android"," devices. While Capacities can also be accessed on mobile browsers, we highly recommend downloading the app for the best experience.",[16,448,449],{},"Currently, we do not have plans for a version of Capacities for smartwatches or support for spatial computers (such as the Apple Vision Pro), though this may change if this category gains mainstream adoption.",[16,451,452],{},"Soon, Capacities will provide a consistent \"Capacities\" look and feel across desktop, mobile, and tablet platforms.",[12,454,456],{"id":455},"our-strategy-for-each-platform","Our Strategy for Each Platform",[16,458,459],{},"Here are some additional insights into our strategy for different platforms.",[97,461,463],{"id":462},"desktop-the-most-powerful-version-of-capacities","Desktop: The Most Powerful Version of Capacities",[16,465,466],{},"Desktop devices are where Capacities originated, making us fundamentally a desktop-first application. Consequently, the desktop version will likely always offer the most extensive features and advancements compared to other platforms.",[16,468,469],{},"Initially, we launched only the web version of Capacities. We later introduced a dedicated desktop app, which has now surpassed the web version in terms of capabilities.",[16,471,472],{},"There are significant differences between our web and desktop versions. Compared to the web version it offers:",[65,474,475,478,481,484,487,490,493,496],{},[68,476,477],{},"Better offline capabilities",[68,479,480],{},"Better performance (esp. over time)",[68,482,483],{},"Better file and download interactions",[68,485,486],{},"More and better integrations (e.g. apple reminder, Raycast)",[68,488,489],{},"Deeplinking",[68,491,492],{},"In the future:",[68,494,495],{},"Better export capabilities",[68,497,498],{},"Can utilize more and more of the native operating system's features",[97,500,502],{"id":501},"mobile-app-focus-and-trade-offs","Mobile App Focus and Trade-Offs",[16,504,505],{},"When developing the mobile app, we recognized the need to simplify its functionality. Mobile use cases differ from those on desktop devices. Thus, we concentrated on key aspects like daily notes, quick search, browsing, reading notes on the go, and ensuring fast input.",[16,507,508],{},"For some users, access to the AI assistant while on the move can also be an important feature.",[16,510,511],{},"To enhance the mobile experience, we streamlined the app by removing certain features. Our goal is to provide the best experience tailored to the use cases that matter most on each device, rather than striving for complete feature parity.",[97,513,515],{"id":514},"our-approach-for-the-tablet-app","Our Approach for the Tablet App",[16,517,518],{},"The tablet experience lies between that of desktop and mobile phones. Some users depend on their tablets for prolonged sessions and complex workflows. Consequently, the tablet app must be more sophisticated than the mobile version while still being less complex than the desktop version due to the virtual keyboard and smaller form factor.",[520,521],"hr",{},[16,523,524],{},"Over time, based on user feedback, we will continue to enhance mobile and tablet functionalities to maintain a balance and address any gaps users may encounter in their workflows.",[16,526,527],{},"In summary, we aim to leverage the unique strengths and primary use cases of each platform while ensuring an overall balance among them as we evolve.",{"title":335,"searchDepth":336,"depth":336,"links":529},[530,531,532],{"id":380,"depth":336,"text":381},{"id":398,"depth":336,"text":399},{"id":455,"depth":336,"text":456,"children":533},[534,535,536],{"id":462,"depth":343,"text":463},{"id":501,"depth":343,"text":502},{"id":514,"depth":343,"text":515},"2024-08-21","August 21, 2024","Here's how we are developing Capacities into a cross-platform app","/blog/cross-platform.jpg",[542,543],"cross-platform","software development",{},"/blog/cross-platform-approach","4 min",[548,549,550],"why-integrations","why-individuals","why-offline-first",{"title":374,"description":539},"blog/cross-platform-approach","VghpdnOg6KoTdKCmYGs3UqoUolngR74je2HoPlthCf0",{"id":555,"title":556,"authorKey":375,"body":557,"category":352,"date":620,"dateFormatted":621,"description":622,"extension":356,"icon":357,"iconColor":357,"imagePath":623,"keywords":624,"meta":627,"navigation":364,"path":628,"readingTime":629,"relatedArticles":630,"seo":631,"stem":632,"__hash__":633},"blog/blog/how-we-developed-tables.md","How we developed tables in Capacities",{"type":9,"value":558,"toc":616},[559,562,566,569,595,598,602,605,608],[16,560,561],{},"Recently, we launched tables in Capacities. It's a major addition to our app, and we developed the whole feature in just a couple of weeks. I wanted to share a little bit about the process and why we think it's one of the best table implementations in any note-taking app.",[12,563,565],{"id":564},"figuring-out-what-to-build","Figuring out what to build",[16,567,568],{},"From the beginning, we wanted it to stand out from table implementations in other note-taking apps while making no compromise on the UI/UX side of things. So these were our requirements:",[65,570,571,577,583,589],{},[68,572,573,576],{},[37,574,575],{},"A super nice UI/UX:"," keyboard accessibility, many shortcuts, using patterns already familiar to our users.\nMaking them pretty and well-formatted: Supporting a variety of formatting options and styles that allow users to make beautiful and useful",[68,578,579,582],{},[37,580,581],{},"Deep integration into the app:"," part of PDF export, rich-text in table cells, seamless copy and paste, linking to any content from within table cells, saving tables as objects, interaction with the AI assistant, familiar formatting options, export to CSV, reusing UI patterns our users already know, saving important tables as objects. For example, the table in this screenshot was generated by our AI assistant in the app.",[68,584,585,588],{},[37,586,587],{},"A powerful extra feature:"," We added formulas like in Excel to make it stand out from other note-taking apps. It allows for a whole range of new use cases. While this will never replace a tool like excel, it is very useful for doing some calculations and the fly and have them right inside your note-taking app. This also works great as a \"Pro\" feature.",[68,590,591,594],{},[37,592,593],{},"Being versatile:"," Having a flexible data model that is not too rigid and structured. Supporting simple inline tables for layout purposes all the way to tables-as-objects that users can open in full-page and revisit frequently.",[16,596,597],{},"We found that this is a combination that is not present in any other note-taking app and really makes @CapacitiesHQ\nstand out.",[12,599,601],{"id":600},"how-we-built-it","How we built it",[16,603,604],{},"We made the table feature the main project of a new employee. While this sounds risky, it allowed us to go the extra mile because he could spend all his time and effort on this one feature. We could then completely polish it with the input from the rest of the team. This focus gave us an enormous speed.",[16,606,607],{},"Another thing that made us super fast on the development side was reusing as much code and as many concepts as possible that already existed in the code base. This also allowed our new dev to get to know the codebase, use powerful abstractions, and learn by imitating what was already there.",[16,609,610,611,615],{},"Feel free to check out our new ",[25,612,614],{"href":613},"/whats-new/release-35","table implementation"," and let us know what you think!",{"title":335,"searchDepth":336,"depth":336,"links":617},[618,619],{"id":564,"depth":336,"text":565},{"id":600,"depth":336,"text":601},"2024-03-11","Mar 11, 2024","Explaining our process and why we think it's one of the best table implementations in any note-taking app.","/blog/how-we-developed-tables/tables-cover.jpg",[625,626],"Feature development","tables",{},"/blog/how-we-developed-tables","2 min",[368],{"title":556,"description":622},"blog/how-we-developed-tables","7fMYgPlcRfO9nXtEwOP-Tan_98apOd_KgV8I6kjoa_8",{"id":635,"title":636,"authorKey":375,"body":637,"category":352,"date":850,"dateFormatted":851,"description":852,"extension":356,"icon":357,"iconColor":357,"imagePath":853,"keywords":854,"meta":858,"navigation":364,"path":859,"readingTime":629,"relatedArticles":860,"seo":863,"stem":864,"__hash__":865},"blog/blog/redesign.md","Our first redesign",{"type":9,"value":638,"toc":848},[639,642,645,652,657,660,666,669,675,681,685,688,693,699,703,706,710,713,717,720,726,731,737,741,748,753,759,764,768,773,779,784,790,795,801,806,812,814,817,838,841],[16,640,641],{},"User interfaces need to constantly evolve to reflect the product, its feeling and the vision. We did a big redesign in Capacities and want to take you on a journey to explore the reasons behind it.",[16,643,644],{},"The most significant aspect we changed is lifting the content above the rest of the user interface. The content is the center of your work, which is now deeply rooted in the user interface. We don't want to distract our users by treating sidebars and secondary UI elements the same way as the content itself.",[16,646,647],{},[648,649],"img",{"alt":650,"src":651},"New page design","/blog/redesign/page.jpg",[653,654,656],"h4",{"id":655},"your-content-is-the-center-of-everything","Your content is the center of everything.",[16,658,659],{},"We created friendly, rounded-lg corners around the main content panel, set it apart with a small margin and lifted it up with 1) a shadow and 2) by giving the surrounding area a slightly darker background. The effect of this is striking. It subconsciously puts the primary content into the center of you attention and creates a much calmer, more focused working environment.",[16,661,662],{},[648,663],{"alt":664,"src":665},"New database design","/blog/redesign/tweets.jpg",[16,667,668],{},"Screenshot of page in dark mode. Shadows don't really work in dark mode so the contrast with the background is stronger.",[16,670,671],{},[648,672],{"alt":673,"src":674},"New page design in dark mode","/blog/redesign/page_dark.jpg",[16,676,677],{},[648,678],{"alt":679,"src":680},"New database design in dark mode","/blog/redesign/tweets_dark.jpg",[653,682,684],{"id":683},"smooth-rounded-lg-corners-create-a-friendlier-interface-for-thinking","Smooth, rounded-lg corners create a friendlier interface for thinking.",[16,686,687],{},"We did not only add more roundedness to the main content panel but also to several other elements such as dropdown items and cards. This again makes the app friendlier and overall more pleasant to work with.",[16,689,690],{},[20,691,692],{},"Example of our main dropdown to reuse content.",[16,694,695],{},[648,696],{"alt":697,"src":698},"Color code for reuse","/blog/redesign/reuse_color.jpg",[653,700,702],{"id":701},"metaphors-are-still-important-in-ui-design","Metaphors are still important in UI design.",[16,704,705],{},"A paper on a desk is still something many of us feel a deep connection with – and reminds us of deep and focused work. We want to bring the same feeling to our users when they are building and cultivating their knowledge.",[653,707,709],{"id":708},"less-lines-and-separators","Less lines and separators",[16,711,712],{},"We realized that too many lines in our UI were distracting and moved attention away from the actual content. So we tried to remove as many lines as possible and leave them only when they were both visually appealing and contributing to the understanding of the user interface and information architecture.",[653,714,716],{"id":715},"combining-calm-surfaces-with-colorful-accents","Combining calm surfaces with colorful accents.",[16,718,719],{},"We kept our calm, gray surfaces but tried to combine them with more colorful accents in several areas. Examples for this are tags, which initially get a random color.",[16,721,722],{},[648,723],{"alt":724,"src":725},"Tags","/blog/redesign/tags.jpg",[16,727,728],{},[20,729,730],{},"Color accents in dark mode.",[16,732,733],{},[648,734],{"alt":735,"src":736},"Tag page in dark mode","/blog/redesign/tag_dark.jpg",[653,738,740],{"id":739},"colors-should-be-semantic-where-possible","Colors should be semantic where possible",[16,742,743,744,747],{},"Since we don't use to many intense colors in the app, we try to use colors to convey a certain meaning that helps the user understand the user interface better. This is also referred to as ",[37,745,746],{},"semantic coloring",". Below are some examples.",[16,749,750],{},[20,751,752],{},"Creation of new content is color-coded in green.",[16,754,755],{},[648,756],{"alt":757,"src":758},"Color code for add","/blog/redesign/add_color.jpg",[16,760,761],{},[20,762,763],{},"Reuse is color-coded in blue",[16,765,766],{},[648,767],{"alt":697,"src":698},[16,769,770],{},[20,771,772],{},"Color codes are also visible in the hints",[16,774,775],{},[648,776],{"alt":777,"src":778},"Color code also reflected in hints","/blog/redesign/hints_color.jpg",[16,780,781],{},[20,782,783],{},"Delete actions are color-coded in red.",[16,785,786],{},[648,787],{"alt":788,"src":789},"Color code for delete","/blog/redesign/delete_color.jpg",[16,791,792],{},[20,793,794],{},"Color for emojis is violet.",[16,796,797],{},[648,798],{"alt":799,"src":800},"Color code for emoji dropdown","/blog/redesign/emoji_color.jpg",[16,802,803],{},[20,804,805],{},"Adding tags get the color orange.",[16,807,808],{},[648,809],{"alt":810,"src":811},"Color code for tag dropdown","/blog/redesign/tag_color.jpg",[520,813],{},[16,815,816],{},"That's it for this post.",[16,818,819,820,825,826,831,832,837],{},"Stay tuned for another one and make sure to follow ",[25,821,824],{"href":822,"rel":823},"https://twitter.com/capacitiesHQ",[29],"@capacitiesHQ",", my co-founder ",[25,827,830],{"href":828,"rel":829},"https://twitter.com/steffeBle",[29],"@steffeBle"," and me ",[25,833,836],{"href":834,"rel":835},"https://twitter.com/MvHohnhorst",[29],"@MvHohnhorst"," on Twitter.",[16,839,840],{},"And have a look at the new design yourself.",[16,842,843],{},[25,844,847],{"href":845,"rel":846},"https://app.capacities.io/register",[29],"capacities.io",{"title":335,"searchDepth":336,"depth":336,"links":849},[],"2022-04-07","April 7, 2022","User interfaces need to constantly evolve to reflect the product, its feeling and the vision.","/blog/redesign/cover_redesign.png",[855,856,857],"design","UI","UX",{},"/blog/redesign",[861,862],"how-to-create-the-knowledge-base-for-your-life","guide-to-pkm",{"title":636,"description":852},"blog/redesign","7NCKpHB6-Neam_4rfDVT9DI6o_6kw2qsTkW-wxDs1PY",1778484784817]