{"collectionById":{"d4a5b68c-8afd-4bbe-a7ac-e9a8422fedde":{"id":"d4a5b68c-8afd-4bbe-a7ac-e9a8422fedde","name":"Blog Articles","fieldSchemas":[{"id":"402ba26f-8f6d-4f5f-bf20-62e6549f4ad4","name":"Slug","type":"slug","role":"slug"},{"id":"f2ba59b9-49cc-4ec6-9416-bda99d4c8383","name":"Title","type":"plain_text","role":"primary"},{"id":"0b77f83b-c31a-4889-b9b3-9a6d2e41fc86","name":"Author Bio","type":"rich_text"},{"id":"0a981f8a-7dbb-440d-a940-25d9060c9b11","name":"Author Job Title","type":"plain_text"},{"id":"df1c88d1-4bd8-4ecd-9059-463b9589de92","name":"Author Name","type":"plain_text"},{"id":"1f58afa6-2748-4188-b4a4-f1e54e37eca9","name":"Hero Image","type":"image"},{"id":"3084d9ba-ab55-4e5a-931b-b9db3d09105f","name":"Article Content","type":"rich_text"},{"id":"b7712ee6-f9fd-4781-8c5c-e7e10ce8f81e","name":"Publish Date","type":"date"},{"id":"968086fc-8ce8-4202-bae3-2b1f99061b26","name":"Last edited at","type":"date","role":"last_edited_at"},{"id":"df818b00-478e-4e64-ab4d-1b35c2896853","name":"Created at","type":"date","role":"created_at"}],"itemById":{"e893ce81-635b-48b0-bd01-c3f39aa1c453":{"id":"e893ce81-635b-48b0-bd01-c3f39aa1c453","index":"%","collectionId":"d4a5b68c-8afd-4bbe-a7ac-e9a8422fedde","fields":[{"id":"31cd7421-a2aa-4746-b522-d7f585bf078d","value":"iOS Developer","itemId":"e893ce81-635b-48b0-bd01-c3f39aa1c453","fieldSchemaId":"0a981f8a-7dbb-440d-a940-25d9060c9b11"},{"id":"4c78d447-f8da-4c17-8373-db639eef4479","value":"{\"root\":{\"children\":[{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Oleksii is an iOS alchemist at Snapp Mobile 📱✨, turning concepts into beautifully crafted Swift code and smooth, user-friendly interfaces. He’s passionate about shaping mobile experiences that feel effortless and refined. A firm believer in the power of simplicity, he focuses on writing clear, thoughtful code that brings ideas to life without unnecessary complexity.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"root\",\"version\":1}}","itemId":"e893ce81-635b-48b0-bd01-c3f39aa1c453","fieldSchemaId":"0b77f83b-c31a-4889-b9b3-9a6d2e41fc86"},{"id":"99bef35e-1866-4a36-bd54-ac5ec5984e92","value":"Oleksii Kolomiiets","itemId":"e893ce81-635b-48b0-bd01-c3f39aa1c453","fieldSchemaId":"df1c88d1-4bd8-4ecd-9059-463b9589de92"},{"id":"05708bac-7eb1-498c-9a56-742fa5620842","value":"2025-01-27","itemId":"e893ce81-635b-48b0-bd01-c3f39aa1c453","fieldSchemaId":"b7712ee6-f9fd-4781-8c5c-e7e10ce8f81e"},{"id":"92ca8c83-b7a4-456c-b498-37329c69b77b","value":"{\"image\":\"fbb4d97a22c27d4f7c61fdba6dfd8ccd4cbea2c6\",\"imageThumbnail\":\"fec6cdb3856ce4a37fa39db479099ca411dc32e4\",\"originalImageHeight\":720,\"originalImageWidth\":1280,\"altText\":\"\",\"fileName\":\"Image_5.png\"}","itemId":"e893ce81-635b-48b0-bd01-c3f39aa1c453","fieldSchemaId":"1f58afa6-2748-4188-b4a4-f1e54e37eca9"},{"id":"7a76e223-8da1-4834-b4a1-0624d678a5ba","value":"Linting a Swift package with swift-format","itemId":"e893ce81-635b-48b0-bd01-c3f39aa1c453","fieldSchemaId":"f2ba59b9-49cc-4ec6-9416-bda99d4c8383"},{"id":"7a790740-c0be-473c-adc0-e2bd268b2603","value":"linting-a-swift-package-with-swift-format","itemId":"e893ce81-635b-48b0-bd01-c3f39aa1c453","fieldSchemaId":"402ba26f-8f6d-4f5f-bf20-62e6549f4ad4"},{"id":"47169f0a-5374-45e6-8dd8-4f4beb7dc9d9","value":"{\"root\":{\"children\":[{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Linting your code is handy and effective way to keep your team’s code style in shape. Nowadays it’s hard to imagine a project without functionality that alerts developers with warnings or errors about issues in the code. It could be done with a simple script added to build phases. But what can you do when you don’t have one?\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Packages are excluded from this option, but they still need to be maintained. Or at the very least, you’ll feel much better knowing your package code is clean and consistent, and no one can make it messy without receiving a warning.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"This article explains how to enable linting for a package during its build process, using only the built-in \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":16,\"mode\":\"normal\",\"style\":\"\",\"text\":\"swift-format\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" tool — no external libraries required.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Preparation\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h2\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"With Xcode 16, swift-format is included as part of the Xcode toolchain, eliminating the need for external libraries and making Swift file formatting more convenient.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"For more information, refer to the \",\"type\":\"text\",\"version\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Getting swift-format\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"link\",\"version\":1,\"rel\":\"noopener ugc nofollow\",\"target\":\"_blank\",\"title\":null,\"url\":\"https://github.com/swiftlang/swift-format?tab=readme-ov-file#getting-swift-format\"},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" section.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"1. Create a package\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h2\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Launch Xcode and select \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"File \u003e New \u003e Package\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" from the menu.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"8bbc2ae681acfe8ec7b3b8aa525880eeb95c6329\",\"src\":\"https://s3-alpha-sig.figma.com/img/8bbc/2ae6/81acfe8ec7b3b8aa525880eeb95c6329?Expires=1765152000\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=sMtnU4-zaqqWrMrK9uaiUhAAyg44Z5TSyb~cUShP9QI~b2-k~NyXh0d-MNTRGwAh-bbv84eJJ9I2GBjZaBf33C0cWe5yR4Z3rjkcF6zEnqAs1P1y-6eCVpj27z8ThhXEFtBzU2ZvTPhMQSLYqUZUYR7i2s8GWJpNQuyBlNWWZ~cVW8C75GH7-0mZul61LamLsHcoY3eA-eHxyYFQ6SjGHePTKQebOjId-0rI1a1fa7csd8LXSAmQ36RSRM0utzrfTp1jg5hyCROZels53TrwY673K7RLiCr~2SbANEn-Rldjt7zseQ4kfo6L2rplvxXb3fSMz8Y9uUxZFxD2aI1pUw__\",\"altText\":\"\",\"originalImageWidth\":1521,\"originalImageHeight\":1095,\"isFillWidth\":false}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Chose \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Library\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" and add the name to the package.\",\"type\":\"text\",\"version\":1},{\"type\":\"linebreak\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"798980c3d352b1f160f1fbce0f88c03a09d104ac\",\"src\":\"https://s3-alpha-sig.figma.com/img/7989/80c3/d352b1f160f1fbce0f88c03a09d104ac?Expires=1765152000\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=TTBB-CeKHAgys1K6GDVqoWlxzDhJY5wLZdB4bfuYqchAJ4hRVPxt6FCW8guNR~~EcWhCAzHxs69mQJF1Z-ijINerRR8zQgdnZ6d60g8HJ3S5m4ryiycpR-qm0mdkNMCRQui~Fw85TsqFhg4VjxoxbLXKGk1OkmN0-JrBsQVb5sn62M2q8dF0xbbhPhCRStnfP1Iw448PGWZ0WJSL2LznHR3KjvV0akeK95l59LZTWivQUn-IF8uzeNyr9QyngQD9iFws3Lo57fGuwPPRexMIDnwpVqCme243KKWVCX4Pat41CEDf00JOu7ho1ywCtauw0K9bqf8newHcSVem5N2aRw__\",\"altText\":\"\",\"originalImageWidth\":1816,\"originalImageHeight\":790,\"isFillWidth\":false}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"2. Add Plugin\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h2\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Package plugin is:\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h4\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Swift script that can be run as part of your build\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"A package could have plugins as extra, or be all about plugins\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":2},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Package plugins are available only within package\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":3},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"General plugins can be made available to the outside\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":4},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Lets you access development tools on your machine\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":5}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"list\",\"version\":1,\"listType\":\"bullet\",\"start\":1,\"tag\":\"ul\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"More information about package plugins can be found in the \",\"type\":\"text\",\"version\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Meet Swift Package plugins\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"link\",\"version\":1,\"rel\":\"noopener ugc nofollow\",\"target\":\"_blank\",\"title\":null,\"url\":\"https://wwdcnotes.com/documentation/wwdcnotes/wwdc22-110359-meet-swift-package-plugins/\"},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" article.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Start by creating a dedicated folder for all potential plugins, including the one you’re currently working on.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":17,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":17,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Ctrl\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" + click on your package name in Xcode and select “\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"New Folder”\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" or use any other method to create a folder in the root of your project.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":17,\"textStyle\":\"\"},{\"children\":[{\"type\":\"linebreak\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Next, create a folder specifically for your plugin’s logic. Since it will lint the package code using \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":16,\"mode\":\"normal\",\"style\":\"\",\"text\":\"swift-format\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" , the name \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":3,\"mode\":\"normal\",\"style\":\"\",\"text\":\"SwiftFormatPlugin \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"was chosen\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":2,\"mode\":\"normal\",\"style\":\"\",\"text\":\".\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" By the end, the structure would look like this:\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"7b5ad292eafc4e50612c98faaaae2ba174bd7115\",\"src\":\"https://s3-alpha-sig.figma.com/img/7b5a/d292/eafc4e50612c98faaaae2ba174bd7115?Expires=1765152000\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=DThkjuJNPfwUM7fCBxPqPmZm0lOxvbSiTdNIC2ESbkP47Y-GnSztx4QPztONO6r2nWvJBeJDNFyRQpUDM5s5Ft-zjXvg6Z1z~DgYFsEKD9y98fhu8QWkTLOAK9kHBh3lVYgE04kWq6Ae1eHw31AIS2QjgiIg4T0sNZxo4dTYyZhrPbMpI8jdpge~zLGLhZq7XzmuOc~ShYYZSocYZydFeU8R-3u0FyK45IB3oDoveLIZbAcY3F4bFnDk7uKBBBLrzq8hvUN6DKB7flAZIxwfOAbLvAiI24q7lllv1la9XjXg8Is4ARcHpBzxOwrzmCnNYbxdpG~knBZB9loWT8vjag__\",\"altText\":\"\",\"originalImageWidth\":856,\"originalImageHeight\":622,\"isFillWidth\":false}],\"direction\":null,\"format\":\"left\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"left\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Now, let’s add some content to plugin file.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"left\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"left\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"da385df5d37c2891ace8d7da5ba764ca9b65081b\",\"src\":\"https://s3-alpha-sig.figma.com/img/da38/5df5/d37c2891ace8d7da5ba764ca9b65081b?Expires=1765152000\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=UYhyTYaowjoaWaNfLIxGBReP-FvuBsF6IUHndvFsa5vi6eH1vc2FSsHx3zl9UeQiI~qjvlIkUiRHNGFAJyTLQe~Cfjg-X8UPYlloJMUruVhSm4jQBk7iAAe94~Sa05BcI6i5UdsED0iP-ghwZ69KKOAaZlx1NEMzkRWGYmXHf~P~RkhVmWQIJe7Cn3kiWaE0lp2DljIgtG0Dev9oG38IvCBXBUDvVPmI2glPtkDy6PBhC3vnRAQbjk64O2taO9H3C96BIf5cW5AX332cDcCJlRvMqJPu5ioPFBH0xhRMxSA89MPW6OQBFb2-WrzzErdyn1RLSSENV2pio3DFw41ZQw__\",\"altText\":\"\",\"originalImageWidth\":3484,\"originalImageHeight\":1564,\"isFillWidth\":false}],\"direction\":null,\"format\":\"left\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"left\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"The next step is to add plugins to targets using the \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":16,\"mode\":\"normal\",\"style\":\"\",\"text\":\"plugins\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" parameter, as well as to the package’s target plugins.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"left\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"left\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"11f8c3f7a7d9ba15121ece3c8281f583ba6e4d76\",\"src\":\"https://s3-alpha-sig.figma.com/img/11f8/c3f7/a7d9ba15121ece3c8281f583ba6e4d76?Expires=1765152000\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=i~I8KFypvBlWFTflJ-l-xzMkAb4MfhkEcxXubGbvw746x1uEAsAN1Hhk-AoENQAy6geloYNl9kIxbAZa51ZnIm~-TFgltxS4ijnOadRpQoAB2-3NjSl2zBd355we~JG6g1ocH3~A6k98yJ6bw-f2f7xnewPim6LqNNKop-1Mh3fvlmpchiVdDAtusOaNK1qNV6Nyt-DifIH2V8ykNehUgU3SoMSMSe06RS5tRHFSyPe1PdtLOJeMd2uny5BEECRWHEVyHYE6RR7N8fb6T9sewGpAwGRW5lE~OueKlUUEsS-NnVRUQJ9pPUguKYF6Yi0PM9Dre4aNFxQ~eaGK09oJNQ__\",\"altText\":\"\",\"originalImageWidth\":3484,\"originalImageHeight\":1860,\"isFillWidth\":false}],\"direction\":null,\"format\":\"left\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"left\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"At this point, the package should build ✅.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"3. Show Test Warning\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h2\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"To confirm we’re on the right track, let’s add a script that displays a test warning message when the package is built.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"First, create a file called \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":16,\"mode\":\"normal\",\"style\":\"\",\"text\":\"swift-format-lint-script.sh\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" . This file eventually contain all of the linting logic, but for now, let’s just add a test message:\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"4f70801ea25fab5a023ae0f09608d8aff23ef1e4\",\"src\":\"https://s3-alpha-sig.figma.com/img/4f70/801e/a25fab5a023ae0f09608d8aff23ef1e4?Expires=1765152000\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=QKleZjLmg0UzrY3qtyWkJhT3UlvKgYRm7PjkHmBUtfF3OZipF-9-BfQxmuEpgyn4wHntO8vawitL6Ix89cVPhmGI4edGB2Kcg46NOWurg~yHOcKp3EG9yryqxyJ9bvCqbtkoaciuClgAW7D98U66qv95PR~f~XUpthWDVTW95bAPRBP2EpBgTem8Qq8k1xeNeKku2w4xpmthgv3kUWefwM9h4PKiUhKoMS9m742s1hjCXqeegufVWftM59GCAWvc3cwRvL8jCQZnmxFUTcA-ph~1e8qS6u7ILZWwTwIkkda-MtmOSf0hVBrKp4d79wAeWrHAvc2mig2LiKGkbHJ-Zw__\",\"altText\":\"\",\"originalImageWidth\":3484,\"originalImageHeight\":968,\"isFillWidth\":false}],\"direction\":null,\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"According to the documentation on \",\"type\":\"text\",\"version\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Log errors and warnings from your script\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"link\",\"version\":1,\"rel\":\"noopener ugc nofollow\",\"target\":\"_blank\",\"title\":null,\"url\":\"https://developer.apple.com/documentation/xcode/running-custom-scripts-during-a-build#Log-errors-and-warnings-from-your-script\"},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\", if we echo a string formatted like this:\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"29006da3ef93d9127c23ac7e5398afba366a0c32\",\"src\":\"https://s3-alpha-sig.figma.com/img/2900/6da3/ef93d9127c23ac7e5398afba366a0c32?Expires=1765152000\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=Kpb-DO28fv2Yb~jikRF08Ajj7weLrkfkxy6rN6vmg-4D6sL-LussSmJ3fNXMN~lnpfIcbYotnjvqoMVapspM6V26M17oFicQ1W-7kQzqSTPqfL8RqSH964SIlSyY~DU9VG1NkgAEonIeN-hRQQsAubFw~UXOMi5--ax5tNqza4EwzDPTarJ3qQZIN1W1PBhe9pzdyM80Mga0NdcsmPbMm2-jfQxbPJox~jSbOCNPePOEyoekPpiulep5O-AmurWkA~hpqhUEmHKbNQDYFQ~5~urS081gMopDo98teWVYJtJpSiP411b-C9AVH7gHzge-4gP606xlcoZVmnnjSTjJ8A__\",\"altText\":\"\",\"originalImageWidth\":3484,\"originalImageHeight\":820,\"isFillWidth\":false}],\"direction\":null,\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Xcode will recognized it as an error, warning, or note. Great! Now, let’s add a build command to our plugin. \",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"In \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"SwiftFormatPlugin\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" file, just type a dot inside the return array to explore all the available options.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"f17507a49c1ee77386c8d11bde3adf0cb3365ac9\",\"src\":\"https://s3-alpha-sig.figma.com/img/f175/07a4/9c1ee77386c8d11bde3adf0cb3365ac9?Expires=1765152000\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=Gwu81j7w6~yzlkOSHmpaH-UPkQAJBAMcnCKKGNsnBMxnS8MJGD9Nq3tVkrhwiWW3Brr8X6-JkKjKiY19FVC6Mmhp5ZFOXBh9XifkRf5B7j9TYP2uztCCv0-wYQIWgnaqk4bNy~ndyedITZrk6R5Hxuok3rHfUvdsoTuVbwcTaDWoaXi5G1HsWOuUjxLhgiMD4BDzUbphjxEEDtDkLfEmw~7J~5Yp2VZImFiTNGvleBmSYksyK-ZjDV0KL7aq7i1K66HY8FA2KcuZpkkkBZBeeeUROlsRa3racf0eI9e6tEdV~ha1YU1cZhtCbZpO2rkVSX6H0hTfYv0W3R5pxnsuZg__\",\"altText\":\"\",\"originalImageWidth\":1832,\"originalImageHeight\":454,\"isFillWidth\":false}],\"direction\":null,\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Note\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\": When attempting to lint the package with \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":16,\"mode\":\"normal\",\"style\":\"\",\"text\":\"swift-format\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\", the \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":16,\"mode\":\"normal\",\"style\":\"\",\"text\":\".prebuildCommand\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" approach did not work as expected. It resulted in unknown errors, primarily related to incorrect file paths. This might be due to the way swift-format resolves file paths or how the plugin handles the working directory.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":1,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"To address this, we’ll use \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":16,\"mode\":\"normal\",\"style\":\"\",\"text\":\".buildCommand\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" :\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"d729ef868e44769b59eeb4c0c13d8b85f81b53d7\",\"src\":\"https://s3-alpha-sig.figma.com/img/d729/ef86/8e44769b59eeb4c0c13d8b85f81b53d7?Expires=1765152000\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=PtRHrzCmPlxBc2h00n3PSR3Ri~fHgsbaJvomyydK4nOf7eIDzf8THqfz6~lh66oPyF~JrfENtC418uxlYdQMkMdAeOOYMekvEeRaTeuzKXeiDzOOssd8w03BJwaBZpoiu3p-GplXQdNF0pJhykm9RD5UQaFprlkE-OHcoX3pbMQiKRZJwvwYHXz0bRzF~khPNfY2zp5Uw8r0sZMN0-Wq-Jq7unZERR9vni9ABNtjGReng4TB10tJ8RJdE-y6rLdbiStno9x-jef9KHwocgJ6iHIXwHBLM3WIsNUuDeZ~5sQxKdl6JZAhC8HuUheEJTSV7pnsLeUsFOVzaWMfgoLq5A__\",\"altText\":\"\",\"originalImageWidth\":3484,\"originalImageHeight\":2532,\"isFillWidth\":false}],\"direction\":null,\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"To get started, provide the script path in the arguments array. Add a line specifying the path to the script that the plugin will execute.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"left\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"d0a801cab51edb516a2ae8f8ac124820dca48677\",\"src\":\"https://s3-alpha-sig.figma.com/img/d0a8/01ca/b51edb516a2ae8f8ac124820dca48677?Expires=1765152000\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=pzKKiVvKyBbxRHKtxBVlZqRgpYBVFNzlESUhDznbzniToaPLTayvNT9rrzKj3po6MpiBEVv7280c97-KL~q2axmnWbvBnVnacp1BJEUUD7rA4NlnhIMwlptD9OAXh1GgZYppQaMGMM1THkZGkuTQCct7GinGFb2qxF~gWcjIB2gOV9syjt8mu-Uv73c0DWi0dqvhXpk~8K~CTfJG---E1Z5VhSJf8HOFbl01AisURtTzp1~sBUinZTLCw1ddCYcOwqOgefoj7BNfntbWbO~U8bHM5J5iaEzbafuUHOHgnaCNXTuh3tUAtXZ5Nl6B6vQskD019ugdznzChl6t6GuabQ__\",\"altText\":\"\",\"originalImageWidth\":3484,\"originalImageHeight\":1040,\"isFillWidth\":false}],\"direction\":null,\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Once added, the plugin file should look like this:\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"60fa1cc0bee187f25fd9dfda1abb466e312e5413\",\"src\":\"https://s3-alpha-sig.figma.com/img/60fa/1cc0/bee187f25fd9dfda1abb466e312e5413?Expires=1765152000\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=PkaF-ZWezRfL2WdEZ7WFtDb~18cvc0qLwxG79jysbdy0tgCeJwkQ-G0g~1GGx5F6xP5-1J7yf1dCEqDPciLIWlXxQ65nrKi0oqYkQAy~YvFpSzB00iaxzbVi-FCf7qM1uKKlrUb9mSK~TsxmB9li0grtTwl15PP6gxaEqINC8LdTXFjx0V1bNjlLP5UpNEwsyXFvv6KOQ1pNZm~4whIa6kyc5wnJZ7dPjKb~cRLj3w9mNRH7T5dBOr5TqTp8IbUR2jKwMOqxPFWcBrtPjyZd0ZSAZSmfEiRaCy0uI0aspQu1vcSHlF1uRUbRf3bKhL0ddyJsmrHjCgvKNPrFfCiaKA__\",\"altText\":\"\",\"originalImageWidth\":3484,\"originalImageHeight\":2456,\"isFillWidth\":false}],\"direction\":null,\"format\":\"left\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"left\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Now, when the package is built, the warning will be displayed.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"21da05f719cc624e2052de059417657e1864be43\",\"src\":\"https://s3-alpha-sig.figma.com/img/21da/05f7/19cc624e2052de059417657e1864be43?Expires=1765152000\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=dlYxRq95TlYBwZKhMkrmIlMYbsCkH~Xr~ovz5C7-ntRncv0dfdv5OY2qf8Yke9vHTck2hl2raXk~2YBUUxcCJy~ggrznUwLXtinS5Oc4tiRmq9p5eK02n5vo4eaT34Kl3k4sH1TH0Ycc14klactzU0R9eezSNrx2DU84McZFwewXmdCIisLFBAQgbvPoUe8gIL6Y8RbQHlv-i2AZUhUjf4qUbtjHUTZFeap9CADFaL3-BZAm6cFq6DAmPecBbawFGQdBxinlQIi0cay3XY5TkAP32oXCzvq3DlQWE-Uz2v00plcYjnZNzdLST8HSDVa7M6Dko6aTDWwr1lqdGWVpAA__\",\"altText\":\"\",\"originalImageWidth\":1043,\"originalImageHeight\":492,\"isFillWidth\":false}],\"direction\":null,\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Nice! Now we can move on to configuraing \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":16,\"mode\":\"normal\",\"style\":\"\",\"text\":\"swift-format\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\".\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"4. Swift-format configuration\",\"type\":\"text\",\"version\":1},{\"type\":\"linebreak\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h2\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Swift format has default configuration, which can be generated using the \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":16,\"mode\":\"normal\",\"style\":\"\",\"text\":\"dump-comfiguration\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" command. The content of this default configuration can be saved to a specified location with the following terminal command:\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"0a4533fb0f4a9725c69808984576b475b3c98689\",\"src\":\"https://s3-alpha-sig.figma.com/img/0a45/33fb/0f4a9725c69808984576b475b3c98689?Expires=1765152000\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=oiL~~q7f9gUFqcDT8Pwn8zkmkLRJTuSFCnP4yb2GwOmLPh2Lbg67RL1rXX4-inPlX6MsdJXh~HinUEW14QYIyv-U0fnCvIB6Gos36jdhHHA1jLtJDihd7n3PLLL2l8BLAmf9oZe9hGRAXYYvGdIr8cjD4BgKHluAK8jrV-734PYSi-lol3vwv~ymgI5m7meGAhAFDFTzyR3QybO1ntRsRnjh-Yuc3VADwPW-tUiTYl3XXZjeAyremBpf8UiLg-7DNosvdhBpUMHjX-TTaz9z3eM~BUJptC00N~teygQnagXPslGoLuYI1pX8rXY4NymZPJVMMR6LVJCxgUjZMWncwQ__\",\"altText\":\"\",\"originalImageWidth\":3484,\"originalImageHeight\":892,\"isFillWidth\":false}],\"direction\":null,\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Now go to Desktop and open it. For more details, refer to the \",\"type\":\"text\",\"version\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Configuring swift-format\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"link\",\"version\":1,\"rel\":\"noopener ugc nofollow\",\"target\":\"_blank\",\"title\":null,\"url\":\"https://troz.net/post/2024/swift_format/#:~:text=Configuring%20swift%2Dformat-,%23,-The%20swift%2Dformat\"},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" section.\",\"type\":\"text\",\"version\":1},{\"type\":\"linebreak\",\"version\":1},{\"type\":\"linebreak\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"In this example, however, we will use a custom configuration. Let’s specify it in \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":16,\"mode\":\"normal\",\"style\":\"\",\"text\":\".swiftFormat\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" file and place it to the package root directory.\",\"type\":\"text\",\"version\":1},{\"type\":\"linebreak\",\"version\":1},{\"type\":\"linebreak\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"0cd5e2b1484ab0f1376b970af986e94a9b49f8af\",\"src\":\"https://s3-alpha-sig.figma.com/img/0cd5/e2b1/484ab0f1376b970af986e94a9b49f8af?Expires=1765152000\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=cJwqlFjIACyl5DSHnOuKZpvlcqliG6Loi71525-7gysjZEVM1XphvaIGdSImY~asWicenuWDdZ9IbateceizWpWLSH9oZ0BDY-k9a9-QNa9fk6RlQehs0H0rGz4LZP25fJNyxsxl5EaF~hwKtUWy60EEyy5iewtV5wCfqZ85UHe-QBx~aewv73flHflPsluuNnVyg-vC5ldST98~H3AORVj1JYz9j4yQG1pG3bpLgQF7zMceb61wqzBz1x1wP7oQtnMO2-7ahcfsa3duXD~gSGxR1klxgqfxQmfruNTUvlJV4Xll7jS7YqyJ-peZRLl94WYGB9k593MTGRd06g2sew__\",\"altText\":\"\",\"originalImageWidth\":3484,\"originalImageHeight\":1564,\"isFillWidth\":false}],\"direction\":null,\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"The content here is basic and adapted from an \",\"type\":\"text\",\"version\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"example\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"link\",\"version\":1,\"rel\":\"noopener ugc nofollow\",\"target\":\"_blank\",\"title\":null,\"url\":\"https://github.com/swiftlang/swift-format/blob/main/Documentation/Configuration.md#example\"},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\". To extend it, you can explore additional rules described in \",\"type\":\"text\",\"version\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Configuration.md\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"link\",\"version\":1,\"rel\":\"noopener ugc nofollow\",\"target\":\"_blank\",\"title\":null,\"url\":\"https://github.com/swiftlang/swift-format/blob/main/Documentation/Configuration.md#example\"},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" file.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"5. Send Configuration and Package Path\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h2\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Now that we have the configuration and a script where all the magic happens, we need to send the configuration and package path to the script so it knows what and how to lint. This can easily be done by passing them as additional arguments to the arguments array in the \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":16,\"mode\":\"normal\",\"style\":\"\",\"text\":\".buildCommand\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" inside the plugin file:\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"5adfa248b0ef066548db14ea520a644d43036cdc\",\"src\":\"https://s3-alpha-sig.figma.com/img/5adf/a248/b0ef066548db14ea520a644d43036cdc?Expires=1765152000\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=mTU0Y5wqRLweIKd26HsurpNTM8UXyF5NwVBKhNIk26-dW3tv-kNLSbQiBHN8WFT2focgpg~Ug25KQanJcIP4gq~HhCbRB2qvQZ7DNB1mcYuqmROuiInTf4287uovwDqFdYCbNSVxn7wnIdlpoZiYq6VIcNUsoYTTuyXCocJQUogNvcVeBYw0eeuy-yQgqia-FwP4IaH36FtIx1Cvjigzpon~5TCwXAdPbqwDdRl6-kaCkNyF494YKX7jZcr-O-5zcNiT6xSa025f~KIbaCn1qBRzMRf47PchZ29bCH7s6PjsU3nwBd3F0so-lAjBskm4J3VsczGZTPYuudxaQgLMAQ__\",\"altText\":\"\",\"originalImageWidth\":3484,\"originalImageHeight\":2456,\"isFillWidth\":false}],\"direction\":null,\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"To confirm that everything is working as expected, let’s print the paths in the \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Report Navigator\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\". Add the following lines to \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":16,\"mode\":\"normal\",\"style\":\"\",\"text\":\"swift-format-lint-script.sh\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" file:\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"fdb7a1ef794704064a7f61204e8a8beab1e33efa\",\"src\":\"https://s3-alpha-sig.figma.com/img/fdb7/a1ef/794704064a7f61204e8a8beab1e33efa?Expires=1765152000\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=C0UqjrQfyOle2EPUmRdh7eWkgS-IVoTH01XvcnJox6CEVAhzeH3R7Upa9W8yoVYMMlvcPwaB9SwWebSj3BxyWG0RaYQRCriyH6ijUgmZr~nmx7sTZzQtn5Kg30m1eGy7H~guI3qtEiMYzy0~fDLgTlEn7dLBZ5rVdzt0HCGUvgAOUT7EL1i5mnPa0D50pAek54nF1cyVHq-yTsSoTfHSZ~rAnxFsBbTNr7Bvn7JubKXMNnGsplCwdcYo-~EiHt7930QnvNrcGTKbyswzivFQCNdy0TfCyPzpwaM8Lb~J9IFiz77dveWVJd7Huzp0rmqrjZNFEiB0IWAp88yCXGuTXw__\",\"altText\":\"\",\"originalImageWidth\":3484,\"originalImageHeight\":968,\"isFillWidth\":false}],\"direction\":null,\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Build the package and click on the build entry in \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Report Navigator\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\":\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"b99aef25b1fd0986416269aa5f7dd9dadd57f4d5\",\"src\":\"https://s3-alpha-sig.figma.com/img/b99a/ef25/b1fd0986416269aa5f7dd9dadd57f4d5?Expires=1765152000\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=UxwM7gTKaHh-Kkf1~KiGf9cQooCpA9eZEz9Vg-FiltKXkoOtzQhMQNRzUm4MO2MvgKfW05mqauHGoc2FB7uUQV3qHJ~DyP5aXqC9wOlp0VpqUutQ9qYAwWjNaQ5EiSfsCTuNPWn-R3cPac8~PeM5nuZIcCgj2A-eqfVThzxZ9IlHhDIYFyhpDTYvtmCyPooT7TwFflom81yh8LpR8c24RPXaaYVd4uctPndXiv2i5V5laSC5QMJpXNXfryNb-Xjm5r5nNyw3zG5gTCs~pMInYanZvmcP3YQYgSlsrQlEzgHVMohkhqy0zsiFfT8EAfw1UmDQj8KDGZN4XRJoulJM6g__\",\"altText\":\"\",\"originalImageWidth\":883,\"originalImageHeight\":572,\"isFillWidth\":false}],\"direction\":null,\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Here they are:\",\"type\":\"text\",\"version\":1},{\"type\":\"linebreak\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"09e5d4b424ece6bf5455166fc62a062a3b75e88e\",\"src\":\"https://s3-alpha-sig.figma.com/img/09e5/d4b4/24ece6bf5455166fc62a062a3b75e88e?Expires=1765152000\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=KZvlzxUmrw~OVVccSHpeu59kMbdDmFCVY5JEsCm5j2in6TMHoR8Em1rsHj~XXJncsGdrti9QGhCpPv7Vqb2mrrTgNh5Z-GfbgiVTtJaaPVxO0pwiaUfeoptvao3jNkx6D5gcCbbS64BAbZanDfXTm6tSKD~C63Os7GMs3rXEzCCB6oBrhtFZqHN08yDo9XftVaKKtUGCdqY7kzeIv-SRaFiVlR1D8WCAcVgfBxNhLojwwJiSSrM2GkC8u4~H6T4oBYuXEkc5av3UeiiwytpsZ8AfN6A2iXXGgb-tG6OSd4RZh6jtIw0YeV5UlFE9b~s2okntRth2z2zyc2i90WicKw__\",\"altText\":\"\",\"originalImageWidth\":1674,\"originalImageHeight\":190,\"isFillWidth\":false}],\"direction\":null,\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Confirmed. Let’s proceed with \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":16,\"mode\":\"normal\",\"style\":\"\",\"text\":\"swift-format\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\".\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"6. Swift-format lint\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h2\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Now that we have the crucial paths, we can start creating the script to lint the package codebase.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Here are the steps and code that needs to be added to \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":16,\"mode\":\"normal\",\"style\":\"\",\"text\":\"swift-format-lint-script.sh\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" :\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Step 1: Locate the \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":17,\"mode\":\"normal\",\"style\":\"\",\"text\":\"swift-format\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\" Tool\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":1,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":1,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"b148966a70a03eb9a54f61862440ce38149429e3\",\"src\":\"https://s3-alpha-sig.figma.com/img/b148/966a/70a03eb9a54f61862440ce38149429e3?Expires=1765152000\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=mZA3HKQKLhKM7HF5gB5~xQT~ZQ8W6897-2PcWXeSBru0btxRuoP9Jz5jVX9Y-Xr2oGksNjZwO8p5o2BooEMFWCnYKIMQROzHpVCs9C25KDmIE4sqFh7mwpVDxzBKrhFOUiP4kO-OUAhZdBOkTHo~qditK2DRQ2OBhqDzXoQts~OZP8WHXMG4bv-TbQE3XOy8~3ZT7YSACGAgPQ-L1A9PxbrJ1Xjs4HybRDAbXDQ4wonPoeo8mFB4DDBjGp~vOxCh3FLA9AyupHL7PWiDywqGk93FWWnO1qBCEfmA4~XhN7bLikSqoHuYNmTbvQiF0Zf76hqawfM9ltC9eapTzXB7ug__\",\"altText\":\"\",\"originalImageWidth\":3484,\"originalImageHeight\":892,\"isFillWidth\":false}],\"direction\":null,\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":1,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Step 2: Resolve and Validate Paths\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":1,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"cfc301977783aa2fafd99e2cc6c196647ea08391\",\"src\":\"https://s3-alpha-sig.figma.com/img/cfc3/0197/7783aa2fafd99e2cc6c196647ea08391?Expires=1765152000\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=GEW6vzuuSppjtEng~BiNPl6rDgfl1CbjLWKV7ARxAeoLAQltZ~rZBjqX13dcfehR2m5MP3w42AlpYgbbdQbn1mKdaqr2omLgxQ52ljb0qP4ewL8B1NGoilkmlCugoKdl98S5nu1mgevPZ1WeMvr8CVAf67kyQZxRFJ6yb7QWRIWSG-spQB27-70iWCTHIAElCMlV~67AjdXT9dFF4ieAfIHoVFIzJYbswq4suIr9zIqPGcaortLxXP7nQ1aaDHrcPa9pSg6GU8JCThQE09MXTf~QW~6UE4ZSrdckWEb3fe98KJ284JsY0kgH2RVSQn3eS6usUBa85pqIvZ-3LBG9LQ__\",\"altText\":\"\",\"originalImageWidth\":3484,\"originalImageHeight\":892,\"isFillWidth\":false}],\"direction\":null,\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Step 3: Run \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":17,\"mode\":\"normal\",\"style\":\"\",\"text\":\"swift-format lint\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":1,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"2693ad494546f113c89a470b433b3a99d34ba3f8\",\"src\":\"https://s3-alpha-sig.figma.com/img/2693/ad49/4546f113c89a470b433b3a99d34ba3f8?Expires=1765152000\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=VdFLB8w~h7dZ7ZG02yyE~SDZE6IAEkJC9bMR3SN~g3rLj2xFx9XPuE48k~WrZ87xFo0uVDxhrgkatnfJzQIWLIowubNX-MzDI9h3z7BVH6FrKh3i2k2nuMjDOZT1pMarhEp4IirZPm5D3zIMBlJJ5VTfMtbBlJWxWsx3PDu4-q67lDzf48KchuRYhKW-neUgB-NRSmBrfyXAAAqUP4rQ67w~Z9oiKoaIz67LFpy7GgJ2FBkkTCueql7~tDdiUOw07ZzYLKTpWX3JOBVso3mGEmXjMhe~KV5L87RzhGwS5nqiWCVrdpYfLhm4hXakqzFiGAeiNM568VHSC~XGocNJLA__\",\"altText\":\"\",\"originalImageWidth\":3484,\"originalImageHeight\":892,\"isFillWidth\":false}],\"direction\":null,\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Step 4: Process and Format Output for Xcode\",\"type\":\"text\",\"version\":1},{\"type\":\"linebreak\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":1,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"The last but most important step is processing each line of the output and formatting it for Xcode’s error, warning, or note display:\",\"type\":\"text\",\"version\":1},{\"type\":\"linebreak\",\"version\":1},{\"type\":\"linebreak\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"77517fbfe65f223d7c76d12320686e790e06a255\",\"src\":\"https://s3-alpha-sig.figma.com/img/7751/7fbf/e65f223d7c76d12320686e790e06a255?Expires=1765152000\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=d1B5JUEUSEgWSRd5lR-V5Dh~mMTyW7917Qx1kyOgiLf2avt9d7e5VkAvxVVRhmHcgbGxhTSeuN~WH7d1-5W46zSPe3jxFFzog2y9QCSsRdphCjsDiUlW-WaepPoC126URW-MpLTO0Ft9Oo9AfFhrhKAV1AGF15Kha0NmlTWNMd1i5zbDZTJCJtfA6c68GJ3DdiN0OjyAkL~X-NzD0QzLa~xt~amo2efR4VCVEtWdSOaqID4plDnLGstTXWCjeSTU-i04BMUvbSiRpXV4rH4JSfEWzrWss2Zjn30uSteN~nQsMh53A1zHCWslgZ2O69Rl7rdBrm0StY-XY9e2bYm8KQ__\",\"altText\":\"\",\"originalImageWidth\":3484,\"originalImageHeight\":1936,\"isFillWidth\":false}],\"direction\":null,\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"That is it!\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":1,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":1,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Build the package. Since the \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":16,\"mode\":\"normal\",\"style\":\"\",\"text\":\".swiftformat\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" configuration specifies an indentation of 2 spaces(which conflicts whit my Xcode settings of 4 spaces). there will be initially be many warnings.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"0dbf6dac136d691c15ddc7bf061a1eb35c34d006\",\"src\":\"https://s3-alpha-sig.figma.com/img/0dbf/6dac/136d691c15ddc7bf061a1eb35c34d006?Expires=1765152000\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=dix5L4ROGspFXPeM75a-UDumgB~8y7uqFTmZp4VjG1K4bKYlgkzjztBu9708F~W-GPwW9m0uLp23bCbDRu9zksnQIXtdiOBlMj7aq-O~dKwBB96ZH6aX9yP4-wTiEUWP~i~dxmHmy8QZ04TEU4NJCtm-0z4JUHbW12DFL4GV626lYNj018d6NRdVHX6JY99nh7zcBjjXCHaaHVNsb4sAWA2C~XSB4SHmLE51wRwDm1CzQojdhYuW13ggfiqppDhQMj3jP9KiO0dKTi0vjjo8zGQWvJDFPJKrpFRYHm~swUaOmeHOw9TqzSvAgF3Ls~k6FzUAy80wjTr8usXuUZw6UA__\",\"altText\":\"\",\"originalImageWidth\":3356,\"originalImageHeight\":2042,\"isFillWidth\":false}],\"direction\":null,\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"To make the package warning-free:\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h4\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"adjust the indentation settings in \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":16,\"mode\":\"normal\",\"style\":\"\",\"text\":\".swiftformat\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" :\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"list\",\"version\":1,\"listType\":\"bullet\",\"start\":1,\"tag\":\"ul\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"9c303d2f7b5ce3cca6ddb6f05d3987724ea7832d\",\"src\":\"https://s3-alpha-sig.figma.com/img/9c30/3d2f/7b5ce3cca6ddb6f05d3987724ea7832d?Expires=1765152000\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=EabZspMsrzACgCYBBb2LHsNrAjah3CdRestJFJtUGUJeY80~4TvetMOmOMqv-EBRSMmw8WJ~aVbPpp1FDjkjI0GAP43YeIUWO6yNlbcOcXkTdxuHxidsCa1HSUCciy9NUq6urfBKKGdR6GGm~tNG2AY6cQQfnCtcBMpfL3dqwfRwfnvyqN54Yh9lrxMgKBiyMZxtRWjGAlGM32JiNFWE4KySR2LVrTdm~uR5Q7W58GOwJkKpvfv-4REv22oW7key4t6ynuPb3ytynCBJxnSyNT~uHKt1imzszU-197z7LbcyqkylHe5nQLKIoe8yBcFISE~o8wd2Kfjaw9FQVvl3UQ__\",\"altText\":\"\",\"originalImageWidth\":3484,\"originalImageHeight\":1564,\"isFillWidth\":false}],\"direction\":null,\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"add or remove trailing commas where necessary in the codebase.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"list\",\"version\":1,\"listType\":\"bullet\",\"start\":1,\"tag\":\"ul\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"c28a5adfe631bcc251337c1ceb7df4ff202f38df\",\"src\":\"https://s3-alpha-sig.figma.com/img/c28a/5adf/e631bcc251337c1ceb7df4ff202f38df?Expires=1765152000\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=OqbQV2g-4lEWrAp1G1wsoTfOhHpSOIvlmxtZXEloNHLwFVGmZlp1VPaBQvLx5GQ2OmJgpMuCUcfmHldgeo1txcc2p6lai6Z50ulIlOdh61KwQBPHtUUxKFDqOiCXrxKaIXc6UConbutfNxPXjrcLaNcwMr8UMOOn9wq-o7BwmAYcZYIzFPXAULY~C-eLOS9ac4UXn1w2s8uxjC8GG~Hrr~9jMN1owYN4JYQQ2fpIeguLdRIX5f3~uCzGYBv0f1D5PXZLT0TFFomxtTU1lhtJSKzckA4ohyESocHdRccUb9n86QvnMR3JlCEH3XaxXlxUbZLC6kJ~NsHyt08tK186QA__\",\"altText\":\"\",\"originalImageWidth\":2554,\"originalImageHeight\":154,\"isFillWidth\":false}],\"direction\":null,\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"After these changes, the package codebase will be \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"warning-free\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\". Beautiful!\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Summary\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h2\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"In this article, we explored how to integrate \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"swift-format\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" into a Swift Package for automated code linting using Swift Package Plugins. The example package demonstrates a streamlined approach to enforce code style and detect formatting issues directly within your development workflow.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"By creating a custom Build Tool Plugin, we utilized swift-format to lint the package’s codebase, outputting results in an Xcode-compatible format for better visibility. The article also highlighted how to structure a plugin, resolve script paths, and handle configuration files effectively.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"This solution not only simplifies maintaining consistent code style but also enhances team collaboration and productivity. With \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"swift-format\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" and package plugins, you can ensure your codebase stays clean, organized, and easier to maintain across projects.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"The code for this example is on GitHub at \",\"type\":\"text\",\"version\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"oleksiikolomiiets/SwiftFormatWithPlugin\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"link\",\"version\":1,\"rel\":\"noopener ugc nofollow\",\"target\":\"_blank\",\"title\":null,\"url\":\"https://github.com/oleksiikolomiietssnapp/SwiftFormatWithPlugin/tree/main\"},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\". Feel free to contribute, explore, or stop by to check it out!\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"References\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h2\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"“Getting Started with Plugins” \",\"type\":\"text\",\"version\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Plugins.md\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"link\",\"version\":1,\"rel\":\"noopener ugc nofollow\",\"target\":\"_blank\",\"title\":null,\"url\":\"https://github.com/swiftlang/swift-package-manager/blob/main/Documentation/Plugins.md\"}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"“\",\"type\":\"text\",\"version\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Swift Format in Xcode\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"link\",\"version\":1,\"rel\":\"noopener ugc nofollow\",\"target\":\"_blank\",\"title\":null,\"url\":\"https://troz.net/post/2024/swift_format/\"},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"”\",\"type\":\"text\",\"version\":1}],\"direction\":null,\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":2},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"“Meet Swift Package Plugins” \",\"type\":\"text\",\"version\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"WWDC22 session\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"link\",\"version\":1,\"rel\":\"noopener ugc nofollow\",\"target\":\"_blank\",\"title\":null,\"url\":\"https://developer.apple.com/videos/play/wwdc2022-110359\"}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":3},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"“Create Swift Package Pugins” \",\"type\":\"text\",\"version\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"WWDC22 session\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"link\",\"version\":1,\"rel\":\"noopener ugc nofollow\",\"target\":\"_blank\",\"title\":null,\"url\":\"https://developer.apple.com/videos/play/wwdc2022-110401\"}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":4},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"“swift-format” \",\"type\":\"text\",\"version\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"README.md\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"link\",\"version\":1,\"rel\":\"noopener ugc nofollow\",\"target\":\"_blank\",\"title\":null,\"url\":\"https://github.com/swiftlang/swift-format\"}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":5}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"list\",\"version\":1,\"listType\":\"bullet\",\"start\":1,\"tag\":\"ul\"}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"root\",\"version\":1}}","itemId":"e893ce81-635b-48b0-bd01-c3f39aa1c453","fieldSchemaId":"3084d9ba-ab55-4e5a-931b-b9db3d09105f"}]},"54d55d03-8f64-4a4e-94a6-397cf873c405":{"id":"54d55d03-8f64-4a4e-94a6-397cf873c405","index":"#","collectionId":"d4a5b68c-8afd-4bbe-a7ac-e9a8422fedde","fields":[{"id":"16bbb7f7-edf9-4282-972c-00c300cd3f10","value":"Jasper Morgan","itemId":"54d55d03-8f64-4a4e-94a6-397cf873c405","fieldSchemaId":"df1c88d1-4bd8-4ecd-9059-463b9589de92"},{"id":"0f1f5f3a-ba88-494c-ae21-e998dde5dfd9","value":"CEO, Snapp Mobile","itemId":"54d55d03-8f64-4a4e-94a6-397cf873c405","fieldSchemaId":"0a981f8a-7dbb-440d-a940-25d9060c9b11"},{"id":"42384c49-64bc-4549-86e3-c3f8554f8700","value":"{\"image\":\"2179fbfa3f2ff517306458b93fd9bc516cbb97c2\",\"imageThumbnail\":\"5afeeaf981c96b5edcb23f9065403791ced4dc59\",\"originalImageHeight\":652,\"originalImageWidth\":1326,\"altText\":\"\",\"fileName\":\"Image_3.png\"}","itemId":"54d55d03-8f64-4a4e-94a6-397cf873c405","fieldSchemaId":"1f58afa6-2748-4188-b4a4-f1e54e37eca9"},{"id":"7ac4e956-79c2-400d-8d5c-c5083775c51b","value":"{\"root\":{\"children\":[{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Founder of Snapp Technology. I bring 20 years of software engineering experience to building no-nonsense, developer-friendly companies that clients genuinely love. My focus is on creating products that are clear, efficient, and built to solve real problems without unnecessary complexity.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"root\",\"version\":1}}","itemId":"54d55d03-8f64-4a4e-94a6-397cf873c405","fieldSchemaId":"0b77f83b-c31a-4889-b9b3-9a6d2e41fc86"},{"id":"a27a7ec3-934a-46bb-b18f-ef994d130099","value":"Do we need another OS?","itemId":"54d55d03-8f64-4a4e-94a6-397cf873c405","fieldSchemaId":"f2ba59b9-49cc-4ec6-9416-bda99d4c8383"},{"id":"30a5f865-21f2-4825-9835-87a010f71a21","value":"2025-04-03","itemId":"54d55d03-8f64-4a4e-94a6-397cf873c405","fieldSchemaId":"b7712ee6-f9fd-4781-8c5c-e7e10ce8f81e"},{"id":"c71f65b1-6d40-407a-8266-2b38820d8c10","value":"do-we-need-another-os","itemId":"54d55d03-8f64-4a4e-94a6-397cf873c405","fieldSchemaId":"402ba26f-8f6d-4f5f-bf20-62e6549f4ad4"},{"id":"ea7bb68d-87ab-4530-adca-990cb34491ef","value":"{\"root\":{\"children\":[{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Last year Huawei ditched Android and in 2025 will be releasing more and more devices running its HarmonyOS Next software platform.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":2,\"mode\":\"normal\",\"style\":\"\",\"text\":\"HarmonyOS is based on an open source operating system (OpenHarmony) that started as an R\u0026D project at Huawei in 2012. The operating system has been architected to support a wide array of small computing devices from microcontrollers to tablets. It is already used in several of Huawei’s TVs, wearables and wireless router products. In 2024 a ‘pure’ version of the OS, without Android support, was released. This has been branded HarmonyOS Next.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":2,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":2,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Several questions leap to mind:\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h4\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Does the world actually need a new OS?\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Why should we care about what Huawei is doing — especially those of us outside China?\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":2},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Finally, what are the chances of success for a new OS?\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":3}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"list\",\"version\":1,\"listType\":\"number\",\"start\":1,\"tag\":\"ol\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Let’s look a little deeper into these topics and try to understand what’s going on in this space.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"1. Does the world need a new OS?\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h2\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"YES.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Let me explain why I have come to this conclusion.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Computing needs have changed\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h3\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"0f0788289b0aa60400a52945bc967bcd57529edf\",\"src\":\"https://s3-alpha-sig.figma.com/img/0f07/8828/9b0aa60400a52945bc967bcd57529edf?Expires=1765152000\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=GKgeyH5hRyunx75F~2tMxRn2UdKkOCSIwdbgAq~FtiUEMj21~xWxr6bgeoHuPvvGrJV-sz8q-nwKQMknxYvZX3OQm6upmxkrN3tDxw~2WCMoe557kaCzmgZ0T~c9fppuTX1QO04MEP1qj1VhYLmbP5WA0T4TBdYskLB7yGb80HbZOu6EHpS8eU2e6AEV69fD~WZgYR6VMmtJtWjW~0aVL2HhRWWVkMtaTamtR7UCp6HkmmFaiGz3s7-1huzvTBgMafclib8ZUqQJpZj38v72hk0VJHMmTHJZ8YXRDF8k0lLPS37v8L~xarInj91Kr0MBwJoKO-0wBSagjv-EYQtUEg__\",\"altText\":\"\",\"originalImageWidth\":1024,\"originalImageHeight\":1024,\"isFillWidth\":false}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"We have seen a steady growth of small form factor computing. We carry computing devices in our pockets, they are found in devices throughout our homes, they are part of our vehicles, they are in medical devices, and in countless industrial settings.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Within this context, one could argue that phones are at the larger end of the spectrum when it comes to small computing devices. Single board computers and microcontrollers can be found in mechanical keyboards, security cameras, hand-held medical equipment, at the checkout in our shops etc.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Going further, it’s not a huge leap to see that the field of robotics is due to take off with the advent of AI for real time context-aware decision making.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"My first argument, therefore, is that an operating system specifically designed for small computing devices will have a valuable role to play. (Neither iOS nor Android were designed or have evolved to address this need).\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Innovation and competition are good\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h3\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Several operating system innovations have been part of the emergence of mobile and small device computing. Symbian, BlackberryOS, PalmOS, WebOS are a few that immediately come to mind.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"b18c8355d4add89b5c1e6c02cb492113ba497998\",\"src\":\"https://s3-alpha-sig.figma.com/img/b18c/8355/d4add89b5c1e6c02cb492113ba497998?Expires=1765152000\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=J~EU2MELr48IU7dD~RHMFKE0ELb1~-64CZNzDBmLfSJHdMYWH5RkDLQL1f1QUeOT9CvcjZ36uWS1YQsCComxAW2HoFsGfPEYVGJ6ow9cu0A79diZsolw65M84rVkNUv~oVyTRI11WpsXahm8yWhRrFRxx86buUyN0LcoFLrV0npGASCg4lp~d-gM7iXW5KCpmxceSK2fQ8nys1rDi~fyUmouI0CqiNOdsIgilijUbHHn422HGQfZjNylwyxPsHPtr0k5CjjyDRZ0UXjSwcfLW1jDmYjK7ldey0pNHUZf~iiPI9kAnarDORAEQsgBVVwFocdREF8n5l-p1zw6crh89A__\",\"altText\":\"\",\"originalImageWidth\":1024,\"originalImageHeight\":514,\"isFillWidth\":false}],\"direction\":null,\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Image by InspireIP\",\"type\":\"text\",\"version\":1},{\"type\":\"linebreak\",\"version\":1},{\"type\":\"linebreak\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Whilst Android and iOS are the incumbents for phone/tablet devices, there have not been many innovations to bring new alternatives into the mainstream. (See Sidebar below for a more granular discussion).\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"My second argument, is that innovation and competition must be welcome if we are to keep evolving computing on devices.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":2,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":2,\"mode\":\"normal\",\"style\":\"\",\"text\":\"SIDEBAR\",\"type\":\"text\",\"version\":1},{\"type\":\"linebreak\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h4\"},{\"children\":[{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"There are a lot of operating systems that I have skipped over when arguing that there needs to be more innovation. This deserves some justification.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"KaiOS and Fuchsia haven’t reached scale to be called mainstream.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":2},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Tizen, Sailfish, Postmark and others are Linux variants so less about innovation vs adaptation.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":3},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"ReactOS, Minix aren’t production-grade OSes and therefore not mainstream.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":4},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Real time operating systems (RTOS) have seen a lot more innovation, however many of these are extremely specialised.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":5}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"list\",\"version\":1,\"listType\":\"bullet\",\"start\":1,\"tag\":\"ul\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Android is stuck on the phone (mostly)\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h3\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Android remains firmly a mobile phone operating system. Google hasn’t had enormous success moving Android to other device form factors. Yes there are Android tablets, but this hasn’t been a massively successful part of the Android world. Android still ships in some TVs, but that feels even less relevant.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Perhaps one exception is the role Android is playing in in car infotainment systems — this is helping bring vehicles into the digital age. Finally it’s quite common to see Android in some hand-held payment devices.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"However, Android clearly hasn’t exploded into an OS for a huge range of devices. Notably, ‘headless’ Android hasn’t been a thing so it’s never been an OS for IoT or smart home devices.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"My third argument is that Google hasn’t moved Android very far away from the phone. There is room for another OS that can capture phone/ tablet devices as well as smaller (headless) form factors.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Darwin (aka Apple’s OS) is proprietary\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h3\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Apple seems to have done well using its Dawin OS core to spin out multiple variants that run on different device types — MacOS, iOS, iPadOS, WatchOS, tvOS, audioOS, visionOS, bridgeOS.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"However, the OS remains proprietary and Apple has little interest building an ecosystem of 3rd parties using its OS.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"My fourth argument is that we need a new device OS that doesn’t replicate Apple’s closed ecosystem but can be adopted by many for broad uses.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Linux has been Hobson’s choice\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h3\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":2,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Hobson’s choice describes a situation where there is only one option available to choose from, no matter how good/bad it is.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":2,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":2,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"If you look carefully, you will see that most of the operating systems mentioned so far have a close relationship with Linux. Android uses the Linux Kernel, as does KaiOS, Meego, Sailfish, Raspberry Pi OS etc etc. (In the RTOS world, this is less of the case).\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"It’s hard to say whether Linux has been the best choice, because there haven’t really been many other options with the hardware compatibility or software and skills ecosystems.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"My final argument justifying why the world needs a new OS, is that Linux for small form-factor computing has been the default option in many cases, not because it is superior, but because of a lack of other viable alternatives. We would benefit from other options.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"2. Why should we care about what Huawei is doing?\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h2\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"While Huawei is best known for its smartphones and 5G technology, the company operates in a wide range of industries, many of which are less visible from outside China. This diversification highlights Huawei’s ambition to become a global tech powerhouse with influence across multiple sectors.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"ecf2edd64c10f13a14fa7ad9d652f7288f4853d6\",\"src\":\"https://s3-alpha-sig.figma.com/img/ecf2/edd6/4c10f13a14fa7ad9d652f7288f4853d6?Expires=1765152000\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=VBbufOlDUZLS9zc6ZEn46J~4UpkrGvAh~fE2WN5P1VG-tF72yAm6nBFjxjU3ZLBXRDQgiiNVSNITvIZsb74ygLuUmdEbzWukcxIf4iugI~~ilvrh6KjiNAnigEbJHZokisL542fIPvWcgcPqIqwBod7Ktmmv817OASIlgFOmgXAcLzC-ZDs3CjHy-m2OvwYVujMz7GhqWbbU3i8eIlmLEskrBBUMSvXfqHAp~9NCqmRmabwJRBUToREjwHde7MvXTu0bHdWDmvaj4WdnQpNHeWHXLkDJpThbvd5iEOoRMu4HSO3tYh-RYXsuQIyWF0ncF0wHPVKlW~egiBBoHGDDiA__\",\"altText\":\"\",\"originalImageWidth\":1200,\"originalImageHeight\":800,\"isFillWidth\":false}],\"direction\":\"ltr\",\"format\":\"left\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Cloud Computing and AI\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h3\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Huawei has made significant strides in cloud computing. Huawei Cloud, offers services such as data storage, AI-powered analytics, and enterprise solutions. The company is also investing heavily in artificial intelligence, developing AI chips and platforms that are used in everything from smart cities to autonomous vehicles.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Smart Cities and IoT (Internet of Things)\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h3\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Huawei had put considerable efforts into the development of smart city solutions, providing the infrastructure needed to connect and manage urban systems like transportation, energy, and public safety. Building on top of its investments in IoT technologies, Huawei has demonstrated the ability to integrate devices and sensors for solutions in urban environments.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Renewable Energy and Green Technology\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h3\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Huawei is actively involved in the renewable energy sector, particularly in solar power. The company produces inverters and other equipment for solar energy systems, helping to drive the global transition to clean energy. Its focus on green technology aligns with broader efforts to combat climate change and reduce carbon emissions.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Healthcare and Wearables\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h3\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Huawei has expanded into the healthcare industry through its wearable devices, such as smartwatches and fitness trackers, which monitor health metrics like heart rate, blood oxygen levels, and sleep patterns. The company is also exploring AI-driven healthcare solutions, including telemedicine and diagnostic tools, which could revolutionize the way medical services are delivered.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Automotive and Autonomous Driving\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h3\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Huawei is making inroads into the automotive industry, partnering with car manufacturers to develop connected vehicles and autonomous driving technologies. Its expertise in 5G and AI positions it as a major player in the future of smart transportation.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"By operating in such a wide array of industries, Huawei is not just a telecommunications company — it is a multifaceted tech giant with the potential to influence nearly every aspect of modern life.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Huawei’s Investment in Innovation\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h3\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Another reason to care about what Huawei is doing is that they are a very significant source of technology innovation.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Huawei is known for its significant investment in research and development (R\u0026D), particularly in several key technological areas. The company is recognized as a leader in 5G technology, holding numerous essential patents and contributing to the development of 5G infrastructure, which supports faster and more reliable internet connections. This technology is foundational for advancements like smart cities and autonomous vehicles, despite the geopolitical challenges the company faces.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Huawei’s subsidiary, HiSilicon, designs advanced semiconductors, including the Kirin series, although U.S. sanctions have affected their manufacturing capabilities. The company is also actively involved in AI research, developing Ascend AI processors and the MindSpore AI framework, which are used in various sectors such as healthcare and finance.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Additionally, Huawei has experimented with innovative smartphone designs, including foldable devices like the Mate X series, offering unique user experiences.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Why pay attention to HarmonyOS?\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h2\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Huawei’s involvement in multiple industries is not random — it’s part of a coordinated strategy to create an interconnected technology landscape. HarmonyOS plays a central role in this strategy by enabling device-level integration and innovation.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Interesting technologies under the hood\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h3\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Within the HarmonyOS operating system there are some important technologies that should provide some interesting opportunities for Huawei and others.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"453ac5a6790914ec48a99e27adc6d51a7ed86cd6\",\"src\":\"https://s3-alpha-sig.figma.com/img/453a/c5a6/790914ec48a99e27adc6d51a7ed86cd6?Expires=1765152000\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=hj7iFQhZW-wnN35VYi3BAT2F34IdTRjwEds~~KNQY64vyFwXopjHIpVzrrZsoFmEUIJqGk4YSPy2VIZ~2NxgRyY1C8GwGSRkJCx9WH62xop79DgxnSReZzpEC1CggE9VOQHQiQ1Aux4t45X137ytvr2J6YI6Prmbs01CARXesvMtMRl2Fg1~iTJ7eou-7tKdtBYUhFXM8oXDs4Go6senTes2vuLqtO4Bonv4GyjVedlg7LZDNrWttEcnIrnj0OGqJzhcoHf6Ji1rlh~iG01OT1eZmZnOjsqxj5qgc4EDfnWGVb--5eF401502Wi5-y~IcePhAtSlVTUijl8UE1M4QQ__\",\"altText\":\"\",\"originalImageWidth\":1108,\"originalImageHeight\":736,\"isFillWidth\":false}],\"direction\":null,\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"The first\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" is the micro kernel design. This is currently proprietary to Huawei but it means that the operating system is primed for use in IoT, robotics, healthcare, automotive and other industries where realtime capabilities are crucial.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":1,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"The second\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" is that the operating system provides the ability to connect devices together as a system-level service. This makes it easier for developers to build solutions that require multiple devices to interact vs grappling with Bluetooth connections or cloud-based synchronisation.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":1,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"The third\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" technology is Nearlink (called Sparklink outside China). This is an alternative to Bluetooth and has been designed for extremely low latency connections, fast data transfer capabilities and low power consumption.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":1,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"OpenSource and ecosystem friendly\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h3\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Huawei made the strategic decision to place the core of the operating system into the \",\"type\":\"text\",\"version\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"OpenAtom Foundation\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"link\",\"version\":1,\"rel\":\"noopener ugc nofollow\",\"target\":\"_blank\",\"title\":null,\"url\":\"https://www.openatom.org/\"},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" — a Chinese open source ecosystem. This was further boosted by the agreement with the Eclipse Foundation to collaborate on Open Source development within the \",\"type\":\"text\",\"version\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Oniro Project.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"link\",\"version\":1,\"rel\":\"noopener ugc nofollow\",\"target\":\"_blank\",\"title\":null,\"url\":\"https://oniroproject.org/\"}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"04b0a502c0f7ced47b47de5b2cd15fcb1afcc725\",\"src\":\"https://s3-alpha-sig.figma.com/img/04b0/a502/c0f7ced47b47de5b2cd15fcb1afcc725?Expires=1765152000\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=HOvEGBo0eyBcNo77DphzwRvIZyLqWKjsXUc0-UBjoBEd5mNLSR9-WWvS7V7DZd7vni-5C8ZMq8seKL7uITpI-qyujQ-aSzFLUw3SOaaByP3FFK3RbYKqOdn80M2yEqSPUJO38csSrt04Ikq64jsbdfXTYul6kSvIx2fRQWQ58xTizPL6M0-j5mJgb3v9EtMPeo0ACrSWofi-9G~MpznbbEx-4AKZkydr4SgBzLzXMPbV9Br3B52KbnxHtis6IwQ4aw6rzgwlQTzUdYoBUfKXSDCTCRDEMLNUWb9Oekc3rVEpeQRFL8i4mKtLWmBy1pUrbxQooLSDrvVp8KnpYBxmJg__\",\"altText\":\"\",\"originalImageWidth\":1279,\"originalImageHeight\":720,\"isFillWidth\":false}],\"direction\":null,\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"This is a very significant move because it has been the start of an ecosystem of OEMs shipping products based on Harmony with the capabilities such as device interoperability. An example is Cannon printers — Harmony based devices (from Huawei or others) can interact with these printers using the operating system’s built-in device connection capabilities and highly performant data transfer technology.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Creating an ecosystem of devices with a common operating system foundation will be a game changer.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"HarmonyOS everywhere\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h3\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"It’s easy to have missed the fact that HarmonyOS is already spreading out far beyond the phone. Already it is possible to HarmonyOS or OpenHarmony based operating systems in the following settings:\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Headphones\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Watches\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":2},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"TVs\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":3},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Smart speakers\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":4},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"WiFI routers\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":5},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Phones\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":6},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Tablets\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":7},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Cars\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":8},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Home appliances (from Midea)\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":9},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Mining (IoT)\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":10},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Digital pens\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":11},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Robotics\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":12},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"ATMs\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":13}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"list\",\"version\":1,\"listType\":\"bullet\",\"start\":1,\"tag\":\"ul\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Whilst we might not be seeing the impact of HarmonyOS \u0026 OpenHarmony outside of China, by the time we see it, there will already be a mature and vibrant ecosystem of manufacturers and solutions based on the OS.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"3. What are the chances of success for a new OS?\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h2\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"I think the answer to this question is different depending on whether you are considering Huawei’s market in China or the rest of the world.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Inside China\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h3\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Whilst not guaranteed, it is fairly likely that Huawei will succeed and establish HarmonyOS as a 3rd ecosystem. It’s market position means it can attract consumers and those building solutions on the platform.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"However, to achieve more significant success for HarmonyOS, a significant ecosystem of non-Huawei products using OpenHarmony must exist. If Huawei can build an ecosystem of 3rd parties using OpenHarmony, and bring these together via the inbuilt device connectivity layer of the operating system, then we will see an evolution beyond what we are currently experience with iOS and Android.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Outside China\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h3\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"The chances of success outside China are clearly much harder to predict and the strategy much harder to prescribe.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Firstly,\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" Huawei will have to demonstrate that they are a source of innovation. Consumers have become entrenched in an Apple or Google ecosystem. Huawei is unlikely to win if they play a ‘me too’ game. They have to bring something new to the table.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":1,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Secondly,\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" consumers will have to see something useful running to be convinced. If we are bombarded with marketing claims and promises then Huawei is unlikely to convince consumers by making bold claims. Instead, they will have to show consumers some real world cases of HarmonyOS doing useful and interesting things in their local environments.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":1,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Thirdly,\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" Huawei will have to overcome data and privacy concerns. There are opportunities to do this in Europe where Huawei can embrace the numerous data sovereignty and privacy standards from the EU. In other parts of the world there might be less concern about these topics or Huawei will have to find local opportunities to show consumers that data is being handled reasonably.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":1,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Geopolitical opportunities\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h3\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"With America going through political change, there could be a change in attitude to our relationship with big tech from American companies such as Google, Microsoft, Amazon, Apple etc.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Consumers could very well start to look for alternative ecosystems and technology providers.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"If Huawei could stoke a healthy 3rd party ecosystem that gives non-US technology companies some new opportunities, there could be much wider acceptance of Huawei products using the proprietary HarmonyOS.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"This is could be possible given the smart move to make OpenHarmony available to everyone.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Long term thinking and determination\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h3\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Ecosystems can take years to form and Huawei is probably one of the few companies that could stick to a long term strategy.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"If HarmonyOS continues to be successful in China, then there is a good chance that Huawei will operate with patience to grow HarmonyOS outside of China.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"It is also reasonable to assume that when Huawei is ready to push more actively into other markets, the products will have already reached quite a mature state. Indeed, they will have a huge domestic market to help refine and evolve their HarmonyOS offering before we get our hands on it.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"TL;DR\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h2\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"A new operating system targeting small devices does fill a gap left by the mobile phone and Linux-based operating systems.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Apple and Google have failed to establish themselves as larger ecosystem players. Linux has been a default choice due to it’s wide chipset and driver support but has otherwise not innovated in the realm of small computing devices.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"However, even a compelling proposition with great technology and innovation will struggle if it does not establish an ecosystem of hardware OEMs, developers and consumers.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"root\",\"version\":1}}","itemId":"54d55d03-8f64-4a4e-94a6-397cf873c405","fieldSchemaId":"3084d9ba-ab55-4e5a-931b-b9db3d09105f"}]},"3c5b467e-c8c3-4e68-b2fc-d0ea238942cb":{"id":"3c5b467e-c8c3-4e68-b2fc-d0ea238942cb","index":"!`","collectionId":"d4a5b68c-8afd-4bbe-a7ac-e9a8422fedde","fields":[{"id":"1b0b59e2-4844-4c93-8154-2699d006dfa4","value":"ship-it-right-a-swift-package-quality-checklist-part-1-of-3","itemId":"3c5b467e-c8c3-4e68-b2fc-d0ea238942cb","fieldSchemaId":"402ba26f-8f6d-4f5f-bf20-62e6549f4ad4"},{"id":"94f85605-efb8-4ac7-bdd3-53692f85d44e","value":"Ship It Right: A Swift Package Quality Checklist. Part 1 of 3.","itemId":"3c5b467e-c8c3-4e68-b2fc-d0ea238942cb","fieldSchemaId":"f2ba59b9-49cc-4ec6-9416-bda99d4c8383"},{"id":"66162448-e9c0-4f52-8585-f2ed7a9d83e8","value":"2026-01-05","itemId":"3c5b467e-c8c3-4e68-b2fc-d0ea238942cb","fieldSchemaId":"b7712ee6-f9fd-4781-8c5c-e7e10ce8f81e"},{"id":"5e0ba620-e0bd-40c6-ac72-ce8c3bcd7245","value":"{\"root\":{\"children\":[{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Oleksii is an iOS alchemist at Snapp Mobile 📱✨, turning concepts into beautifully crafted Swift code and smooth, user-friendly interfaces. He’s passionate about shaping mobile experiences that feel effortless and refined. A firm believer in the power of simplicity, he focuses on writing clear, thoughtful code that brings ideas to life without unnecessary complexity.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"root\",\"version\":1}}","itemId":"3c5b467e-c8c3-4e68-b2fc-d0ea238942cb","fieldSchemaId":"0b77f83b-c31a-4889-b9b3-9a6d2e41fc86"},{"id":"c376ff3b-d305-4c27-809b-28c1aecdfc0a","value":"Oleksii Kolomiiets","itemId":"3c5b467e-c8c3-4e68-b2fc-d0ea238942cb","fieldSchemaId":"df1c88d1-4bd8-4ecd-9059-463b9589de92"},{"id":"f3bcd098-48e4-4b28-8063-334d621fec0c","value":"{\"root\":{\"children\":[{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"I still remember the moment I decided to open-source my first Swift Package Manager plugin. The code worked perfectly in our internal projects at \",\"type\":\"text\",\"version\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Snapp\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"link\",\"version\":1,\"rel\":\"noopener ugc nofollow\",\"target\":\"_blank\",\"title\":null,\"url\":\"https://snapp.technology/\"},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\", but making it public-ready? That was a different story. I spent the next week adding DocC documentation, setting up GitHub Actions CI, writing example apps, and addressing edge cases I’d been ignoring because “it worked for us”.\",\"type\":\"text\",\"version\":1},{\"type\":\"linebreak\",\"version\":1},{\"type\":\"linebreak\",\"version\":1},{\"detail\":0,\"format\":3,\"mode\":\"normal\",\"style\":\"\",\"text\":\"This series is for \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":2,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Swift developers turning internal packages into\",\"type\":\"text\",\"version\":1},{\"type\":\"linebreak\",\"version\":1},{\"detail\":0,\"format\":2,\"mode\":\"normal\",\"style\":\"\",\"text\":\"polished public repositories — covering documentation, quality, and\",\"type\":\"text\",\"version\":1},{\"type\":\"linebreak\",\"version\":1},{\"detail\":0,\"format\":2,\"mode\":\"normal\",\"style\":\"\",\"text\":\"community setup.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Here’s the thing: most developers know how to write good code. But there’s a massive gap between “code that works” and “a repository that welcomes users and contributors.” That gap includes:\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"children\":[{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Documentation that assumes zero context — \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Your \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":2,\"mode\":\"normal\",\"style\":\"\",\"text\":\"README.md\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" makes sense to you, but will it help someone discovering your project at 2 AM?\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":1},{\"children\":[{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Quality automation — \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Are you manually checking code style, or does your CI catch issues before they reach main?\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":2},{\"children\":[{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Community infrastructure \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"— When someone wants to contribute, is the path clear or confusing?\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":3},{\"children\":[{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Discoverability\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" — Great code that nobody knows about might as well not exist.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":4}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"list\",\"version\":1,\"listType\":\"bullet\",\"start\":1,\"tag\":\"ul\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"I learned these lessons by studying successful repositories, discussing best practices with experienced coworkers, and developing my own sense of what makes a project polished versus what might fall short.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Let’s start with the most visible part of any repository — the README.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"README: Keep It Concise\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h2\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"README is the door, not the whole house.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h3\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Follow a simple rule: the README should answer three questions:\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"children\":[{\"detail\":0,\"format\":2,\"mode\":\"normal\",\"style\":\"\",\"text\":\"What does this do?\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":1},{\"children\":[{\"detail\":0,\"format\":2,\"mode\":\"normal\",\"style\":\"\",\"text\":\"How do I install it?\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":2},{\"children\":[{\"detail\":0,\"format\":2,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Where can I learn more?\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":3}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"list\",\"version\":1,\"listType\":\"number\",\"start\":1,\"tag\":\"ol\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"What Belongs in a README\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h3\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":2,\"mode\":\"normal\",\"style\":\"\",\"text\":\"1. Title and One-Line Description — \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"make it crystal clear what this is.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":2,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"2ddbe27da96c49341b0fc05ebbd834cd1cdbd367\",\"src\":\"https://s3-alpha-sig.figma.com/img/2ddb/e27d/a96c49341b0fc05ebbd834cd1cdbd367?Expires=1768780800\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=iNYDLCKBUuChY~psAIXfTaGf6Xdq0JfEYku~KxCOCZ9~pxxkm~aWHNLItel5o5g3QELsjYP6jZJIWXB0gRUZQPzxg1XTcnitqLWRKxAmkR~0aQf15Lh6vSLyGCxzv69S1DKXsomjog3I8N3cIwsXXByGyD2VCKrylrcRLPpjDM9jIT6zTw-hJjf5Rtmy3q8WyhKCSK1xtGSCyAKVirN9uw8ZaIH1mZop3jN1AuNYJycFRrYFCjBV229DL57FRd8iWvJXk6u1Nlo3f13~wy~fKLn2r1LczzkoVaggrdqrlwxGRvaNNSSTZ12lavtkQuucUIo1Yfq4Unb6KlDKWoh4rA__\",\"altText\":\"\",\"originalImageWidth\":3484,\"originalImageHeight\":968,\"isFillWidth\":false}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":2,\"mode\":\"normal\",\"style\":\"\",\"text\":\"2. Key Badges — \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"status, version, license, supported platforms etc.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":2,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"89e9db53ab0607e939b1e93744ca5c69aece78df\",\"src\":\"https://s3-alpha-sig.figma.com/img/89e9/db53/ab0607e939b1e93744ca5c69aece78df?Expires=1768780800\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=oje9ofQbbxxixcJ7Fe4vW0uXjjeDL8w5c4A8Lldt7ImOJaMWqBBBP4vbq3Ek-jWLfH20HrS-xA5MbMikv4GvPnYGLO7ixQO5HVl~NpWe9b8~xuEX4hR33cBflhgwyxk2LfkiDSsN6kB8nydcMXuL~d03XuCqq2P7mfU42Ci4h8Xtd01MkwS2WP7OrjUPJYsnteLv0-wmIe3gll6Fd3r4~47qLZ3W3dyi~iKy8TTGmCliPXIIUOasez1LGXFU4QuEPYjwb8nT~TMr70uUZ1RFlRou33kUIwHkLC5N1K75E5-aiUUe3pDsHmyPbdbBSYo5mO4p30GOEIJCSilxPzCS1Q__\",\"altText\":\"\",\"originalImageWidth\":3484,\"originalImageHeight\":1264,\"isFillWidth\":false}],\"direction\":\"ltr\",\"format\":\"left\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"left\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"55934c1ac95f01d7d457cf1ba368d7936974d4b0\",\"src\":\"https://s3-alpha-sig.figma.com/img/5593/4c1a/c95f01d7d457cf1ba368d7936974d4b0?Expires=1768780800\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=SLkliIUgDwVR470zdblZZ~XPxqhYYnevQz8D8uUeSgxvQ8d688yndEY-DUBB5o7PC8e2A~oxujHzi7zSwcFXU2nSo7dRA4ZTJnCLBrdSEuzPjMT7wLEqHP8J9etJnII-jHU2nkrXfESkC-Og66yQBNhtWLLsH85IaDXl8Omu5IcHwspv96Bvfh4TubNNGaxhMglsIvQ2EZIEosnxiPLVSnvs9J2fE11mtWNxnw3PFNJYoGu2i~kZ7g8qIICwlLGnWY~3NcpkLUl-SIL~~S8xImdZqcyr1F4Q6zmQS2RRJCJdKo~n2KPD9BFYSJ1kCRINW4gUu8D9KInKq6DiA13AuA__\",\"altText\":\"\",\"originalImageWidth\":1864,\"originalImageHeight\":416,\"isFillWidth\":false}],\"direction\":\"ltr\",\"format\":\"left\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"left\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":2,\"mode\":\"normal\",\"style\":\"\",\"text\":\"3. Installation Instructions/Quick Start — \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"keep it copy-paste ready.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":2,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"5cd63b513120c097542195205fb0fd3aaef149f0\",\"src\":\"https://s3-alpha-sig.figma.com/img/5cd6/3b51/3120c097542195205fb0fd3aaef149f0?Expires=1768780800\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=E7B0Ty~JCG1wf3NFxBZMtvWdycwGl914mTOP-zhtVyfBZ9hkUWTIKZq-FBMKYb3Pvy0DWV6FRmEAAyln-I-T9IuAUcS7rKAlmQCyAd9yf4AMPNjodiwn-UHmKY50ViHhiOr5TC~ej6Xk5X2Hy67QE~IsyeYMQPmadM08nsSn9zigVpQaeOLkzJzX2yY0Tb3aZDsqzzvzbpdvXOgq-OLLCg~8ZacoYg1GyG5vegZh7Nw7d6yIBwfAPbSJ2~i9QPa1ModPDQFPq29UX35W~F8ckBSAA3m4dUw~9oVA2XFwe4UrCcQnqny6rxCO68hs-j8Jg3fJAqumGZIDFDxYUpIWgg__\",\"altText\":\"\",\"originalImageWidth\":1736,\"originalImageHeight\":686,\"isFillWidth\":false}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"left\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":2,\"mode\":\"normal\",\"style\":\"\",\"text\":\"4. Minimal Usage Example \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"— simple examples that show the core value proposition\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"left\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":2,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"left\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"d2cdcec0936453a7ef571f967128565ac5402ece\",\"src\":\"https://s3-alpha-sig.figma.com/img/d2cd/cec0/936453a7ef571f967128565ac5402ece?Expires=1768780800\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=uRoY-xI5bGiMxWlWb78MLAwX~~qGy~vCCQQsA35xNfsB-cCx2DPJmCST6-X9htaGq5DU2e14HFs7mNo7soQUONL0VV6oxWy241TYAbEJoONn6lHUo8ISjStWZoy-WEOzq5Hf2dItMJiPyapmkE8cvj0cHqC-P~Sx2m2QhYurHLIKLzdm89OmqJDe~Ur76gMJsbkAJ1Fp2Hnf7NK4h6UilZECnUQNAbTQsItQIawlS-2qmOZeckm~sASVfvRlwGg7b4~KbvaSwqs4BFdqkruSf0F0ztrGJylJyp2BaunUuIP5kFZot-zQ9lW5o~cdHkguS1fTZ4cWiR7CeLzgQ9JlVQ__\",\"altText\":\"\",\"originalImageWidth\":3484,\"originalImageHeight\":1936,\"isFillWidth\":false}],\"direction\":\"ltr\",\"format\":\"left\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"left\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"or code snippet\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"left\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"left\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"7f85fccd9348b5efc2e7859626b018d43c39ba7a\",\"src\":\"https://s3-alpha-sig.figma.com/img/7f85/fccd/9348b5efc2e7859626b018d43c39ba7a?Expires=1768780800\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=h96EJ8fgDkteBxK8UBnq1hWl05KVeIOoldHQ5pyLDpruGDfZSLr3XYb~mxgnSlm5XReVmorRm0FIePE7CQ0ZrE~KxIi~khcFqieTRyJOXykSidWNto~U6-Mt-jWyEtLtsvphH5VBtHvddq-m3x5kiVtqeRQmBZLX56TSbhDjyjT2fqTR~EbpTC8u-nJ~1PJlfo9upqsnIyFoDcNVXhpZv8OKXlbUrXhqLOcuGbioU9oU6ITtUtgNMSaO8tjOLcDkWVc4SOCfhc3SzYQYcWmKEd8aBVvnrM-c1uETDKfzXfReXmCcK4obSM12PTCKEyePh3o6IADqOcQJ0jT5szXQ4Q__\",\"altText\":\"\",\"originalImageWidth\":1740,\"originalImageHeight\":826,\"isFillWidth\":false}],\"direction\":\"ltr\",\"format\":\"left\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"left\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Consider adding a \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"screen recording \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"— it often demonstrates your framework’s capabilities faster than written explanations.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":2,\"mode\":\"normal\",\"style\":\"\",\"text\":\"5. Link to Full Documentation\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":2,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"6c5e3f9bda5b9e1cf88957a7ea29b54d6fd2d561\",\"src\":\"https://s3-alpha-sig.figma.com/img/6c5e/3f9b/da5b9e1cf88957a7ea29b54d6fd2d561?Expires=1768780800\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=HeBtkppetWR8Eiznt~cZZ7XCUs50V0LBhhbI42CBqsflAm-l~nGBCZ3b02fVCcMPRTb6dM5EtGEIuMzrGqjtjKR2c4wGFaNEIIaVwUTM7leYNZCRBnt76xIoKkiLzo3fAPahdetv5RSlygLa2atQHOpiS9q12H-IIApIya7k-dEEnDh4f9Uko0YTfxwE0bCyq7MNZrNqpq4Be4Fmi66e0NkC126IjvqXv-00XOv10IwT9DmnG0vb7fUTIZa-ws158XsFNX32ZURrowZpwhOMV6xs3pjthh3XjyXIY7Pq79jteONWc77LWGbMzq~MQmh~a3DE9V3r3C0L3ap77kB4Og__\",\"altText\":\"\",\"originalImageWidth\":3484,\"originalImageHeight\":1040,\"isFillWidth\":false}],\"direction\":null,\"format\":\"left\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"left\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":2,\"mode\":\"normal\",\"style\":\"\",\"text\":\"6. License — \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"quick reference, one line or a badge or both.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"left\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":2,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"left\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"2291534844410a444215624111b2df41bc4e48dd\",\"src\":\"https://s3-alpha-sig.figma.com/img/2291/5348/44410a444215624111b2df41bc4e48dd?Expires=1768780800\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=FIDHtBCbRED6H9X6HN9RmjxPLAww2nC2d7jlINjXMf8wAOp8fnkO2ZIxZYVT8ZZtSrKUAtV8TCvqmNh-GF-Sz6feVnGivYEUiwMghOjEhLb72bWkBrchPz76wWndpni7FPQKspGkHap7TYh51j-YBrU-MIy3MypyEF4wZAjYVf5wRtnanqLNtpH3KKguMEnn~YkYAYZC9jrGQ19ERCPhohRd7ox7l9FIDHCg1QaRnLbmgkahM7VqubOniu2rycNd5-XksQQdtUNs3WPv9e5PfxxwLkQBw4HnRbA6gOqGGEUMnwA6o8lse3VqefUZ8dJB8G57V~QbyeGUj7~BGaLMIw__\",\"altText\":\"\",\"originalImageWidth\":3484,\"originalImageHeight\":892,\"isFillWidth\":false}],\"direction\":null,\"format\":\"left\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"left\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"What Doesn’t Belong in a README\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h3\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Everything else. Specifically:\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"children\":[{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Detailed API documentation\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" → DocC comments on your public APIs\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":1},{\"children\":[{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Comprehensive guides\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" → DocC articles\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":2},{\"children\":[{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Architecture explanations\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" → DocC articles or separate docs\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":3},{\"children\":[{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Every configuration option \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"→ DocC articles\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":4},{\"children\":[{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Change log\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" → Separate \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":2,\"mode\":\"normal\",\"style\":\"\",\"text\":\"CHANGELOG\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\".md file\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":5}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"list\",\"version\":1,\"listType\":\"bullet\",\"start\":1,\"tag\":\"ul\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"If you find yourself writing “Advanced Usage” sections or multiple levels of nested headers, you’re overcomplicating your README. Move that content to proper documentation.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Real Examples\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h3\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Look at my actual repositories to see this philosophy in action:\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"children\":[{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"MediaBridge\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"link\",\"version\":1,\"rel\":\"noopener ugc nofollow\",\"target\":\"_blank\",\"title\":null,\"url\":\"https://github.com/oleksiikolomiietssnapp/MediaBridge\"},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" — Brief and to the point\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":1},{\"children\":[{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"swift-coverage-action\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"link\",\"version\":1,\"rel\":\"noopener ugc nofollow\",\"target\":\"_blank\",\"title\":null,\"url\":\"https://github.com/Snapp-Mobile/swift-coverage-action\"},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" — GitHub Action, under 100 lines\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":2},{\"children\":[{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"SwiftFormatLintPlugin\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"link\",\"version\":1,\"rel\":\"noopener ugc nofollow\",\"target\":\"_blank\",\"title\":null,\"url\":\"https://github.com/Snapp-Mobile/SwiftFormatLintPlugin\"},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" — SPM plugin, focused on essentials\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":3},{\"children\":[{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"SnappDesignTokens\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"link\",\"version\":1,\"rel\":\"noopener ugc nofollow\",\"target\":\"_blank\",\"title\":null,\"url\":\"https://github.com/Snapp-Mobile/SnappDesignTokens\"},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" — Framework with link to comprehensive DocC docs\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":4}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"list\",\"version\":1,\"listType\":\"bullet\",\"start\":1,\"tag\":\"ul\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"License: Just Use MIT\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h2\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Here’s my license advice: \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"MIT is the way\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\". It’s permissive, simple, and universally understood.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Why MIT? The entire license fits on one screen, it’s safe for commercial use, plays well with other licenses, and creates zero adoption friction. If you had specific patent concerns requiring Apache 2.0, you’d already know it.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"How to Add: GitHub offers an “Add a license” dropdown when creating repos. Select MIT. Done. Or create a LICENSE file manually. Choose MIT. Add the file. Move on.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Documentation: DocC and Working Examples\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h2\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"As mentioned in the README chapter, clear documentation hierarchy matters: \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"README for essentials, DocC for everything else\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\". But here’s where I get particularly opinionated: write DocC comments for every public method and abstraction, and make absolutely sure they include working examples.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Let me emphasize that last part: \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"working examples\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\". Not broken code. Actual code that you’ve run and verified works.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Nobody likes copying non-working example code, and nothing destroys trust in documentation faster than examples that fail — just ask anyone who’s hit broken sample code in Apple’s docs.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"DocC Comments for Public APIs\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h3\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Every public method and type needs documentation. Not “nice to have” — needs. When you publish a framework, your public API is your contract with users.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"65b795c9738d510f8e1b71453c8030e890a7b836\",\"src\":\"https://s3-alpha-sig.figma.com/img/65b7/95c9/738d510f8e1b71453c8030e890a7b836?Expires=1768780800\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=SXx-jUSHN~5gknibSC5ueQKtxUqwzNCnsMuyIuiUUMjLewGEzUFVVpCuCDSE9pnxgDurpg2jodoqklbOQfs2ixRaZF6LJH8sIfw3tEeGKuNhc7RmVTJ1rPCInLFaJIUVirPAwIgXNRUBTrObDWQSqeslzSk-4WFmCqBWOcdJciTFyWdhrd3ZGV2njn3Ski6c1-YOTafufnyhq19jA3vK3jBlFJBZW2np2jeMM3yh0LQg93WzBVhliLG~a9oaqylMQtCVedek6tljeUbcCfNmKJMh9jFF~F4pPTKYj5EojGAN9iQY0Qz74EFQCS~H30dXbHJu~Hsz0FbsIBXRZ6F1-g__\",\"altText\":\"\",\"originalImageWidth\":638,\"originalImageHeight\":990,\"isFillWidth\":false}],\"direction\":null,\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Testing Your Documentation Examples\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h3\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"I learned this lesson the hard way with \",\"type\":\"text\",\"version\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"SnappDesignTokens\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"link\",\"version\":1,\"rel\":\"noopener ugc nofollow\",\"target\":\"_blank\",\"title\":null,\"url\":\"https://github.com/Snapp-Mobile/SnappDesignTokens\"},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\". Early versions had documentation examples that were close to correct but had small syntax errors or used an outdated API. Users would copy them, get errors, and (rightfully) lose confidence in the entire framework.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"My go-to method is using code from actual tests in documentation examples — that way they’re verified and guaranteed to work.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"DocC Articles for Detailed Guides\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h3\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Articles are where comprehensive documentation lives. I organize them by topic:\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"children\":[{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Getting Started\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" — Step-by-step guide for first-time users\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":1},{\"children\":[{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Configuration \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"— All available options with explanations\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":2},{\"children\":[{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Advanced Usage\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" — Complex scenarios and edge cases\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":3},{\"children\":[{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Architecture\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" — How the framework is designed (for contributors)\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":4}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"list\",\"version\":1,\"listType\":\"bullet\",\"start\":1,\"tag\":\"ul\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Articles use standard Markdown with DocC extensions. Reference your API directly:\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"3a20e0995f8c2347a54e2b90d071612e7afc7136\",\"src\":\"https://s3-alpha-sig.figma.com/img/3a20/e099/5f8c2347a54e2b90d071612e7afc7136?Expires=1768780800\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=R0L-dqcGTHSzURaMkgSp79kqNXwQ9Rx~63qTVxS5z3OKGh1J3TXdHgqYbn8EXlCXDJem1v0Qkw41q5zI2X4BjTOwOtKbojEHXK6iyugTfLBGHDWrQg53Hf1X91j7efkl0bF1m9GglguEujdQ-4wfjeeADFOL3TtDIOFuHzJDckpRyqA3fIQCiKteNgVXXmG2oaNWzHytZv7BZiYSzGn3-~8Shm5hqBajAMRiYrVkMHsIXqvG9Wvy1xIYTh205jb2wJTRPF0H0-koeN1FP~xuyRWcMv9itPdfcfxg6IpV8yBi~f3YNGKehSVQDp-5JWA87KwRPgrxlDdA3cLsOnHl3A__\",\"altText\":\"\",\"originalImageWidth\":3484,\"originalImageHeight\":1040,\"isFillWidth\":false}],\"direction\":null,\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"The double backticks create links to your API documentation. When readers click them, they jump to the full API reference.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"For a real example of this structure, check out \",\"type\":\"text\",\"version\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"SnappDesignTokens documentation\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"link\",\"version\":1,\"rel\":\"noopener ugc nofollow\",\"target\":\"_blank\",\"title\":null,\"url\":\"https://github.com/Snapp-Mobile/SnappDesignTokens/tree/main/Sources/SnappDesignTokens/SnappDesignTokens.docc\"},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\".\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Framework Icons (Optional but Nice)\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h3\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"If you want to add polish, create an icon for your framework. I use the \",\"type\":\"text\",\"version\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Strata — Icon Generator\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"link\",\"version\":1,\"rel\":\"noopener ugc nofollow\",\"target\":\"_blank\",\"title\":null,\"url\":\"https://apps.apple.com/pl/app/strata-icon-generator/id6742242942\"},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" for creating framework icons — it’s designed specifically for generating the right sizes and formats for DocC. Place it in \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":16,\"mode\":\"normal\",\"style\":\"\",\"text\":\"YourFramework.docc/Resources/\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\". It’s a small touch that makes your framework feel more professional.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Key Principles\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h3\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"children\":[{\"detail\":0,\"format\":2,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Working examples are non-negotiable\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" — Test them before publishing\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":1},{\"children\":[{\"detail\":0,\"format\":2,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Document the “why” not just the “what” \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"— Explain when and why to use each API\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":2},{\"children\":[{\"detail\":0,\"format\":2,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Keep documentation close to code\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" — DocC comments live with the code they document\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":3},{\"children\":[{\"detail\":0,\"format\":2,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Separate concerns \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"— README for quick start, comments for API reference, articles for deep dives\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":4},{\"children\":[{\"detail\":0,\"format\":2,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Verify everything \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"— Broken docs are worse than no docs\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":5}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"list\",\"version\":1,\"listType\":\"number\",\"start\":1,\"tag\":\"ol\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Great documentation turns a good framework into one that developers actually want to use.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Example Apps: Show, Don’t Just Tell\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h2\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Documentation tells developers how your framework works. Example apps show them. There’s a massive difference between reading about an API and seeing it in action, and every public repository should include working examples as part of the package structure.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"We learned this building \",\"type\":\"text\",\"version\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"SnappThemingSVGSupport\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"link\",\"version\":1,\"rel\":\"noopener ugc nofollow\",\"target\":\"_blank\",\"title\":null,\"url\":\"https://github.com/Snapp-Mobile/SnappThemingSVGSupport\"},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\". Developers could run the example, see the output, then reference the code to understand the implementation.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Project Structure\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h3\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Include example apps as part of your Swift Package Manager structure. It could be a Source folder or root for better visibility — up to you.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"The example lives alongside your framework code, not in a separate repository. This keeps everything in sync and makes it trivial for developers to find.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"2e3c0f65e75a99ed5359fbe118f4dd832a04c1d0\",\"src\":\"https://s3-alpha-sig.figma.com/img/2e3c/0f65/e75a99ed5359fbe118f4dd832a04c1d0?Expires=1768780800\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=pofkc4Wj9O54rh-kXYgfgZur1FgRcJs-p2KhZoZsG~hvMx3mozre9fcu-MnzWVnObFbFQe9a6K8t70aqjgM-80BAYzKe3Ph941JFsiAgLI5SkzhzH0DorYN5FVve~wFbltSYf4g8MiqwWVR5p9MDVo0J2Qxj2JwMLDpQNELn8OwdMWMuR00Bb7569CjWsu3NG78uLLAJTVz2CcHTCAlgxmq2SydDWuYzRgGWIWfcHgztG7hJz-Qsc9Xmt9HCVIOX3bJwYaXQCROIyLP3nhvLG355-vuI0WEVz3-Gaw3A0jr8jXTWgEt-2J1GvMgSaOxfhkR5gR2KOkb5FXpouDfRUA__\",\"altText\":\"\",\"originalImageWidth\":3484,\"originalImageHeight\":1636,\"isFillWidth\":false}],\"direction\":null,\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"macOS Executable Targets: The Easy Choice\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h3\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Here’s a practical tip I wish someone had told me earlier: \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"prefer macOS command-line executable targets over iOS example apps\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\".\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Why? They’re dramatically faster for CI to run. No simulator. No waiting for Xcode to boot.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"When iOS Examples Make Sense\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h3\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Sometimes you need iOS examples — specifically when your framework:\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Deals with UI components\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Uses iOS-specific APIs (MPMediaLibrary, UIKit views)\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":2},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Requires device features (camera, sensors)\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":3}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"list\",\"version\":1,\"listType\":\"bullet\",\"start\":1,\"tag\":\"ul\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"In these cases, create an iOS example, but keep it simple:\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Single-target app\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"No external dependencies beyond your framework\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":2},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Clear navigation to relevant features\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":3},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Instructions in README for running it\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":4}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"list\",\"version\":1,\"listType\":\"bullet\",\"start\":1,\"tag\":\"ul\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"For a real example, check out \",\"type\":\"text\",\"version\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"MediaBridge’s Example app\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"link\",\"version\":1,\"rel\":\"noopener ugc nofollow\",\"target\":\"_blank\",\"title\":null,\"url\":\"https://github.com/oleksiikolomiietssnapp/MediaBridge/tree/main/Example\"},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"—it's an iOS app because the framework deals with a library that isn’t supported in macOS.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"The Documentation Reference Loop\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h3\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Example app demonstrates real usage\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Documentation references the example app\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":2},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Users run the example to see it in action\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":3},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Users read the code to understand the implementation\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":4},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Users check documentation for detailed API info\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":5}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"list\",\"version\":1,\"listType\":\"number\",\"start\":1,\"tag\":\"ol\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Each piece reinforces the others. Your example app becomes the practical bridge between “I read the README” and “I integrated this into my project.”\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Now that we’ve covered how to help users understand and use your package, let’s talk about maintaining code quality as your project grows.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Auto-Linting: Consistent Code From Day One\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h2\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Code style debates are exhausting. You know what’s not exhausting? Automated \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":2,\"mode\":\"normal\",\"style\":\"\",\"text\":\"linting\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" that enforces consistent style before code reaches your main branch. No discussions about where braces go. No PR comments about trailing whitespace. Just consistent code, enforced by tools.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"I built \",\"type\":\"text\",\"version\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"SwiftFormatLintPlugin\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"link\",\"version\":1,\"rel\":\"noopener ugc nofollow\",\"target\":\"_blank\",\"title\":null,\"url\":\"https://github.com/Snapp-Mobile/SwiftFormatLintPlugin\"},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" specifically to solve this for Swift Package Manager projects. It integrates swift-format directly into your build workflow, catching style issues before they become PR bikeshedding sessions.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Why This Matters\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h3\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"When you make a repository public, you’re inviting contributions from developers with different editors and preferences.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Without automated enforcement, you end up with inconsistent code and two bad options: accept the mess or spend review time discussing formatting instead of logic. Neither is acceptable.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"The Setup\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h3\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Integration takes two minutes. Add the plugin to your Package.swift targets, create a \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":16,\"mode\":\"normal\",\"style\":\"\",\"text\":\".swift-format\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" config file with your rules (we use 120-char line length, 4 spaces, respect existing line breaks), and you’re done.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Contributors run swift package plugin format before committing. CI automatically enforces style during builds. If code doesn’t match the rules, the build fails with clear output about what needs fixing.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":2,\"mode\":\"normal\",\"style\":\"\",\"text\":\"The result\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\": at no point do contributors guess what style you want or read a CONTRIBUTING document about brace placement. The tools guide them automatically.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":2,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":2,\"mode\":\"normal\",\"style\":\"\",\"text\":\"SwiftLint\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" is another solid option, especially if you want semantic rules beyond formatting (like complexity metrics or naming conventions). Many projects use both. Choose one, configure it, enforce it in CI. The specific tool matters less than having automated enforcement.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":2,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Testing: The Non-Negotiable Axiom\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h2\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Unit tests are a must-have for public repositories. This isn’t up for debate. It’s an axiom — a fundamental truth of professional software development.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"If you’re publishing code for others to depend on, you must have tests that verify it works. Not “nice to have.” Not something you add later when you “have time.” Tests are part of shipping.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Why Tests Are Non-Negotiable\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h3\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"When someone adds your package as a dependency, they’re trusting that your code works. Tests are your proof.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"They demonstrate correctness, stability, and confidence. They show contributors they can modify code without fear. They document how the API is intended to be used.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"What to Test\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h3\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Test the public API comprehensively:\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"children\":[{\"detail\":0,\"format\":2,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Happy paths\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" — Normal usage with valid inputs\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":1},{\"children\":[{\"detail\":0,\"format\":2,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Error cases \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"— Invalid inputs, boundary conditions\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":2},{\"children\":[{\"detail\":0,\"format\":2,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Edge cases \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"— Empty collections, maximum values, unusual but valid inputs\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":3},{\"children\":[{\"detail\":0,\"format\":2,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Integration\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" — Components working together\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":4}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"list\",\"version\":1,\"listType\":\"bullet\",\"start\":1,\"tag\":\"ul\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"You don’t need 100% coverage of private details, but \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"every public method\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" should have tests verifying correct behavior and error handling.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"CI Integration\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h3\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Tests must run in CI on every push and pull request to \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":2,\"mode\":\"normal\",\"style\":\"\",\"text\":\"main\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" at least. Use a matrix to test on multiple platforms (macOS, iOS) and Swift versions. Cross-platform packages should work everywhere, and the matrix catches platform-specific issues.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"The Standard\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h3\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Before you make a repository public, ask yourself: “Can I confidently say this code works?”\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Without tests, the honest answer is “probably, based on the limited scenarios I’ve manually tested.” With comprehensive tests, the answer is “yes, and here’s the proof.”\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Tests aren’t about hitting some coverage percentage. They’re about professional confidence in the code you’re asking others to depend on.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h4\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Test Coverage: Visual Feedback in PRs\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h2\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Tests verify your code works. Coverage reports show which code is actually tested. Having test coverage displayed directly in pull requests gives contributors immediate feedback and helps maintain quality standards.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"I built \",\"type\":\"text\",\"version\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"swift-coverage-action\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"link\",\"version\":1,\"rel\":\"noopener ugc nofollow\",\"target\":\"_blank\",\"title\":null,\"url\":\"https://github.com/Snapp-Mobile/swift-coverage-action\"},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" to solve this for Swift projects. It generates coverage reports and posts them as PR comments, making coverage visible without requiring contributors to run coverage tools locally.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"d9927e5e2fad7df34ed00bdba37feb03f46f64b9\",\"src\":\"https://s3-alpha-sig.figma.com/img/d992/7e5e/2fad7df34ed00bdba37feb03f46f64b9?Expires=1768780800\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=QHTlrXhqB5OavPrpHFQLwCjBg4JDT05VdkHl3rcwRhVUHsIw5QotDv5XrshziRSBDPGxoxB8SuBw1-F5QNMMsdxbOvtKILUqeI-KwxXm~K96vkDZngRgYJrdws9UMbuvyQdlWM~KIbvyvdAYwAR04cqq8T6emkm98dgId76aQKmZmStM~kaEvxI5ZWUv5hXecXX7WWQURUfAhTzlm3vUyqNoAH-NSTg-NJeIBxmHbBMCiGljO6vfsQlHWr-kS5e1CDd7JZtTq63QVdkSvxZfZR2qqtWVL9g-xGStY1Rg~swNe2q5S0dpvGPjh-llmu8YyNuw9dRJjoEdYabi5gSWUQ__\",\"altText\":\"\",\"originalImageWidth\":1614,\"originalImageHeight\":500,\"isFillWidth\":false}],\"direction\":null,\"format\":\"left\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"left\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Why It Matters\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h3\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Coverage reports in PRs provide immediate feedback — contributors see if their changes are tested before requesting review. You see if coverage is improving or declining.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"We add \",\"type\":\"text\",\"version\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"swift-coverage-action\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"link\",\"version\":1,\"rel\":\"noopener ugc nofollow\",\"target\":\"_blank\",\"title\":null,\"url\":\"https://github.com/Snapp-Mobile/swift-coverage-action\"},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" to our GitHub Actions workflow. This is useful for you and contributors to quickly see the health of the codebase.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Coverage percentage is useful, but it’s not the goal. The goal is confident, well-tested code. Use coverage as a signal, not a target. If it starts dropping, dig in: Are the untested paths critical error handling?\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Part 1 Checklist: Foundation and Quality\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h2\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"- [ ] Concise README with title, installation, quick start, docs link\",\"type\":\"text\",\"version\":1},{\"type\":\"linebreak\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"- [ ] MIT LICENSE file\",\"type\":\"text\",\"version\":1},{\"type\":\"linebreak\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"- [ ] DocC comments on all public APIs with working examples\",\"type\":\"text\",\"version\":1},{\"type\":\"linebreak\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"- [ ] DocC articles for comprehensive guides\",\"type\":\"text\",\"version\":1},{\"type\":\"linebreak\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"- [ ] Example app (preferably macOS executable)\",\"type\":\"text\",\"version\":1},{\"type\":\"linebreak\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"- [ ] Automated linting (SwiftFormatLintPlugin or SwiftLint)\",\"type\":\"text\",\"version\":1},{\"type\":\"linebreak\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"- [ ] Comprehensive unit tests\",\"type\":\"text\",\"version\":1},{\"type\":\"linebreak\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"- [ ] Test coverage visible in PRs\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Next: \",\"type\":\"text\",\"version\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Part 2: Community and Lifecycle\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"link\",\"version\":1,\"rel\":\"noopener\",\"target\":null,\"title\":null,\"url\":\"https://medium.com/@oleksii_24924/b1a0ed970e4e\"}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"root\",\"version\":1}}","itemId":"3c5b467e-c8c3-4e68-b2fc-d0ea238942cb","fieldSchemaId":"3084d9ba-ab55-4e5a-931b-b9db3d09105f"},{"id":"b8247a5b-c82e-434b-be1a-2e507a947e41","value":"iOS Developer","itemId":"3c5b467e-c8c3-4e68-b2fc-d0ea238942cb","fieldSchemaId":"0a981f8a-7dbb-440d-a940-25d9060c9b11"},{"id":"cd55923e-5faa-46e3-bc83-6204ccde51d4","value":"{\"image\":\"9972fa5742ca6aeedf28786fddff2999b950112c\",\"imageThumbnail\":\"35d869621a9520848d9829bf0d33f1068f2ac7a5\",\"originalImageHeight\":933,\"originalImageWidth\":1400,\"altText\":\"\",\"fileName\":\"Shipit.png\"}","itemId":"3c5b467e-c8c3-4e68-b2fc-d0ea238942cb","fieldSchemaId":"1f58afa6-2748-4188-b4a4-f1e54e37eca9"}]},"a9458e2b-bfb5-4cf8-883d-d6edb7f1113d":{"id":"a9458e2b-bfb5-4cf8-883d-d6edb7f1113d","index":"%r","collectionId":"d4a5b68c-8afd-4bbe-a7ac-e9a8422fedde","fields":[{"id":"3f9de30c-3838-4a44-9323-b17b3ff9f1d8","value":"How We Found the Perfect Android Automotive Developer Kit Solution","itemId":"a9458e2b-bfb5-4cf8-883d-d6edb7f1113d","fieldSchemaId":"f2ba59b9-49cc-4ec6-9416-bda99d4c8383"},{"id":"0c427d4f-242a-448b-9ce8-452be328631f","value":"Al Sutton","itemId":"a9458e2b-bfb5-4cf8-883d-d6edb7f1113d","fieldSchemaId":"df1c88d1-4bd8-4ecd-9059-463b9589de92"},{"id":"e47b00c6-dbb3-462e-9e2e-d943ad5b0215","value":"{\"image\":\"c5e7a733ed8e0b69e300c5689181e1f11a712a2e\",\"imageThumbnail\":\"8d18c532ed94dca7a4ae9182401821149ce424db\",\"originalImageHeight\":2730,\"originalImageWidth\":4096,\"altText\":\"\",\"fileName\":\"autokit_2.png\"}","itemId":"a9458e2b-bfb5-4cf8-883d-d6edb7f1113d","fieldSchemaId":"1f58afa6-2748-4188-b4a4-f1e54e37eca9"},{"id":"d851d251-2511-4b79-b782-aad7506f0c36","value":"how-we-found-the-perfect-android-automotive-developer-kit-solution","itemId":"a9458e2b-bfb5-4cf8-883d-d6edb7f1113d","fieldSchemaId":"402ba26f-8f6d-4f5f-bf20-62e6549f4ad4"},{"id":"058ab09c-4d6c-4968-92a5-9b7c5167552e","value":"2024-12-03","itemId":"a9458e2b-bfb5-4cf8-883d-d6edb7f1113d","fieldSchemaId":"b7712ee6-f9fd-4781-8c5c-e7e10ce8f81e"},{"id":"a8d6341e-30ed-4e37-8cf3-8dbc94580e5b","value":"{\"root\":{\"children\":[{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"When we started Snapp Automotive we identified multiple ways to help the automotive ecosystem create great Android based experiences in vehicles. These ranged from processes, to tooling and software technologies, that would allow folk to create these experiences faster, iterate on them more quickly, and arrive at a delightful experience that everyone could enjoy.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"One of the pieces of the puzzle we identified was the lack of a reasonably priced development platform. We initially made builds for the \",\"type\":\"text\",\"version\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Raspberry Pi\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"link\",\"version\":1,\"rel\":\"noopener\",\"target\":null,\"title\":null,\"url\":\"https://medium.com/snapp-automotive/android-automotive-os-11-on-a-raspberry-pi-2abaa133f468\"},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\", and have used Android tablets with some of our customers, all to ensure that we have a cost-effective solution to allow folk to try out, and provide feedback on, automotive experiences.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"dd7e4948d6eba38fd7c3bc76b92b39cb83a71805\",\"src\":\"https://s3-alpha-sig.figma.com/img/dd7e/4948/d6eba38fd7c3bc76b92b39cb83a71805?Expires=1768780800\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=hjgLiExMdDml9FI8zVxPrvGCWhwNYtClXKFZb1gPkk7jLURc-oUI0UbxipLs1QXwjv6PvCgB~JE3YTAdHlSPtMLnyEqgJcxdUkBmvl5v8-v7ZJD6yPQGQ0Z1dN3VzR9UxuW1vpfxkQNGSDSdnNObceImPCe5ERAx~2Z0NbPT4YGw8YJEoOETK1xFcCCRSPfR5IT06aNto8m4xONAgiQ7U9yyvYLb~v8ozpY9nLTE0BajIXAmi0SYygxkJmGI2zOT7Q9P4VOqOJzJRLkcVkKN6TVJuVBl2fNLw12sp7V960N2fx8BuwGtdrzZ5o8NLmTnAz04gCE4H61kmoZ3ybB9OQ__\",\"altText\":\"\",\"originalImageWidth\":4096,\"originalImageHeight\":2731,\"isFillWidth\":false}],\"direction\":null,\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Last year we took the decision to create a “Development Kit”. Android for phones had the \",\"type\":\"text\",\"version\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Android Dev Phone 1\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"link\",\"version\":1,\"rel\":\"noopener\",\"target\":null,\"title\":null,\"url\":\"https://venturebeat.com/social/android-developers-start-your-engines-google-unlocks-the-g1/\"},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\", which was a great help to developers getting started on the newly released Android OS. Android for TVs has the \",\"type\":\"text\",\"version\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"ADT-1\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"link\",\"version\":1,\"rel\":\"noopener\",\"target\":null,\"title\":null,\"url\":\"https://developer.android.com/tv/adt-1\"},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" which serves a similar purpose. Unfortunately, for Android Automotive OS, the recommendation was to \",\"type\":\"text\",\"version\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"repurpose some of Google’s Pixel Phone models\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"link\",\"version\":1,\"rel\":\"noopener\",\"target\":null,\"title\":null,\"url\":\"https://source.android.com/docs/automotive/start/pixelxl\"},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" to act as AAOS devices, but, to us, this missed the mark for what was needed. \",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Phones (and tablets) don't allow you to try different screen sizes and aspect ratios. They don’t work well for arms-length testing of UIs. They also can’t be easily expanded to provide access to the CAN bus, don’t support multiple screens, and other hardware configurations which are commonplace in vehicles.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"So we began our search for something which would give us the flexibility we wanted, performance that reflected in-vehicle hardware (i.e. not an emulator), and in a package which was affordable enough to be widely usable (unlike the bench units automotive companies currently use today).\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Today, after a lot of research and discussion, we are excited to share that we can best make this available by supporting the community efforts around an existing piece of hardware; The Khadas VIM3.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"The Journey\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"left\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h2\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"When we started looking for the right piece of hardware we, wrongly, assumed that it would be a short search. We thought we could find an off-the-shelf head unit that would allow us to create AAOS builds which included things that aren’t in the AOSP (e.g. a Map provider), and package it in a way which would be useful to developers.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"After gathering some hard data around the interest in an automotive dev kit, and talking to various companies, we’ve realised that a low-volume, low-cost, off-the-shelf automotive head-unit doesn’t currently exist, and, from a cost perspective, creating one isn’t, for us, feasible.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"The two main hurdles were Intellectual Property and Sales Volumes. We talked to several companies who had existing head units that could be customisable, but, they either couldn’t give us access because the head unit hardware because it had been created for a specific customer, wanted thousands of euros per unit for small runs, or could not give us the ability to build our own firmware for the units due to licensing restrictions on the relevant Android BSP.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"We also had discussions with companies who would design something for us, to see if that would be viable, but that would cost hundreds of thousands of euros, and the end product would not fit within our cost budget. \",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"We are still talking to some of these companies about solutions for our customers who are producing vehicles and need in-vehicle hardware, but, to us, this has led us to the conclusion a solution designed for use in vehicles, and on developers desks, might not make the best dev-kit.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"The VIM3\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"left\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h2\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Using the VIM3 was an idea originally suggested to us by Chris Simmonds. Chris, for those who don’t know him, is a much admired member of the Linux and Android communities who frequently organises tracks at conferences, and has a wide knowledge of Android, and Linux, at a low level in the software stack.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"The VIM3 isn’t, on its own, suitable for use in vehicles. It’s designed for the maker community, and so has features that would allow third parties to alter the firmware of vehicles on the road, which is something most vehicle manufacturers do not want. It also, natively, lacks some of the features an infotainment system board would have (e.g. a CAN bus interface), but some of those can be worked around (e.g. USB CAN bus dongle, thanks again Chris!). So it looks like a good fit for a desk based dev kit.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"c5e7a733ed8e0b69e300c5689181e1f11a712a2e\",\"src\":\"https://s3-alpha-sig.figma.com/img/c5e7/a733/ed8e0b69e300c5689181e1f11a712a2e?Expires=1768780800\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=gT4~DJm1XyuGNjwvwB8f8Sp~WT91jwRcNcNEqdPmSjVV0jUVi9hk9ZKiJF-lk5HpyPX-BikB40ctGhFXebJJRLASdAjjbaZMpG8P7OVkPruzYlyKEEemwFSwHZLDLbt41wiF6i27lJK0WIMAjCTKeoSh2k6PL99YNMXOWRxsqPk0oE1YwH7eNQ~1B64z4~SoRBFxyXTYVZWqEUV9rwLv7SltR1V7ZPx7aSF-q2y3Fc~Nhaqf-RhqlivSTS1GllCBm5jNdl76UicU2iWlVynMugcK~5RFn4MuQ~0449B-m33bRAP-k0YVcVmuTvxBlMDYgpqnkF21xjht0915WlTfKQ__\",\"altText\":\"\",\"originalImageWidth\":4096,\"originalImageHeight\":2730,\"isFillWidth\":false}],\"direction\":null,\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"The VIM3 is supported in Google’s \",\"type\":\"text\",\"version\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Android Open Source Project\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"link\",\"version\":1,\"rel\":\"noopener\",\"target\":null,\"title\":null,\"url\":\"https://source.android.com/docs/setup/create/devices\"},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\", which avoids the redistribution issues around custom builds for Google Pixel phones and tablets (which comes from their BSP licence agreement). It can support different display sizes, and dual displays, allowing folk to simulate multiple passenger displays, or a central display and cluster arrangement, and it’s widely available from online retailer, such as Amazon, in the UK, Germany, the USA, and others countries, meaning we side-step having to be involved in physical shipment logistics.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"One of the groups Chris is part of, the \",\"type\":\"text\",\"version\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"AOSP devs\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"link\",\"version\":1,\"rel\":\"noopener\",\"target\":null,\"title\":null,\"url\":\"https://aosp-devs.org/\"},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\", have already made instructions on building \",\"type\":\"text\",\"version\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"firmware for the VIM3 available\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"link\",\"version\":1,\"rel\":\"noopener\",\"target\":null,\"title\":null,\"url\":\"https://aospandaaos.github.io/device-vim3.html\"},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\", and they’re not the only folk who’ve already “kicked the tyres” on Android on the VIM3. There are folk such as \",\"type\":\"text\",\"version\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"BayLibre\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"link\",\"version\":1,\"rel\":\"noopener\",\"target\":null,\"title\":null,\"url\":\"https://baylibre.com/\"},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" who are \",\"type\":\"text\",\"version\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"actively pushing improvements to Google\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"link\",\"version\":1,\"rel\":\"noopener\",\"target\":null,\"title\":null,\"url\":\"https://android-review.googlesource.com/c/device/amlogic/yukawa/+/3253421/3\"},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" that will improve Android on the VIM3 for everyone, and we’ve \",\"type\":\"text\",\"version\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"recently contributed a change\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"link\",\"version\":1,\"rel\":\"noopener\",\"target\":null,\"title\":null,\"url\":\"https://android-review.googlesource.com/c/device/amlogic/yukawa/+/3342471\"},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" which makes it easier to build firmware for the device.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Overall \",\"type\":\"text\",\"version\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"its specifications\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"link\",\"version\":1,\"rel\":\"noopener\",\"target\":null,\"title\":null,\"url\":\"https://www.khadas.com/vim3\"},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" are pretty solid, it has near global availability, strong community support, and has the ability to be expanded to meet our check-list of needs for a dev kit, and so we decided to recommend it for AAOS development and make builds of AAOS 12, 12.1, 13, 14, and 15 available to folk who want to get involved in automotive development, but don’t want to build their own firmware images.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"7e88d1b50e668b0c7026e387091ebf0365078c8f\",\"src\":\"https://s3-alpha-sig.figma.com/img/7e88/d1b5/0e668b0c7026e387091ebf0365078c8f?Expires=1768780800\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=mkWDy~FI~NzFLTmwWKNJkzrgDul8B8GX0vFYniD4K8aRxjYz8Mk2zN4Ht6VP-CxUSMsKgJO42Wa3VKrWCy8zsIDRtjrYD7AI3K6e4XnqeW~mZxDfbuXT5krNhgIqUBgLk4-LzlDotaSbg0XY4xbWGAkbeIiXT~TE4kbota3UNrpz6WKLTOlxLXCpBFgeIqShDX7XyGqgwlWAGOB3MFodBJRs46qwcRxQcB131bRvvzzyeS7tIuTB4q9yNv19CAjKQdoz3AzmnP~26G1N~9NhMGIqKQ6PmiMJaK1e9tK10SpkwgJLmWj9qz5viBoTGaGxwdPYVLWKMMOK2BBwq04eXQ__\",\"altText\":\"\",\"originalImageWidth\":4096,\"originalImageHeight\":2731,\"isFillWidth\":false}],\"direction\":null,\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Next Steps\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"left\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h2\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Chris and the AOSP devs community have \",\"type\":\"text\",\"version\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"already created technical documentation\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"link\",\"version\":1,\"rel\":\"noopener\",\"target\":null,\"title\":null,\"url\":\"https://aospandaaos.github.io/device-vim3.html\"},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" around buying, and creating builds for the VIM3, and \",\"type\":\"text\",\"version\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"we’ve created our own version of that\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"link\",\"version\":1,\"rel\":\"noopener\",\"target\":null,\"title\":null,\"url\":\"https://github.com/snappautomotive/device_snappautomotive_vim3/wiki\"},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\", so we’re going to focus on the needs of automotive developers who don’t want to build firmware, but, instead, just want an Android Automotive OS device to develop against. We’re also going to help Chris, the AOSP devs, Baylibre, and everyone else involved in the communities to ensure the VIM3 stays relevant, and useful, to all types of developers.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"We’re looking forward to helping the community build an open solution, and helping companies get started with AAOS development in a cost effective manner. Thanks to everyone who expressed interest in the dev kit, you can find our free Android Automotive builds for the VIM3 and the details on how to get started \",\"type\":\"text\",\"version\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"on our website\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"link\",\"version\":1,\"rel\":null,\"target\":null,\"title\":null,\"url\":\"https://www.snappautomotive.io/developer-kit\"},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\".\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"root\",\"version\":1}}","itemId":"a9458e2b-bfb5-4cf8-883d-d6edb7f1113d","fieldSchemaId":"3084d9ba-ab55-4e5a-931b-b9db3d09105f"},{"id":"9727ae8a-429b-4010-9357-d05d83970fe3","value":"{\"root\":{\"children\":[{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Former Google Android Staff Engineer with over 25 years of software development experience across leading global companies including Facebook, Reuters, JP Morgan Chase Manhattan, Deliveroo, and others. Proven track record of building and scaling high-quality, reliable software systems, leading complex technical initiatives, and mentoring engineering teams in fast-paced, high-impact environments.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"root\",\"version\":1}}","itemId":"a9458e2b-bfb5-4cf8-883d-d6edb7f1113d","fieldSchemaId":"0b77f83b-c31a-4889-b9b3-9a6d2e41fc86"},{"id":"d480da62-a756-40a7-b43d-ce36d8a87466","value":"CTO - Android Automotive","itemId":"a9458e2b-bfb5-4cf8-883d-d6edb7f1113d","fieldSchemaId":"0a981f8a-7dbb-440d-a940-25d9060c9b11"}]},"d170bf6b-3352-42d5-a55b-7bd99f0f7709":{"id":"d170bf6b-3352-42d5-a55b-7bd99f0f7709","index":"%u","collectionId":"d4a5b68c-8afd-4bbe-a7ac-e9a8422fedde","fields":[{"id":"8b6cd9c2-0b88-450c-a4e5-03488218f0da","value":"We Really Need to Take Infotainment Error Handling Seriously","itemId":"d170bf6b-3352-42d5-a55b-7bd99f0f7709","fieldSchemaId":"f2ba59b9-49cc-4ec6-9416-bda99d4c8383"},{"id":"679c9344-96c5-450d-ba07-c6fb6626e3f0","value":"2024-11-04","itemId":"d170bf6b-3352-42d5-a55b-7bd99f0f7709","fieldSchemaId":"b7712ee6-f9fd-4781-8c5c-e7e10ce8f81e"},{"id":"2c92453a-ee16-4a96-93f4-63e7e7d9850c","value":"we-really-need-to-take-infotainment-error-handling-seriously","itemId":"d170bf6b-3352-42d5-a55b-7bd99f0f7709","fieldSchemaId":"402ba26f-8f6d-4f5f-bf20-62e6549f4ad4"},{"id":"861c0857-e01c-4ae1-a33a-68bd656502c9","value":"{\"image\":\"5a0e4fc397d5606baa22de469965df56e0818e39\",\"imageThumbnail\":\"fde7fc7e4421478d4e02af33f5e45a01958be8c6\",\"originalImageHeight\":1536,\"originalImageWidth\":2048,\"altText\":\"\",\"fileName\":\"autoerror.png\"}","itemId":"d170bf6b-3352-42d5-a55b-7bd99f0f7709","fieldSchemaId":"1f58afa6-2748-4188-b4a4-f1e54e37eca9"},{"id":"e6835d3e-d9a2-44b0-aa88-7b8c7cdcdea4","value":"Al Sutton","itemId":"d170bf6b-3352-42d5-a55b-7bd99f0f7709","fieldSchemaId":"df1c88d1-4bd8-4ecd-9059-463b9589de92"},{"id":"8f56eb60-9605-4a55-8578-0844ee0c8fc2","value":"CTO - Android Automotive","itemId":"d170bf6b-3352-42d5-a55b-7bd99f0f7709","fieldSchemaId":"0a981f8a-7dbb-440d-a940-25d9060c9b11"},{"id":"a2ad1b06-c937-49cd-aad0-4fb9b49538cd","value":"{\"root\":{\"children\":[{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Imagine starting a new job. Imagine coming into the office on the second day to find your computer is showing a “Loading” screen. Imagine being told the only way to fix it was to shut the computer down, leave the office, lock the door, go away for 15 minutes, then come back and try again. That’s pretty much equivalent to the experience I had this weekend with my newly purchased Cupra Formentor.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"My wife and I got into the car, started it, and tried to switch to her profile. Simple enough we thought, but a few minutes later, where the only indication on screen that the system was doing anything was a “Please Wait….” message, we decided to try rule 1 of technology; If it seems stuck try turning it off and back on again.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"This time we saw a “Loading Settings” screen, so we set off because, after all, we were trying to drive somewhere to meet some folk at an arranged time. The infotainment experience we had for the whole hour-long journey didn’t change…. “Loading Settings” was all we saw. We couldn’t start the internal Navigation app, we couldn’t start CarPlay. The only thing the screen would do is show that it was loading settings…. for an hour.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"0ee75bfa5de7b849ff34ad93140a6d914d22d311\",\"src\":\"https://s3-alpha-sig.figma.com/img/0ee7/5bfa/5de7b849ff34ad93140a6d914d22d311?Expires=1768780800\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=TLFD39G3EQhCSjUKIMZddeBT4wNuXI~sJeRsUJPrbd4tyaT-YtWdfaRDZ5vyhCM-E9nnuLQ6qo3eNKevj5b8MW3NOXZM-gRkamEgyGpAeUF1UAitRMFUS354v6w5oiYRU4EkXzVdvMuCFbJnbUJDjFy03LTbSiIIkAEFqxK0voWvqnTKZ-fe5JG~xC4wVr1O1f2DteknRvkVoDphVirPzMk2oZzKljXDuiEF5z3dGa9r8DWoUJ-YnD6o5C36x1J8BI0ZdiRxHrqXoXBoAZhHatzKYb94af3h-~k6ao7rzgfRhrZuLSx1c4RBJBTdN8FVoh5sxYIUerSLEBNtxwx37g__\",\"altText\":\"\",\"originalImageWidth\":4032,\"originalImageHeight\":3024,\"isFillWidth\":false}],\"direction\":null,\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Profile switching issues on the Formentor aren’t a new problem. There’s a post on a user forum \",\"type\":\"text\",\"version\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"from over two years ago\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"link\",\"version\":1,\"rel\":\"noopener\",\"target\":null,\"title\":null,\"url\":\"https://www.seatcupra.net/forums/threads/anyone-have-a-view-on-whether-a-factory-reset-of-the-infotainment-will-fix-lagginess.469925/#post-5013849\"},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" which talks about the usability problems of switching users on the Formentor, and, given that Cupra was part of Seat, and is part of the Volkswagen Group, it’s surprising, to me, that the infotainment system could have such long-lived usability problems. Doing a bit of research uncovered that the compute platform is known as MIB3, and it’s used in multiple vehicles, and this isn’t an issue which is limited to the Formentor.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"It’s also not a difficult problem to solve. Using a \",\"type\":\"text\",\"version\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"watchdog timer\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"link\",\"version\":1,\"rel\":\"noopener\",\"target\":null,\"title\":null,\"url\":\"https://en.wikipedia.org/wiki/Watchdog_timer\"},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\", and having sensible defaults, which are two well known software techniques, would ensure that things like profile switching achieve what the driver wants, or falls back to a set of predictable defaults, in seconds. This means that folk can get on with the task they’re trying to accomplish (i.e. driving to another location), and not be stuck with a useless screen in the middle of their car.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"I later found out that a software update had been released several months before (MIB3 version 1969, my car was on version 1940). Did the OTA update screen show anything? Nope. I ended up having to go into an engineering menu and manually apply the update from a USB stick. Not exactly something you can expect an average driver to do.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"5963ae8180c88917b034174f7115879081b48e1d\",\"src\":\"https://s3-alpha-sig.figma.com/img/5963/ae81/80c88917b034174f7115879081b48e1d?Expires=1768780800\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=iBkhsGll-hytoM8~SZzeS2nqqwXW9Y-YnkyOYDHCTFsnzG1jDLyNgFygqKxTjxer8S2wDZruEp5wft-299bUbosFkNZzvFqPURgeiyzCST0bTr5T-eXXBbV0Fgqlq-X1eGjTZrczDfuuIvJa9gPDkxT4-qawUdI4iZRzqNp7ZXHfomg6EVDQb6Ark9c5ReoTJ7SLWAKQDCBKywHfVP-xVQYD60UkhWTeN5q5Vh7hqozA~CvbkJdJ6FlL2jy0fWE8LNkbAhuMvisWVS0w5Wq~dAyBcFKPUa25zQYLWF4J6J7DTva-GBWeF3~uhH-6fjJsACv3JOlMtR6hGc~ZREHt5w__\",\"altText\":\"\",\"originalImageWidth\":4032,\"originalImageHeight\":3024,\"isFillWidth\":false}],\"direction\":null,\"format\":\"left\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"left\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"I’m pretty sure I hit an edge-case error (otherwise there’d be a lot more complaints online), so how do we get the automotive industry to take infotainment error handling seriously?  Drivers certainly want a reliable infotainment system whatever happens (an hour-long drive with Google Maps on a phone reading out directions isn’t fun when you have an unusable 10.9” screen only centimetres away).\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Any issues with Infotainment systems tarnish the automotive brand (knowing MIB3 is a cross-car platform means I’m now cautious about recommending any other VW group car). Leaving errors, even edge-case ones, unresolved for years projects an image of lack of customer care, no matter how good the vehicle is otherwise.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"With the move to Android Automotive OS based systems we have an opportunity to hit reset on error handling. We don’t need to, and in many cases can’t, carry over legacy implementations, without review, just to save development costs. We have an opportunity to create systems which gracefully handle errors in a way which works for the driver, and gives them an experience which will leave them focusing on the driving experience, and not why they’re sitting in a car for minutes looking at a “Please Wait” message, or staring at a loading screen for hours, when all they want is some navigation instructions.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"At Snapp Automotive we’ve been delivering Android Automotive OS proof of concept implementations for evaluation, and implementations which have been rolled into production, for a range of platforms. We’re focusing on the infotainment system as our core competency so we can make the experience reliable, enjoyable, and something that adds value to the vehicle's brand.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"I just hope more manufacturers decide to focus on making infotainment error handling something users can, effectively, not worry about, and that in the near future, I don’t have to spend another hour looking at a “Loading settings” screen instead of getting help to achieve the job in hand; Driving from A to B.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"root\",\"version\":1}}","itemId":"d170bf6b-3352-42d5-a55b-7bd99f0f7709","fieldSchemaId":"3084d9ba-ab55-4e5a-931b-b9db3d09105f"},{"id":"1919db76-0b29-4d2b-ad12-7459c217359a","value":"{\"root\":{\"children\":[{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Former Google Android Staff Engineer with over 25 years of software development experience across leading global companies including Facebook, Reuters, JP Morgan Chase Manhattan, Deliveroo, and others. Proven track record of building and scaling high-quality, reliable software systems, leading complex technical initiatives, and mentoring engineering teams in fast-paced, high-impact environments.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"root\",\"version\":1}}","itemId":"d170bf6b-3352-42d5-a55b-7bd99f0f7709","fieldSchemaId":"0b77f83b-c31a-4889-b9b3-9a6d2e41fc86"}]},"74a1903b-5353-4325-b47a-2610388e8506":{"id":"74a1903b-5353-4325-b47a-2610388e8506","index":"%y","collectionId":"d4a5b68c-8afd-4bbe-a7ac-e9a8422fedde","fields":[{"id":"7149c02b-4c8f-4757-ba03-546d165575d4","value":"2024-04-30","itemId":"74a1903b-5353-4325-b47a-2610388e8506","fieldSchemaId":"b7712ee6-f9fd-4781-8c5c-e7e10ce8f81e"},{"id":"8f0b658c-83b9-4f99-9da4-b976cf2f4af1","value":"how-we-created-a-multi-brand-design-system-in-figma","itemId":"74a1903b-5353-4325-b47a-2610388e8506","fieldSchemaId":"402ba26f-8f6d-4f5f-bf20-62e6549f4ad4"},{"id":"37516783-6661-465f-82f4-5cc10eed96e6","value":"How We Created A Multi-Brand Design System In Figma","itemId":"74a1903b-5353-4325-b47a-2610388e8506","fieldSchemaId":"f2ba59b9-49cc-4ec6-9416-bda99d4c8383"},{"id":"ddd0a29f-1836-4442-88f0-1df5ba967e8a","value":"Casper Kessels","itemId":"74a1903b-5353-4325-b47a-2610388e8506","fieldSchemaId":"df1c88d1-4bd8-4ecd-9059-463b9589de92"},{"id":"7c858e83-19ba-4845-9b37-affd9d858c4b","value":"{\"image\":\"6ec42d58068fe5dbc1feb6f0e8f73952ac378ab5\",\"imageThumbnail\":\"e7b1a91a24e666407819e3fc6f1a39e58a248ce0\",\"originalImageHeight\":1200,\"originalImageWidth\":1800,\"altText\":\"\",\"fileName\":\"auto_ds.png\"}","itemId":"74a1903b-5353-4325-b47a-2610388e8506","fieldSchemaId":"1f58afa6-2748-4188-b4a4-f1e54e37eca9"},{"id":"6b3dc66f-7f60-47fa-b6bc-a52be75c4552","value":"{\"root\":{\"children\":[{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Two years ago, we set out to create \",\"type\":\"text\",\"version\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"SnappOS\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"link\",\"version\":1,\"rel\":null,\"target\":\"_blank\",\"title\":null,\"url\":\"https://www.snappautomotive.io/snappos\"},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\", a white-label infotainment system aimed at carmakers who don’t have the time or expertise to build their own. We work with carmakers ranging from high-end hypercars to mass-volume micro-mobility vehicles. All are served by one product. \",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"However, each carmaker we work with has unique branding, features, and hardware setup. Naturally, we don't want SnappOS in a sports car to have the same look as in a city car.  That is why we invested a lot of time and effort into creating a theming engine to handle this level of customization. Over the past months, we've been working on a design system that is closely connected to the theming engine and allows us to scale to tens of different brands without branching out. Here's how we did that. \",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"ee1e29fd9bd181373fa32796a8fdf77dea40b9bf\",\"src\":\"https://s3-alpha-sig.figma.com/img/ee1e/29fd/9bd181373fa32796a8fdf77dea40b9bf?Expires=1769385600\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=Zk0svuc8kkg~2nNUd7-WWm5~cWFh-DvmzBNitUJdQ6PxeGXKTUZxju125MyvBeF8YzCann0ZtrPzMgYySuuB6bmT1q2L~jV~9v-HAO9mPI~Ujn0lqsvl5XjPL-fpQIn7o9GQkW2lOiJom1vAHlcDJFw0KLqOPMiRT3Cdihm2-KZ25l0eKDTERLXxxn6JTInptr411ZTjytL-l3u8OQEK9QNtgkH5tknOKLAnmiHDoOizuN4lLaXe5~63GKtJHn2nOlXHtn0jlmx3KPHGcVEAI8KFyk2~KheWm1giDFlj32QdaeGJgXgJ34v8ZhCcxo1y3pZJDgKx49S3pZE3u5jozQ__\",\"altText\":\"\",\"originalImageWidth\":3601,\"originalImageHeight\":1240,\"isFillWidth\":false}],\"direction\":null,\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"The Theming Engine\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"left\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h2\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Every carmaker we work with is served with the same core product. For each carmaker, it is crucial to go in the shortest amount of time possible from a white-label product to a finished solution adjusted to the screen layout, with custom features, and unique branding.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"That is why we created our own '\",\"type\":\"text\",\"version\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"theming engine\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"link\",\"version\":1,\"rel\":null,\"target\":\"_blank\",\"title\":null,\"url\":\"https://www.snappautomotive.io/theming-engine\"},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"', a core part of our product that ensures we can create distinct branding for each customer with the same product as the basis. We've written before about \",\"type\":\"text\",\"version\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"how the theming engine works\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"link\",\"version\":1,\"rel\":null,\"target\":\"_blank\",\"title\":null,\"url\":\"https://www.snappautomotive.io/blog/a-deep-dive-into-our-powerful-theming-engine-for-android-automotive\"},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" in detail. The core idea behind the theming engine is simple. Anything that is customizable has a token assigned. A token can store any string or integer.  Therefore, the tokens include the typical things like colors and fonts, but also icons, radius, spacing, effects, app icons, and operands like booleans. By changing the value of the token, we change the UI theme.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"We developed the theming engine at the same time as the product so in the first year of development, there was a lot of trial and error to figure out the capabilities and limitations of the theming engine. That is why, when the first version of the product and theming engine was ready, the Figma library and codebase were not really connected. \",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"This made it difficult for designers to understand the capabilities of the theming engine, and very time-consuming for developers to implement the designs. So that is why we decided to create a design system from scratch that is easy to use by both designers and developers, has the same setup and logic of the theming engine, and serves all platforms from in-car to mobile. \",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"The Previous Setup\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"left\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h2\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"With our first version, we ran into several problems because we were trying to do something that wasn’t supported by Figma. \",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"In our original setup, we had one global components file with, you guessed it, all the components. Then for each theme, we duplicated a styles file with the colors, icons, and typography. Similarly, we duplicated the product files that included all the pixel-perfect final designs.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"fd6924b349a72c91009c74c6c26627d1f7083b36\",\"src\":\"https://s3-alpha-sig.figma.com/img/fd69/24b3/49a72c91009c74c6c26627d1f7083b36?Expires=1769385600\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=uaVXSZVlkMnp8HBJDsLSzXvaVor9Tfo5IsbQNLHoLbKg-Dv-ka8hi5uUE49MPguj7-7J0FSJCDwPOfOPaKTsQiSqg~B6YWoHBAUW4LhZ2IpmOaeiXsb-95VC9E-U~SWnFdo~XXmw9OEIbCXbPqg3tKfyUOMwO-RCdIGVKdt8APcBYrpaTjxXt-LYchVY7890eW3qiRZco~aoe0sZNXS-4ToMc7AuYr97IbgYu11DsIsY4yL2n3V8oFI1OVHT8dIoSM1vw08GjDXPYwDASFl0-DcdvBdywKA~xDLSToHdT4uoC3ByRnNEZYoehne4o~6xCgNujI8pi6UH1ezLtb7IVg__\",\"altText\":\"\",\"originalImageWidth\":2049,\"originalImageHeight\":932,\"isFillWidth\":false}],\"direction\":null,\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"There were several problems with this setup. First, when replacing styles files, nested components don’t update resulting in a lot of manual work and mistakes. Furthermore, there are always some components that are specific to a carmaker, for example, climate controls. These were placed in the product file instead of the global components file but that resulted in components being all over the place. \",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"It also meant that there were at least 3 files needed for one theme. Lastly, the theming engine used a different way to declare the different styles compared to the designs in Figma. So it was time for a better setup.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Finding Solutions\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"left\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h2\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Around the time we started, Figma released variables. These work exactly like our theming engine: a set of tokens that define all the customizable items in a theme. So we tried playing around with different setups centred around variables:\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"cd588b5a308071baf8b4d46ce037d708765270f6\",\"src\":\"https://s3-alpha-sig.figma.com/img/cd58/8b5a/308071baf8b4d46ce037d708765270f6?Expires=1769385600\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=iAvBTEwmObr-Xf0ykvOtXRcuomr~ACegfxIKzRfkLrLASM4XH7HCDq0oqwc1n8jgw8utoP9GVYMqPUQlK2XmHRxwbSJjPp~ZIRHP8BGDa9svYLVNWb5M3N4yBntPuAdFchc9kF~yDL60abStto8ogWPQqeg5kJySWbCS9dHKyPLfCFm4ft0KuiVi2W9dlViLTwnuRqXGaTZgOCpSBPZv4PFz9UMt8SF-GTO6pRpatu3qyMaUCX8usYrRrv2UXNYwqVdPGQFoNu2K1x70~g9jx2GVWnl7c4RwYFdr0S-18z6cxXb8LusarIl4mZgU3FlSYOqBIYgW5MCgpC1zqaczLQ__\",\"altText\":\"\",\"originalImageWidth\":3125,\"originalImageHeight\":2492,\"isFillWidth\":false}],\"direction\":null,\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"The variables allowed potentially for only one components file and one styles file with different modes for each theme. However, typography was not included yet so that would result in a separate typography file for each carmaker. Furthermore, the idea of using one set of primitive color values for all modes wouldn't work as each mode would have to use a different color palette. And with Figma’s pricing, adding a high number of modes would be unsustainable.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"We played around with other setups but most had the same problem. When dealing with multiple files with component or styles declarations, it is very easy to end up with broken dependencies or components that aren’t overridden by changing their parent files. \",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"After a couple of weeks of trying different setups, we settled on what is the least worst version, given the constraints of Figma.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Our Design System Setup\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"left\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h2\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"We decided to move everything into one big file. For each customer, we duplicate the file and modify it within a set of constraints. This ensures that there are no broken dependencies and makes it easy to iterate on UI themes. Here is the file setup:\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"4acab612ffaa92264b214b520b48680da4f2a65c\",\"src\":\"https://s3-alpha-sig.figma.com/img/4aca/b612/ffaa92264b214b520b48680da4f2a65c?Expires=1769385600\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=F4vXVrVV~dyV3zX4-ulmt9W1FqIeoooZfLC6xzXmPzk5UqVtDGotEZY3YPUOjkRoDJ33-Aqi-RZKHQvFiuGRg9US~kqvI-1~vU6K~y8mLKAKu1kDOTfKVwIIDiA7N6Vfb4PVRzIZ0edJMX0m5i8JVb9LMRnHz9Y-JfMJTXtRUWPaMvsMmO8dQ-zD6ZOyliTvYVYzuHR5Sx5N4VYMNocdpo0wnluljW6vq5CKzvV-R8Ncd3~FFvuX7wsX87RCN-Q4zvp3sOKy90Z2IYqhcIy0xUqrvQajykowXN3cy5KdxKm8OSugMniM9opC48v-KnDZVry7RWIQIOd~52wv6olBZA__\",\"altText\":\"\",\"originalImageWidth\":2389,\"originalImageHeight\":1789,\"isFillWidth\":false}],\"direction\":null,\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Foundations\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h3\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"The foundations form the core of a UI theme. These are all declared as tokens in the design system. We follow the typical setup of a set of primitive values for the color palette, spacing, and radius values. And from those primitive values, we build up our set of tokens.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"863540c61b90d47a6827cdb04ab907e71309f935\",\"src\":\"https://s3-alpha-sig.figma.com/img/8635/40c6/1b90d47a6827cdb04ab907e71309f935?Expires=1769385600\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=Iv53GLy~hf~lPrEvY~0hCuOB9~om56U6h8P71jL7VUT8o5dn5wTqCJ~zveq2NYwKim2s82iIdHcSQXyFZobR79uvYX5r58Zs4e0lhgF9jAHdygAmyDVqbEjAvr7n2WAwFwhzhFg~94dYKliEheWiWZkhUNPsGLkp1H6DopysKoB6t8Xzu8e859wU3SIpPWVAUZWlESe9ZHujbcpBbDs9-D6juYjCpILerw-ILjfGS8VjbgRL9h74xq5w2BxezxL1QAwHZ9J8xp9tsVcrBhVZ-6gyGzxpjoWGS64R8HdDIPeMlU9socV8-wP0Mgf5cPecT4NM97O4kQopFfyKodvHGQ__\",\"altText\":\"\",\"originalImageWidth\":1500,\"originalImageHeight\":677,\"isFillWidth\":false}],\"direction\":null,\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"The tokens consist of colors, typography, icons, app icons, spacing, radius, effects, and visual assets such as images of vehicles or user profile pictures. We currently have over 200 tokens per theme. Each theme can have a set of modes, for day/night themes, but also, for example, different modes adjusting the theme to the color of the car.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"37ea84abe4f98761e3812aae3300531bf6fedf5a\",\"src\":\"https://s3-alpha-sig.figma.com/img/37ea/84ab/e4f98761e3812aae3300531bf6fedf5a?Expires=1769385600\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=Oi9LTSokieVsLS3ByWft1-LL6o8hDW7ucShAjsY-tO4XuS5bf44dB1Sx9RWQ8Ro8V2KQk7rL9~n7IiOa679UxuLrDClpeMrH0-fyjGvDilQLhGhVjb45DjkFQsb3aZCKa4gmQs1UMq7j8gld~6S5zTJEuZ9Eqqih9R88-sUELXNzcLZG6utLdbm3qkQt9rQDxae~FgE4vR5X0EzygWjjOjiPgdR4IyuLvjLo4xvsycJBtzGBE9yiLLEQAtRCwmeWr4fe2HyFAzi6-Tyvo30coUDIU3hl4fA~IXvpg0u9S1ULjnRRFQiyxpOviXicCpimyrl1R8SKHWf26UvFhQDDRw__\",\"altText\":\"\",\"originalImageWidth\":3010,\"originalImageHeight\":778,\"isFillWidth\":false}],\"direction\":null,\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Out theming engine supports more logic than the current implementation of variables in Figma. So we even declare things in the list of variables that aren’t supported in Figma, such as a \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":16,\"mode\":\"normal\",\"style\":\"\",\"text\":\"hasOutershadow\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" boolean that toggles a shadow on components, an \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":16,\"mode\":\"normal\",\"style\":\"\",\"text\":\"animationSpeed\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" value, or a \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":16,\"mode\":\"normal\",\"style\":\"\",\"text\":\"MapboxStyleURL\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" that changes the theme of the map. We document these anyway because the list of tokens in Figma is the source of truth. When we finish a theme, we export the list of tokens with a plugin and with minimal development cost, we have a unique theme!\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"55aaa0bde921d637b3196734d479154930a1aa60\",\"src\":\"https://s3-alpha-sig.figma.com/img/55aa/a0bd/e921d637b3196734d479154930a1aa60?Expires=1769385600\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=gHpAMhMb2dIufcnnFeNQFz9xxtCfNes9GlqOzRmKVyCzidX2WOWdyt24fioH2h7LfZ2hd3TB~i8gvsFuy5kKFSMLCW3KmPyInKwyW83CvcCPZWTPq5ftOIeAAH3tHkn1djykTO1J2xo~dQU6zRvYvakGQHYnC-oirQB1DcePPtR2eNdmd66CPxAS00ZHGh6ERdwY0UzjxfYotfg3uJlS9HA4hLxk8pJT8MQh1aKFz7CJSnOvJM2NeaY1hbLwXZak4EjIg-BvOVMpSen6kVngEk1kBzMmmKM0s5YdSFAbNnoptvrPAsCQzCmKUKZKhFnXdrlK-nY9NS9OltwPElpJxg__\",\"altText\":\"\",\"originalImageWidth\":2049,\"originalImageHeight\":932,\"isFillWidth\":false}],\"direction\":null,\"format\":\"left\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"left\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Fixed Components\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h3\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"The fixed components are the set of global components that are shared between all themes. These can’t be modified for a specific customer. The set of foundational tokens modifies these components for each UI theme. As mentioned earlier, when working with a new carmaker, we duplicate the entire file. We currently have about 20 different groups of components across the in-car and mobile products. So the main drawback is that this set of components must stay identical between all files and this requires manual work. The more customers we work with, the more work it is to keep them up to date between files.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"f027ce338ebbb00be1a4318594b5cd5b9b042c79\",\"src\":\"https://s3-alpha-sig.figma.com/img/f027/ce33/8ebbb00be1a4318594b5cd5b9b042c79?Expires=1769385600\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=nJFJQX-0qkAHjufQX-IDDUo-uQK3lYsemLkbUkyMGZLu2O2BEfvp9Axprll8l7wB8Zo8wmA6~X8V0ETL4-TmfQsDQa26hei3CfSQED3jlOHGrKSs9G09LkSCRZ50xuXipjS1BwelDeTPL5LsA1oJOrdfAN~ZuDtDifu4d8k5P2CQFeDDRmVR0K6YxDnmYIwxThzMF3ErGCcFUB9xg-dhXqrkVV3pahc0qAdi3yc65A7cOqoo6E1994ifQ14Uvw58YS~fuPjqsFkA9iITtv7g85mAnQ0zHlLpC-9xCQwB4pMITa6yicvKk~zBvU3YsOLIr2nkFgU~9NjcUNVUsQQbxw__\",\"altText\":\"\",\"originalImageWidth\":2016,\"originalImageHeight\":902,\"isFillWidth\":false}],\"direction\":null,\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Custom Components\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h3\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Additionally, we have a set of custom components that are specific to each carmaker.  These are adjusted to the particular features of the car we work with. For example, each carmaker will have slightly different climate controls. However, we also include components here that have a large impact on the overall look of the system, such as the media player and widgets. This is to ensure that we can create visually distinct UI themes.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"e23059c17a7cff3636800b1480a4bfda8885505b\",\"src\":\"https://s3-alpha-sig.figma.com/img/e230/59c1/7a7cff3636800b1480a4bfda8885505b?Expires=1769385600\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=jakbRYsVQJhtULEEotmaWuOuNrGSqoB0M~E4eKvffJq6TLHVWk2~Z6zR1hnmV~VQh644wcs133kUhriG6YaY93VOuLuU5MZSjt9UJRjddbRCIq7Wk4bcNdl4Em30qXqfbF8orAOoW1tfnNnd~GuOdRlyw2TDkOgM-5RtqtVDbcrXhD2nZcgGMxFQ4ny63JT6zvy9NiN8ohE7YkicHPx7CyqNzyLDhBROfPUbyHIS4lGtZWVSpwDohBXjuQbCr4j5Ji---1t0~vDpgqPKkcXoAV5N9kvDZN1~xtsJQEI9Q-15nS8aohpX5fHGqewef3g0uNdmzlBEO~omisfxQb9OJw__\",\"altText\":\"\",\"originalImageWidth\":2570,\"originalImageHeight\":1456,\"isFillWidth\":false}],\"direction\":null,\"format\":\"left\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"left\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Screens\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h3\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"The 'Screens' pages have the final designs for the infotainment system and the mobile app. In these files, we also do the specification of the variants and behavior of the components.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"6c43f4fb21b7ef9178da65a7d13505e22ae2c9cd\",\"src\":\"https://s3-alpha-sig.figma.com/img/6c43/f4fb/21b7ef9178da65a7d13505e22ae2c9cd?Expires=1769385600\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=qNwgL6DOg0sv6pXmgrN10i8M-JCCQsxzwbXcs7TyOXiHXbiAVkRsmq8KaTOvptA4V3qY-MXu1oJsKouOTbDQiD9Ui4F-Hv-35W4ey2xK-WC0mtYRzJABdKqTp9mD7FO6TPQlnpuOmdGNrKzRB3O~Ei5TsNZoxVCiJga3x05DGJXDbSarZsGu69M3tI9zPQwWIag7yRxs3ZZg3-boyFQnVWoC33wZJ4khpWOE3c9xiCjmielXl8qJAAeA9xMINA-92uReZLhuap83biGWwdl3CQxQxTjoRQuRmOjr~duPa-wvWUWR5rXhind7q0LCrUxrhsx-JiAeZnz6dCW7hdcGIg__\",\"altText\":\"\",\"originalImageWidth\":2212,\"originalImageHeight\":1010,\"isFillWidth\":false}],\"direction\":null,\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Dealing with Hardware Constraints\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h3\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Often we are dealing with multiple displays inside an interior. For example, each display has its own color calibration and pixel density. To correct for this, we always design for the base pixel density of 160DPI and adjust the artboard size to scale proportionally with the pixel density. This ensures that the designs in Figma will look identical to the car. Moreover, we have set fixed minimum width and height tokens for all interactive elements to ensure that they are easily clickable while driving. These can be adjusted for each car. If there is a color calibration issue, we can fix this by creating special tokens.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Accessibility\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h3\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Included in our base file are several accessibility checks. Most important is the text size which scales up proportionally with the pixel density of the screen. For contrast, we ensure that all text and icon elements use text tokens. We have three surface colors so we run checks with the darkest text color on the lightest surface color to ensure that it passes the contrast checks. We also run color blindness simulations and adjust the colors accordingly.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Final Thoughts\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"left\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h2\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"The advantage of this setup is that it is one self-contained design system setup. Duplicating the file will not result in broken dependencies. It is also easier to work in a single file for designers and developers, especially going back and forth between customizing the UI tokens and seeing the results.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"We are not restricted by the number of tokens so we create as many as we need to design a distinct theme. This gives as much freedom to designers as possible without increasing development cost. Once we finish a UI theme, all we have to do is export the list of tokens with a plugin to our theming engine and that is it!\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"68ff48f26e840eace67a6f0bed8b535783ea124b\",\"src\":\"https://s3-alpha-sig.figma.com/img/68ff/48f2/6e840eace67a6f0bed8b535783ea124b?Expires=1769385600\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=LHOMqhc5CkU8IEL6stUgQJ9FV-EG2kVoUN-xuyWgikJOv0VzASJn8jYkE4pnr6wZnwY0TZvjiwBTtHxg62-8FTkKxclnuEQajCsBRs7X5~suVauF89gAHPaWFzKOD5TtJrWPpO4jNVuQa-AlOlAvhg~jXL1uw3kLJ3QsgBCqI~1~fxO4xTy0GJ6ghyr7tZBIc0xOYUoOyq9TK~vI1sX2ya7rOjrmS3Mt7FrUM-SgU-7OyR0x7bqZGijALMO77BPFJ~ZGDWSMDdIkvZGIXLq76YBXb2ni~G7UDGRZAcqc0MXWJOo72DDD1~EgDQjFxLM1Ie-y38fc8hA8k6NQ8YHe~g__\",\"altText\":\"\",\"originalImageWidth\":3106,\"originalImageHeight\":960,\"isFillWidth\":false}],\"direction\":null,\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"The big drawback of this setup is the fact that the set of fixed components must be kept up to date between files. So if we are working with five different carmakers and want to update the button component, we will have to go through each file to update the component. Keeping all files in line with each other will be labor intensive. However, since development is the real cost, it is optimal that this work doesn’t fall on developers as it did in other setups.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"The whole process from deciding to redo the entire system to the finished setup took about 3-4 months with two designers, and two to four developers. We had plenty of other work ongoing so it was not a full-time effort. We are trying to do something that isn't really supported by Figma but thanks to its flexibility we did end up with a system that works. The result is that we can create a totally bespoke-looking infotainment system and implement it in less than two weeks instead of months. \",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"root\",\"version\":1}}","itemId":"74a1903b-5353-4325-b47a-2610388e8506","fieldSchemaId":"3084d9ba-ab55-4e5a-931b-b9db3d09105f"},{"id":"85e8ec9b-5e22-4978-a8d0-65d3f670a51b","value":"CPO - Android Automotive","itemId":"74a1903b-5353-4325-b47a-2610388e8506","fieldSchemaId":"0a981f8a-7dbb-440d-a940-25d9060c9b11"},{"id":"04bbb22d-adb8-4946-abf8-49be5c97c17a","value":"{\"root\":{\"children\":[{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Specialized in automotive UX research and design, with experience delivering intuitive, user-centred digital products across the automotive and software industries. I’ve worked with a wide range of companies and startups, translating complex systems into seamless, scalable experiences that align user needs with business goals.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"root\",\"version\":1}}","itemId":"74a1903b-5353-4325-b47a-2610388e8506","fieldSchemaId":"0b77f83b-c31a-4889-b9b3-9a6d2e41fc86"}]},"840b0f15-1e38-49a9-8e49-be9e609cb518":{"id":"840b0f15-1e38-49a9-8e49-be9e609cb518","index":"%f","collectionId":"d4a5b68c-8afd-4bbe-a7ac-e9a8422fedde","fields":[{"id":"ed0d8c31-703f-460d-96ca-316dfe06809e","value":"CI CD for OpenHarmony Project — GitHub Action","itemId":"840b0f15-1e38-49a9-8e49-be9e609cb518","fieldSchemaId":"f2ba59b9-49cc-4ec6-9416-bda99d4c8383"},{"id":"6dfa4572-b005-45f7-9891-56bb973f989a","value":"ci-cd-for-openharmony-project-github-action","itemId":"840b0f15-1e38-49a9-8e49-be9e609cb518","fieldSchemaId":"402ba26f-8f6d-4f5f-bf20-62e6549f4ad4"},{"id":"ab4a543f-e117-4121-b3fc-984fd7da6556","value":"2024-12-05","itemId":"840b0f15-1e38-49a9-8e49-be9e609cb518","fieldSchemaId":"b7712ee6-f9fd-4781-8c5c-e7e10ce8f81e"},{"id":"76ff96b9-3928-434a-865f-c5de4defe862","value":"{\"image\":\"00ab9d167aded835d11686bd0b9a232b704245fc\",\"imageThumbnail\":\"64efff1e20a9432170f17385c1a12932037ae48b\",\"originalImageHeight\":2048,\"originalImageWidth\":3584,\"altText\":\"\",\"fileName\":\"Open Harmony.png\"}","itemId":"840b0f15-1e38-49a9-8e49-be9e609cb518","fieldSchemaId":"1f58afa6-2748-4188-b4a4-f1e54e37eca9"},{"id":"3c39ae69-9466-4940-857c-102a200bbf70","value":"Payam Zahedi","itemId":"840b0f15-1e38-49a9-8e49-be9e609cb518","fieldSchemaId":"df1c88d1-4bd8-4ecd-9059-463b9589de92"},{"id":"c963e47f-3220-4583-9d3d-56de068588d9","value":"{\"root\":{\"children\":[{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"I'm a Mobile Developer with 7+ years of experience in test-driven mobile app development, specializing in Flutter, Kotlin, and Android Java. I've worked on a range of applications in various industries. I'm also an active contributor to open source projects and have worked on more than 10 projects to date.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"root\",\"version\":1}}","itemId":"840b0f15-1e38-49a9-8e49-be9e609cb518","fieldSchemaId":"0b77f83b-c31a-4889-b9b3-9a6d2e41fc86"},{"id":"adfb3516-82b7-4f86-b351-3bb3713475d5","value":"{\"root\":{\"children\":[{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"When developing \",\"type\":\"text\",\"version\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"OpenHarmony\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"link\",\"version\":1,\"rel\":\"noopener ugc nofollow\",\"target\":\"_blank\",\"title\":null,\"url\":\"https://docs.openharmony.cn/pages/v4.1/en/OpenHarmony-Overview.md\"},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\", we typically use \",\"type\":\"text\",\"version\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"DevEco\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"link\",\"version\":1,\"rel\":\"noopener ugc nofollow\",\"target\":\"_blank\",\"title\":null,\"url\":\"https://devecostudio.huawei.com/en/\"},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" Studio to write our code, build the project, test it, and run it on our devices, with DevEco Studio taking care of everything under the hood.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"However, as engineers, we love to automate repetitive processes, right? This is where CI/CD workflows become incredibly useful. GitHub Actions, in particular, is a popular and highly customizable workflow solution.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"In this article, we’ll explore how to create a workflow on GitHub Actions to build and verify our OpenHarmony application.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"A Little Context\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h2\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"To write our GitHub Action workflow, we first need to understand how DevEco Studio works under the hood. Specifically, what tools does it install, and how are they used? In this article, we won’t dive too deep into all OpenHarmony tools and DevEco Studio capabilities. Instead, we’ll provide a brief overview to understand the components needed for our workflow.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"hvigorw\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"link\",\"version\":1,\"rel\":\"noopener ugc nofollow\",\"target\":\"_blank\",\"title\":null,\"url\":\"https://developer.huawei.com/consumer/en/doc/harmonyos-guides/ide-hvigor-commandline-V13\"}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h3\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Hvigor is a simple build tool, much like Gradle for Android, but designed specifically for OpenHarmony apps. It helps you manage tasks, dependencies, and builds easily. DevEco Studio uses \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":16,\"mode\":\"normal\",\"style\":\"\",\"text\":\"hvigorw\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" to build, test, and run apps on devices.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"ohpm\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"link\",\"version\":1,\"rel\":\"noopener ugc nofollow\",\"target\":\"_blank\",\"title\":null,\"url\":\"https://developer.huawei.com/consumer/en/doc/harmonyos-guides/ide-ohpm-cli-V13\"}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h3\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"OHPM (OpenHarmony Package Manager) is akin to npm for JavaScript, but tailored for OpenHarmony applications. It helps facilitate the publishing, installation, and management of dependencies for shared packages. DevEco Studio uses OHPM to manage third-party libraries within OpenHarmony projects.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Code Linter\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"link\",\"version\":1,\"rel\":\"noopener ugc nofollow\",\"target\":\"_blank\",\"title\":null,\"url\":\"https://developer.huawei.com/consumer/en/doc/harmonyos-guides/ide-command-line-codelinter-V13\"}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h3\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"OpenHarmony’s Code Linter is a tool that checks ArkTS and TypeScript code for best practices and coding standards. It helps developers identify and fix issues during development, ensuring high-quality code.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Now that we have a good understanding of the tools involved, the next step is to bring these components together into a cohesive GitHub Action that can automate our workflow.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"oh-action\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h2\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":16,\"mode\":\"normal\",\"style\":\"\",\"text\":\"oh-action\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" is a reusable GitHub Action that helps you prepare the development environment needed to build your OpenHarmony project. Essentially, it is responsible for providing the OpenHarmony SDK and command-line tools required for building, testing, and managing your project, making it easy to add to your CI/CD workflows.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":16,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Simple Example\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h2\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Let’s look at a really simple example of using \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":16,\"mode\":\"normal\",\"style\":\"\",\"text\":\"oh-action\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" in a GitHub Actions workflow to build an OpenHarmony application:\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"38c29ca66ce4189b6af1f847adb2e90d53c3007d\",\"src\":\"https://s3-alpha-sig.figma.com/img/38c2/9ca6/6ce4189b6af1f847adb2e90d53c3007d?Expires=1768780800\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=Mk0uclZdKH4rdcI523GX7mD3Q1DxkMPyQZwiyXngWLvtmYPODH8nJG5lkvHD5h9vKIoM7zSnKNYbTzMETdQ4Ku-rnRodlG4YSXVoUW9gg3zwKjSW1Tyz4Cna-iXXDer9~U3YbZ32OpIz8OjjjlZmGCs1hhNvPS~H8mV39YSgy6hmSOL5~9mZF6VdbwpXxVAWoDlP8QJcM7Lz4MppeP3M8ZydpoH~HBqr6Dbly54yE1g0TlXyFIO6oYL~HjbnCd~sJR-OrQHxINRlfODBpWyVMrCmrko8Y7~HtSXE~NgAvhGMPZRett8ZfVQK9PAay1FzHn-h2Orm-QUatBzGsUu8RA__\",\"altText\":\"\",\"originalImageWidth\":3484,\"originalImageHeight\":2456,\"isFillWidth\":false}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"In this example, we have a simple GitHub Actions workflow that:\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Checks out the repository code using the \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":16,\"mode\":\"normal\",\"style\":\"\",\"text\":\"actions/checkout\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" action.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Sets up the OpenHarmony environment using \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":16,\"mode\":\"normal\",\"style\":\"\",\"text\":\"oh-action\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\".\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":2},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Builds the project, verifying the availability and versions of \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":16,\"mode\":\"normal\",\"style\":\"\",\"text\":\"ohpm\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" and \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":16,\"mode\":\"normal\",\"style\":\"\",\"text\":\"hvigorw\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" to ensure the environment is correctly configured.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":3}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"list\",\"version\":1,\"listType\":\"number\",\"start\":1,\"tag\":\"ol\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Real-World Example\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h2\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Now that we have a basic understanding, let’s explore a more complete, real-world example of using \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":16,\"mode\":\"normal\",\"style\":\"\",\"text\":\"oh-action\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" to build an OpenHarmony project.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"96499b8c48292450d0d6b2a6e3aa569caa46f7c4\",\"src\":\"https://s3-alpha-sig.figma.com/img/9649/9b8c/48292450d0d6b2a6e3aa569caa46f7c4?Expires=1768780800\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=ntVjtkPg6oTU1xCDY2t6fshc0yjA4HGXttHOwkXIue7XlpWdcSWk~suDdspD84AigfNnKEBfdIk61PuZWodhmtgBocdzsApGVzxDNf~eWZpYow~fxa4VCZEb7j2m35UDFSCx1jq1dr8aGG3j5~GWLhcZBO7LExGA~FTBgVasaUnx8TFgwax7zodWoQeP257HCZwRp1AOmfNNdGB9SMOYWRZrMgFZ1M7eMeKk2isrHlaUm3Zy9BV6xkGQRtd-SOUitsBN7wJ6Z15eAzthNJwBGevQC0CVDWW3O1dAk1VMAJg~5-J1QbljTZBF2O81kJz~KONKa440lERgXgdMTOXvrA__\",\"altText\":\"\",\"originalImageWidth\":3484,\"originalImageHeight\":2904,\"isFillWidth\":false}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"What is important is:\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"children\":[{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Installing dependencies\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" using \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":16,\"mode\":\"normal\",\"style\":\"\",\"text\":\"ohpm install --all\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" to ensure all project dependencies are available before building. This step ensures that every required package or library for the OpenHarmony project is properly installed.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":1},{\"children\":[{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Building the project\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" using \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":16,\"mode\":\"normal\",\"style\":\"\",\"text\":\"hvigorw\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\", which cleans the project environment, accepts licenses, and then builds the application package. This step (\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":16,\"mode\":\"normal\",\"style\":\"\",\"text\":\"assembleHap\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\") is crucial to make sure everything compiles correctly and produces the final output, ready for deployment or testing.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":2}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"list\",\"version\":1,\"listType\":\"number\",\"start\":1,\"tag\":\"ol\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"This example represents how you can use GitHub Actions in a more practical scenario, automating the entire workflow for your OpenHarmony project from setup to build.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Conclusion\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h2\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"In this article, we explored the inner workings of DevEco Studio, including the tools it utilizes to manage, build, and test OpenHarmony projects. We also learned how to leverage \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":16,\"mode\":\"normal\",\"style\":\"\",\"text\":\"oh-action\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" to create a custom CI/CD workflow on GitHub Actions. With \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":16,\"mode\":\"normal\",\"style\":\"\",\"text\":\"oh-action\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\", you can automate setting up the OpenHarmony SDK and command-line tools, installing dependencies, and building your project—simplifying the process significantly.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"By integrating \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":16,\"mode\":\"normal\",\"style\":\"\",\"text\":\"oh-action\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" into your CI/CD pipeline, you ensure that your development workflow is not only efficient but also consistent across different environments. For more specific use cases and further customization, be sure to visit the \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":16,\"mode\":\"normal\",\"style\":\"\",\"text\":\"oh-action\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" GitHub repository and explore the possibilities.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"root\",\"version\":1}}","itemId":"840b0f15-1e38-49a9-8e49-be9e609cb518","fieldSchemaId":"3084d9ba-ab55-4e5a-931b-b9db3d09105f"},{"id":"96df1bc0-9653-4ad1-9a59-1a896bc9ffce","value":"Software Engineer, Flutter Developer","itemId":"840b0f15-1e38-49a9-8e49-be9e609cb518","fieldSchemaId":"0a981f8a-7dbb-440d-a940-25d9060c9b11"}]},"f4e5f709-ebad-44e5-8d9c-69abed2fdf8b":{"id":"f4e5f709-ebad-44e5-8d9c-69abed2fdf8b","index":"\u00267","collectionId":"d4a5b68c-8afd-4bbe-a7ac-e9a8422fedde","fields":[{"id":"fe8d8ff0-cba5-4f83-baad-3b8e568eda64","value":"CPO - Android Automotive","itemId":"f4e5f709-ebad-44e5-8d9c-69abed2fdf8b","fieldSchemaId":"0a981f8a-7dbb-440d-a940-25d9060c9b11"},{"id":"b66fdb2b-4782-49e3-ae4b-d2d046c0f4e0","value":"a-deep-dive-into-our-powerful-theming-engine-for-android-automotive","itemId":"f4e5f709-ebad-44e5-8d9c-69abed2fdf8b","fieldSchemaId":"402ba26f-8f6d-4f5f-bf20-62e6549f4ad4"},{"id":"72932d6e-5571-42d9-80bf-7363e9303fcc","value":"A Deep Dive Into Our Powerful Theming Engine for Android Automotive","itemId":"f4e5f709-ebad-44e5-8d9c-69abed2fdf8b","fieldSchemaId":"f2ba59b9-49cc-4ec6-9416-bda99d4c8383"},{"id":"ca1dc25d-5388-4be1-9405-0ccd1681f82f","value":"2024-03-26","itemId":"f4e5f709-ebad-44e5-8d9c-69abed2fdf8b","fieldSchemaId":"b7712ee6-f9fd-4781-8c5c-e7e10ce8f81e"},{"id":"84ce7a6e-b23f-4bae-899b-7f424d839264","value":"Casper Kessels","itemId":"f4e5f709-ebad-44e5-8d9c-69abed2fdf8b","fieldSchemaId":"df1c88d1-4bd8-4ecd-9059-463b9589de92"},{"id":"cd5437c9-dae0-4f8c-8edb-91d49b3fd6a1","value":"{\"image\":\"7394d6a74ec6110359b89c5f8e966a3ab1bc5d51\",\"imageThumbnail\":\"d26897b9f57b4ac5b992006e1335dcd95b7d487a\",\"originalImageHeight\":1200,\"originalImageWidth\":1800,\"altText\":\"\",\"fileName\":\"aa_theme.png\"}","itemId":"f4e5f709-ebad-44e5-8d9c-69abed2fdf8b","fieldSchemaId":"1f58afa6-2748-4188-b4a4-f1e54e37eca9"},{"id":"1f1f7d4b-dd03-4bdc-8bb0-aa10457fd4f6","value":"{\"root\":{\"children\":[{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"SnappOS is an Android Automotive infotainment system aimed at carmakers from low-budget micro-mobility to high-end sports cars. For each brand, we ensure that the user experience is bespoke and that no two instances of SnappOS will look alike. That is why we’ve designed SnappOS to be as customizable as possible. There are three levels: hardware layout, services, and most importantly, the UI theme.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"ed27f3735ed26cf11d505b320d3bc5eba1a76eda\",\"src\":\"https://s3-alpha-sig.figma.com/img/ed27/f373/5ed26cf11d505b320d3bc5eba1a76eda?Expires=1769385600\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=lkDSoGGQDDBbOrouNbJOwj6OMSNwCMFHN1B1tlq8qDcSjWvHcqx3yG4gdLv9QgoShrXtLVKu3g2cM59A~j9SVvQ8GtgbFTIfsyIfEX8dlMO44~I~KVyPvfQ2aK3eOfpph13Lmgcn5MepeOw6LIQ1YR9H48fWsgf0GW-0Pwl9usTh58aH6NMlrckydF044yyj32EIp~Ef6XD87~KMx6YVHtBr3MPtnou8loIdtCNeiMSS4mBvAViS47tYiiOTgUZMn2zbrTpaZL8Q9KjPpvIhakeXK2BsKuzownS2v7-F8tq4HvC6qARsWgQoLpiZ8XnZwGGAxAoKFs-aQxr~PjIqsQ__\",\"altText\":\"\",\"originalImageWidth\":1872,\"originalImageHeight\":974,\"isFillWidth\":false}],\"direction\":null,\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Hardware Layout\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"left\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h2\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"No two interiors are the same. We’ve designed SnappOS so that it can be easily adapted to each different screen layout and dashboard configuration without breaking the architecture of the system.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"ee1e29fd9bd181373fa32796a8fdf77dea40b9bf\",\"src\":\"https://s3-alpha-sig.figma.com/img/ee1e/29fd/9bd181373fa32796a8fdf77dea40b9bf?Expires=1769385600\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=Zk0svuc8kkg~2nNUd7-WWm5~cWFh-DvmzBNitUJdQ6PxeGXKTUZxju125MyvBeF8YzCann0ZtrPzMgYySuuB6bmT1q2L~jV~9v-HAO9mPI~Ujn0lqsvl5XjPL-fpQIn7o9GQkW2lOiJom1vAHlcDJFw0KLqOPMiRT3Cdihm2-KZ25l0eKDTERLXxxn6JTInptr411ZTjytL-l3u8OQEK9QNtgkH5tknOKLAnmiHDoOizuN4lLaXe5~63GKtJHn2nOlXHtn0jlmx3KPHGcVEAI8KFyk2~KheWm1giDFlj32QdaeGJgXgJ34v8ZhCcxo1y3pZJDgKx49S3pZE3u5jozQ__\",\"altText\":\"\",\"originalImageWidth\":3601,\"originalImageHeight\":1240,\"isFillWidth\":false}],\"direction\":null,\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"SnappOS supports the instrument cluster, head unit, and passenger displays. For each, we designed a modular architecture that makes it easy to adapt to different screen sizes and feature sets.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"To achieve this, we always design for the smallest display size possible so upscaling is easy. We also test all of our designs on different screen layouts, from narrow vertical ones to widescreen. Then, for each of the important components of the launcher, we created different versions to fit the different display sizes so we can build up the UI with these Lego blocks.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"83686b3a8f58dbd400c710202ccff5df031d7888\",\"src\":\"https://s3-alpha-sig.figma.com/img/8368/6b3a/8f58dbd400c710202ccff5df031d7888?Expires=1769385600\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=comwOHrH7mOUxzMJ8-zsVgCVeSwP5jJ-5WQOXVPaLIAYF-itqUw2bt860kd8tDr3CGhtfmJRY-RqUGXm2Ye3oW8WkLYbR-Mxdxb40ZTXjlmidcZmY4oAijQkRWAlKSzfCxOLcxjelyueYTzCiBqP-L0i3xrm0xWJ1IW7RliLacGfDH2F8Qe8im83U6rd~R5PnZ2J3UxbrgEAJhIs9HGo-Wi5WjqDat2YC8E0EBmSkaq89uAo6Tkts75xW2N9KyX8I4CJRfm8KhBEys4qh3qubWQdk1yJKn35jKwE-L8vgwBNAFELgkVRWCBK6aaPwVr4IDL8hWqMgp7PYUw0Dk3yAQ__\",\"altText\":\"\",\"originalImageWidth\":1936,\"originalImageHeight\":1008,\"isFillWidth\":false}],\"direction\":null,\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"We can then easily adapt to specific features. For example, physical or touch-based climate controls.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Services\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"left\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h2\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Next up are the third-party services. Any Android Automotive services work in SnappOS. But it depends on the type of carmaker what strategy is best. We see three different approaches:\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Hand over most of the services to Apple CarPlay and Android Auto, for which we have designed SnappOS Light\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Supply SnappOS with a set of pre-installed system apps\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":2},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Integrate an app store. Since we follow Android’s guidelines, SnappOS can handle both Google Automotive Services and alternatives.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":3}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"list\",\"version\":1,\"listType\":\"number\",\"start\":1,\"tag\":\"ol\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"252e3af8b155196ecd9c4a5074e9c4e977f35b83\",\"src\":\"https://s3-alpha-sig.figma.com/img/252e/3af8/b155196ecd9c4a5074e9c4e977f35b83?Expires=1769385600\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=CD8N~JaTb8QsHHel-v7DWhptkMonQiZlcwoKhmSrcFT21iHHgs3uKb14DHO1qXT-TJ1uyIsh4Hfww1G5-ZD74lHwLMSuAv47CMvhGN8koKPg5u1L-bTNn~RMXlHj6bw9pYu7MIkcHlugdgUNuk2HJ3WCmEbJrSCcZl0oDdVjQJJSSVLr8w3Gaue2QVAjB~wVb4Ahzq6eicAuvxReiVVTjq4nMOvPVD4EomRwn-52srESPZCeg62nnQnsFNOX8uXbGgH~HphMpD~7Bjh7qTXq-uRVSclV6y11pIMzO~1J3hQC9qu48Ldqjf30m6SFpKHBlO3DFM6Njvubm8ZQDcN6Ag__\",\"altText\":\"\",\"originalImageWidth\":3320,\"originalImageHeight\":1040,\"isFillWidth\":false}],\"direction\":null,\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"UI Customization\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"left\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h2\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"The last layer is the most fun. We’ve developed our own theming engine that can handle the most elaborate UI changes and we set up a fast development process around this. This means that we can go from nothing to a deployed unique theme in two weeks.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"The most important part of the theming engine is that everything from the apps down to the SystemUI is built with JetPack Compose. JetPack Compose is Android’s recommended toolkit for building UI and it makes development easier and faster. It also allows for cool stuff like dynamic changes of the UI theme without losing the state of the system. Or seamlessly changing the UI depending on the drive mode:\",\"type\":\"text\",\"version\":1},{\"type\":\"linebreak\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"247ca129036f07c031da2873842f0ecf387f5279\",\"src\":\"https://s3-alpha-sig.figma.com/img/247c/a129/036f07c031da2873842f0ecf387f5279?Expires=1769385600\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=RPGHBG9csdOUa3DuWhY6wVI2KwJwyfgxFAZjOCcwEGLVjW-KxJ3fcGOvXThba3bwfcplWE~0Dg8rBenU3BC8pnp7nb5wc4zZ8ZXTJpHt94K3idL6vn8Sa6VwUB8yIw2Ga-mxcfytJ6YjXSPhMDbwOrwqCi13USBbeNMKa~SRcNS8VcWNDaZt3AsteKf39pPQz88O3QJJcallZLInW8U-BsNa6BWfsi0qZ6005sRwCxJoR1oEAnt427r2FEzBGPFNKqXsXCsZewblFiTygipS2-yp7Km~VghQQhQ~89kxeD930ROEpop-Gvvf2TqK6Y0vXfDDVLgZon7O3rt1vsqtCQ__\",\"altText\":\"\",\"originalImageWidth\":3106,\"originalImageHeight\":1040,\"isFillWidth\":false}],\"direction\":null,\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"A lot of work went into creating a design system. Thanks to the newly released variables in Figma we’ve been able to create an incredibly powerful library of components that allows for nearly limitless design changes with minimal work. These components are then built with JetPack Compose. \",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"We make sure that our Android and Figma libraries are perfectly in sync and that components are built in exactly the same way. In the next article, we will dive deeper into how we set up our Figma file, but at the core is the list of tokens we define. Each component has a set of unique tokens and by changing the value of these tokens, we can change the look and feel of the entire UI theme. \",\"type\":\"text\",\"version\":1},{\"type\":\"linebreak\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"c895d6cfa02cdf6ce999beeda1b605e3bcf8a719\",\"src\":\"https://s3-alpha-sig.figma.com/img/c895/d6cf/a02cdf6ce999beeda1b605e3bcf8a719?Expires=1769385600\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=qRhR-1TeiWdXm6jCagRRVaSCnt1-CCBW5-9TAb8-MWK4J8c3GqxJzg3tnc9FMZ0k-rpR9s3RyrmFsWRFrFnWel2~5~d~QihCEjzwaXTWcBQgkgfNKylNVMc9q~eSsIypTTYY~raA11wk1uY2F3NuUH8wrRZEBXj79BLvxhxvhoer7OfRTDFHvFksctLjRuYrQcxUkZc0cuyrRab2ytOLirjnaEdvGwmmrbPnbODIPbOZCluFfxuPn98X-Cl1J5ZWjvpfSvnODKjKGnqia-srqMU5vav9HACFnCtR92ntU-vb1t4qKb~LrJPxwowrXlAjUHHaIBj4eaTwK6wuxJRY7w__\",\"altText\":\"\",\"originalImageWidth\":2484,\"originalImageHeight\":1010,\"isFillWidth\":false}],\"direction\":null,\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"So the process for creating a new UI theme is essentially to change the values of the tokens for colors, spacing, radius, effects, and more. Our theming engine supports more advanced logic than Figma currently supports. For example, we can pass a boolean with each component to toggle a shadow, or we can use a set of boolean and text tokens to create more advanced, custom layouts that are currently not supported by Figma (at least in an automated way, we do it by hand). In the end, we have a long list of tokens that can easily be exported from Figma as a JSON and adapted to code.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"But that is not where it ends. We found that there is a small subset of components that heavily influence the look of the system. For example, in our launcher, the media player and menu bar weren’t different enough. That is why we have a set of ‘custom components’ that we adapt for each theme to have a bigger distinction.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"498536968cd07466dbecc826557f36a2aec576ae\",\"src\":\"https://s3-alpha-sig.figma.com/img/4985/3696/8cd07466dbecc826557f36a2aec576ae?Expires=1769385600\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=jvnXoVoHV-ekj6OkrvI~~L~1d7rUjT9YGa7bFrzOniWLvyKb-TMfZuOpchOcGBGCyHZS1kcdi~1FMf6gFq7Blx3g0oScH5CuBnsTM-2zb6p0oRK8nV9FMnDDMaGNbd~H65cUV3pkOexDvn86sDRlN~g9z8g9mqnMqot-TX5rysQnyVzdQS0EqjTyujjiIm6p-b9foSuQMLg4FHOSoleYy-mBsZqsnwqR3REhIp2dEuG0U8pdAN5IMNWJZNVQ0mk-ICnMjxBpaNG~0v4rLKUhIgtmf3nE8ee7eYywlJT7vx0NpMPNa0f9FbnM3NYiz5VH4JXHvEac3iBlrjb8xKYoUg__\",\"altText\":\"\",\"originalImageWidth\":1540,\"originalImageHeight\":637,\"isFillWidth\":false}],\"direction\":null,\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"All of the components of a theme are captured in an APK. We’ve set up our theming system in such a way we can remotely push themes to devices in the field without the need for major updates. This allows for a whole range of new opportunities, for example, to make themes unique to a vehicle and allow a customer to specify things like colors in the purchase process just like for other aspects of the car’s interior. \",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"A lot of work has gone into our theming engine. And the result is that we can design and deploy totally different looking instances of SnappOS in a matter of days. We can ensure that any carmaker we work with can express their brand properly and offer a bespoke experience.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"18cc0ac73f973eec5787d97c5c693b24131a71e5\",\"src\":\"https://s3-alpha-sig.figma.com/img/18cc/0ac7/3f973eec5787d97c5c693b24131a71e5?Expires=1769385600\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=aBpFjwmZB5BzqsTrDpphxDDL0IDonSqe5mAAxB9pb-R-8j4R-pW5Xia83TsrvlaPPG6MgobV-iiEXIaB1YH1e6dNVQom9Xfp~L~nWZIZc3HqVKlQyq~LfbyxP5HXQBd5Sg0-ItBMh1cL2nyL6uCOLpxIZwttDzr0Q9FwPJCyxD10gKOsg8COGOTlR7bz6r0qkGqy08u2t3ZgbGTPCP5DAdGEn-k1JbKLfItZ9oYFxIIMHQH8ymetfRO5NQn~xSZd6K2h-PRxxEASFEopHiw7Kq~cb5y1Q0uTL-WKIIiVM2w3NtFBeUboZC9kZOvo-NIiqBzUF6aucFUgyYaxf9yuDw__\",\"altText\":\"\",\"originalImageWidth\":3106,\"originalImageHeight\":960,\"isFillWidth\":false}],\"direction\":null,\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Next, we will share more about how we’ve set up our Figma file structure and design system to allow for rapid design. And then we will share a use case of where we designed and deployed a unique UI theme in less than two weeks. Sign up below if you'd like to be notified when we post these articles!\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"root\",\"version\":1}}","itemId":"f4e5f709-ebad-44e5-8d9c-69abed2fdf8b","fieldSchemaId":"3084d9ba-ab55-4e5a-931b-b9db3d09105f"},{"id":"59271d6b-434e-4b0a-90b9-45fcda7c985c","value":"{\"root\":{\"children\":[{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Specialized in automotive UX research and design, with experience delivering intuitive, user-centred digital products across the automotive and software industries. I’ve worked with a wide range of companies and startups, translating complex systems into seamless, scalable experiences that align user needs with business goals.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"root\",\"version\":1}}","itemId":"f4e5f709-ebad-44e5-8d9c-69abed2fdf8b","fieldSchemaId":"0b77f83b-c31a-4889-b9b3-9a6d2e41fc86"}]},"1a52d56d-e318-40ff-8553-f3e4be29839e":{"id":"1a52d56d-e318-40ff-8553-f3e4be29839e","index":"%O","collectionId":"d4a5b68c-8afd-4bbe-a7ac-e9a8422fedde","fields":[{"id":"331b5516-48e0-43f3-9d18-58c051cd48f4","value":"{\"image\":\"6fd692568bfb6478e1806da72fb489c9669c0ce1\",\"imageThumbnail\":\"36e77f851415b68b288ba81a3484e5c8b9b73de3\",\"originalImageHeight\":1390,\"originalImageWidth\":2086,\"altText\":\"\",\"fileName\":\"Harmony_hero.png\"}","itemId":"1a52d56d-e318-40ff-8553-f3e4be29839e","fieldSchemaId":"1f58afa6-2748-4188-b4a4-f1e54e37eca9"},{"id":"4cb02444-d592-486d-825f-c63b87b5f376","value":"HarmonyOS App Development 101","itemId":"1a52d56d-e318-40ff-8553-f3e4be29839e","fieldSchemaId":"f2ba59b9-49cc-4ec6-9416-bda99d4c8383"},{"id":"aafcbf79-8d66-4617-8a7e-c5eecfab3525","value":"harmonyos-app-development-101","itemId":"1a52d56d-e318-40ff-8553-f3e4be29839e","fieldSchemaId":"402ba26f-8f6d-4f5f-bf20-62e6549f4ad4"},{"id":"dbb442dc-8473-45e1-8674-5f46dbf53ff9","value":"2025-01-19","itemId":"1a52d56d-e318-40ff-8553-f3e4be29839e","fieldSchemaId":"b7712ee6-f9fd-4781-8c5c-e7e10ce8f81e"},{"id":"797afc36-43a1-4f95-84a2-cac6fceded18","value":"{\"root\":{\"children\":[{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Huawei have taken a big step in moving away from the Android platform with the launch of new devices running HarmonyOS Next.\",\"type\":\"text\",\"version\":1},{\"type\":\"linebreak\",\"version\":1},{\"type\":\"linebreak\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"This is a brand new operating system that had been design specifically for devices. This means it is lightweight, supports a range of device types, is modular and extensible.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"In this article we aim to give you an overview of what is available to developers wishing to build apps on this new platform. To that end, we will be looking at the following topics:\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"The IDE\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Programming Languages\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":2},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"UI Framework\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":3},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Build Tools\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":4},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Package Management\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":5},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Running code (devices/emulators)\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":6},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Debugging\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":7},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Testing\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":8},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Profiling\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":9},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Other cool stuff\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":10}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"list\",\"version\":1,\"listType\":\"bullet\",\"start\":1,\"tag\":\"ul\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":2,\"mode\":\"normal\",\"style\":\"\",\"text\":\"If you are curious about the Harmony platform, its Open Source foundations (OpenHarmony) and its global reach (Oniro), \",\"type\":\"text\",\"version\":1},{\"children\":[{\"detail\":0,\"format\":2,\"mode\":\"normal\",\"style\":\"\",\"text\":\"we have written about it here\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"link\",\"version\":1,\"rel\":\"noopener\",\"target\":null,\"title\":null,\"url\":\"https://medium.com/snapp-mobile/harmony-os-harmony-next-openharmony-and-oniro-explained-61389636c00e\"},{\"detail\":0,\"format\":2,\"mode\":\"normal\",\"style\":\"\",\"text\":\".\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":2,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"The IDE\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h2\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"The development environment for Harmony apps is currently a Huawei-based IDE which is based on the JetBrains IDE platform.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"The good news is that JetBrains offers a world-class IDE platform and it makes for a very solid development experience for Harmony apps.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"For those, wanting to keep to the Open Source side of Harmony (\",\"type\":\"text\",\"version\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"OpenHarmony\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"link\",\"version\":1,\"rel\":\"noopener ugc nofollow\",\"target\":\"_blank\",\"title\":null,\"url\":\"https://www.openharmony.cn/\"},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" and \",\"type\":\"text\",\"version\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Oniro\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"link\",\"version\":1,\"rel\":\"noopener ugc nofollow\",\"target\":\"_blank\",\"title\":null,\"url\":\"https://oniroproject.org/\"},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"), you are out of luck right now. DevEco Studio is proprietary, albeit free to use software.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Let’s look at a couple of IDE features — these should not surprise you but hopefully demonstrates that the platform is already in a good place (as far as IDEs go).\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Project Creation\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h3\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Creating a project will look familiar already for many. There are a few project templates to choose from to bootstrap your project.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"d0f23290fa28511596b1aec4a890d496f2222218\",\"src\":\"https://s3-alpha-sig.figma.com/img/d0f2/3290/fa28511596b1aec4a890d496f2222218?Expires=1768176000\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=sCoGClLCek1qsrWNntirouHe1nf8NqY9dOLFWr7afuM5u8fRJCz39rlQe~HymPX7Cz7~U349o-StXlH5IeGAmBMZ6CnXjFidSiWUL2eCfeS7bsMJUTfVnhsNnr9-jQMTFUaE7nINvLgFpYdkml7Fr1Z3eJZ17IUDrHwva8g0XPQdzSIdXYyUeHvMJwZcW5Hk1wQuaWvjXVLB-NN4KAhEL6VrmY9dDjLNlm6J6R0SpvD~60GryGruIZxjHC5CWp67Gs9U9Icmgz9f2sZqicw6x4ZrWO7g7iM06Q9j8PR01h8dHSjTUwhe4Q8zflsfH~wEeFH7RWi9SmhNOpe-bNyTTg__\",\"altText\":\"\",\"originalImageWidth\":1129,\"originalImageHeight\":727,\"isFillWidth\":false}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"You will also then need to configure a couple of options — a couple of notes on these (which could probably be expanded into a separate article).\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Firstly, the bundle name is used for app signing and identity. Secondly, an app supports a single SDK version. (The latest SDK version is 13, however version 11 is still widely used.) Thirdly we can specify the module name. The default (‘entry’) isn’t very descriptive. If you have a single-module app, you can call it ‘app’ or similar. For multi-module apps, you would typically call it something like ‘view’ or ‘ui’ — basically it’s the module that is used to start the app.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"IDE Overview\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h3\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Most of what you will find in the IDE is pretty standard for a JetBrains based IDE.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"90ab51339e249d3d74d01e36a7c61ff472a3f73e\",\"src\":\"https://s3-alpha-sig.figma.com/img/90ab/5133/9e249d3d74d01e36a7c61ff472a3f73e?Expires=1768176000\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=CLjtf5ZWipX08lN4tL~yd85-78Bh6K21Fc0slurdO~2DnQHRLBitsUcct8UtT2XBXkwS-XlNlIjQIYQrDhveP2-Ejn2eZP19Am-rugtOiEyoSpfd3iSDgR86i9IZL2BTWiAKLvCYe~iGMdhoBOwEhKE4NYpHie7sv6XZOjd7ylrT1Wtn-atbGyqX9IPuZW5RXezmdPbcHVRGqbe8Zcmapnggnd9V1iW7ucfyoaT-EQ9qzvc4eVqQOO1XuB2kof3Eq7rShHI18pKRjzXy3dzFPPD3ZDIfSN2AGWoZEnaM5Piqf4~FwSFAemxrlYI3QWim5HEr8-hwnyuHJOFK7uQZcQ__\",\"altText\":\"\",\"originalImageWidth\":1920,\"originalImageHeight\":1030,\"isFillWidth\":false}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Here is a short list of features that you can expect to find:\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Code completion \u0026 navigation\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Core refactoring support (renaming reference etc)\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":2},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Code linting\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":3},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Searching for reference\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":4},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Code folding\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":5},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Running / Debug configs\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":6},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Test execution\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":7},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Packaging \u0026 deployment\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":8}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"list\",\"version\":1,\"listType\":\"bullet\",\"start\":1,\"tag\":\"ul\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"In short, the IDE for Harmony apps is familiar and comfortable. In particular, if you are used to JetBrains-based IDEs, you will feel very much at home.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Programming Languages\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h2\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"There are a couple of choices for writing Harmony apps. Let’s start with the most typical choice.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"ArkTS\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h3\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"The Harmony platform has created a subset of TypeScript as it’s main programming language — ArkTS.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"6fbb959fb872058fdcf464ea0f3269ee68db0dce\",\"src\":\"https://s3-alpha-sig.figma.com/img/6fbb/959f/b872058fdcf464ea0f3269ee68db0dce?Expires=1768176000\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=HFDZN8QfttyQ9aw0~W4-aH8aTBsMS8dxY8FEnR15PIbLRCMkfG1peU5TfsnL6P3kxwEpi4VG-86c-BIfCMB-1L0qJEAAIH3FBaE-IFts2sjIScY0dLxSTLf4uw17d8Z9YW1UQKJu9a2kY30r1Kd2oEc4qkci0trqkYgq4IbKZcDLyfpzhAfBGMtPBfLJZCYRoltR8tP8PbluxJgFoYMmFr56bSF~fZMwWeisq4fi7b~5ZUJlw5I9WHzntYfMtDUetD3P9NRz4L4~7AGjncGRS3qT9XJIxlJf7bOLaRzNu4MkxT-oJ8X0JqBxaddLZqvFV2ceQb~jhmp5Bs99tJvZNg__\",\"altText\":\"\",\"originalImageWidth\":836,\"originalImageHeight\":591,\"isFillWidth\":false}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Before you jump to conclusions, it is important to emphasise, that this is \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"NOT\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" a cross-platform web-view like technology.\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\" Let me repeat\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" in case you missed it — this is not a cross platform language!\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Whilst ArkTS uses TypeScript syntax and language features, it is actually compiled into a binary format. Compiled ArkTS cannot be run in a browser or outside the app ecosystem. (Well…technically it can…but it’s not it isn’t intended to be a general purpose language runtime).\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Why a subset of TypeScript? ArkTS removes those features that would prevent anything that is not strongly typed or would hinder performance of the compiled code.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"I will leave the debate as to the merits and shortcomings of this decision for other time — there are of course, arguments on both sides.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"C/C++\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h3\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Another first-class language for Harmony apps is C++. For devices with screens \u0026 UIs (e.g. watches, phones, appliance screens etc), this should be seen as a compliment to ArkTS.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"For the smallest form-factor devices (such as micro-controllers), C/C++ will be the primary language for developing features.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"C/C++ support also provides the ability to integrate 3rd party C/C++ libraries into your Harmony apps. These could be libraries for specialised uses cases like banking and security platform integration or game engine libraries or perhaps just a useful set of utilities or SDKs.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"JavaScript / Harmony Markup\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h3\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"For simpler app requirements, a web-like development framework is available. This includes an HTML-like markup language for UI layout, styling with CSS and interaction/logic with JavaScript.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Note that these are not pulling resources from HTTP servers as with a web browser — the files are local. The capabilities of these apps are limited. It is not possible to use much of the SDK from these apps (e.g. accessing the device camera or sensors).\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"This option seems mostly useful for simple content based apps for which basic rendering of information is needed.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Other options\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h3\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"There is another language coming from Huawei that should be available sometime in 2025. I won’t go into details here, but leave that for another article.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"There has also been some good work to support ReactNative as an option for writing apps. This is not a core part of the HarmonyOS platform but should prove useful for companies and developers who have already invested in that technology.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Similarly, there has been work to create a Flutter runtime for HarmonyOS. Again, this isn’t official or part of the core platform.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"UI Framework\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h2\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Apps with a UI are written using the ArkUI framework. This is a declarative UI framework that should be very familiar with most app developers.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"This is actually a pretty comfortable way of writing UIs. There is a reasonable set of standard UI Components and it is extremely easy to build one’s own as needed.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Let’s look at a very simple example of some UI code.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"116f5d13f8f9c429ab41cc2b6bc08aea7ab9e21f\",\"src\":\"https://s3-alpha-sig.figma.com/img/116f/5d13/f8f9c429ab41cc2b6bc08aea7ab9e21f?Expires=1768176000\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=aqMttg7wci7uvdeFSB4Y41O~oA6tXmLVWHSs10~qVAPPShmUhWJrGxIHhL3I7DFEeZO5YHQBimL3AjB3isCfh4~MwOUHYSTBxmXdopUZg374HRF60HjhrmFo2KqYh~mHWr9eewYviaFkJaUlwJKviNSZn0cEa21i-rqvBkNckvpR1dMmbpaXxApOUFwYxIsPf~OvCTqRgYwxsxd9Pwsd72saBaZLMTcgiBvfJESF5huAIO6cM762Vm2NXHX~OckjCg5u79cOI3Q4I6urjdyX0Tfp9OKHzMt-udedHkugoGXoOi8Sv7u-KO-f25ER1yF777YB~F3GMFts96H2JeBAmw__\",\"altText\":\"\",\"originalImageWidth\":963,\"originalImageHeight\":736,\"isFillWidth\":false}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Layout components include Column, Row, Stack, Flex and Relative layouts. In addition there is a List and Grid layout component. There are multiple form components such as TextInput, TextArea, Button, Checkbox, Calendar Picker etc. \",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Some of the UI behaviour components are Scroll, Swiper, Panel, Tabs and more. Navigating between pages is very simple, with a Router component that supports pushing and popping screens or replacing the current screen with a new one in the hierarchy.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Styling and theming are substantially improved in the latest releases of the framework and offer no surprises for those used to such features on other platforms. \",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"In general, the UI framework is easy to use.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Build Tools\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h2\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Build tools are used for compiling and packaging apps. This is provided via a pretty simple tool called \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":2,\"mode\":\"normal\",\"style\":\"\",\"text\":\"hvigor\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\".\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Whilst hvigor does a reasonable job, it’s a bit too slow for a build tool. Perhaps it is because it was written in TypeScript (why?) and uses a Node runtime to execute.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"The simplicity does mean that you don’t get tangled in complicated build configurations. But it doesn’t really offer much.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Configuration files use a \",\"type\":\"text\",\"version\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"json5\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"link\",\"version\":1,\"rel\":\"noopener ugc nofollow\",\"target\":\"_blank\",\"title\":null,\"url\":\"https://json5.org/\"},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" format which is easy to configure by hand.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"290774bee94e7c806120d68e532dd82e157cf4b0\",\"src\":\"https://s3-alpha-sig.figma.com/img/2907/74be/e94e7c806120d68e532dd82e157cf4b0?Expires=1768176000\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=tx5PWZG2J3guAEDMx-tbXybjwHDADYSoc~S0bvzrG5Tm71NXVFYjPSrl8DujvPO9vBRZCNZmuVi1KvWVvfg0vJE~f5PKF~LJBR0CjmlRS0ap3M3Tu3jPM6G~EDcNUOEP4-XYT-90JNB9H1OpkVU-bUcxIX~UVvhm2pdW5hDsQm47jB6ifTQDxsQPKcZH3eMHRgiG8K-LKh1~njdJQ9N2d5Y6kPrNXnN-ocbYt4rIbJrERJ5dqEjfzVQ5HZxtArqQ9ApYtmQilSmIj25f8JjdRNiim-JWNXG-hX5mrK6UUaO2N6cMkenhb~uqk64ffkOBAUhUUUWeMJH27xoEHqiWRw__\",\"altText\":\"\",\"originalImageWidth\":878,\"originalImageHeight\":721,\"isFillWidth\":false}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"There isn’t any build scripting, although that doesn’t seem to be needed.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Package Management\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h2\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Another TypeScript/Node based tool is provided for managing app dependencies. This is called \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":2,\"mode\":\"normal\",\"style\":\"\",\"text\":\"ohpm.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":2,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Configuration for app dependencies is done in \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":2,\"mode\":\"normal\",\"style\":\"\",\"text\":\"oh-package.json5\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" files. For example, \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":2,\"mode\":\"normal\",\"style\":\"\",\"text\":\"ohpm\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" can be used to configure apps to include C++ libraries, multiple app modules or 3rd party component libraries.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":2,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"438a60177eec3ee2d820b58c8e57c21f44524444\",\"src\":\"https://s3-alpha-sig.figma.com/img/438a/6017/7eec3ee2d820b58c8e57c21f44524444?Expires=1768176000\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=OhitiSgE6WOIKWGbbiHbyMTA7K4RMajOwgcg-0qJM1Qy13OVtPvt71q1NmKUqNVkRTebADh9oqLm-Z6juF2TXlCwux3EfoRheBH4lrQdoEIJXryIWFZ5z9FP6seCpwb2oiBv7Dp74gpDN7O~yRCZOJOkDp1wZYfH7jHRWa3F3W~EChOYO5EQliGXM3LfsN0-if4WXAUJ5H2-SVlaH~8~mcqT1r5AFItqDiOe18gG5wLEdUua5pue8lBlb-SCj-7fmVr9xq9zLOFzxJUUbdA89~F95PJ9AxlRcRbYzx~7eDxSs1ngfF7~bULC1av0EDcDceD122~oPKXJ4fYwmVjGng__\",\"altText\":\"\",\"originalImageWidth\":614,\"originalImageHeight\":345,\"isFillWidth\":false}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":2,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Similar to the build tools, this feels like a solid part of the app development ecosystem. Similar to the \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":2,\"mode\":\"normal\",\"style\":\"\",\"text\":\"hvigor\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\", I’m not convinced that a TypeScript based tool makes sense.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Running code (devices/emulators)\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h2\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Right now, this is a weak area for anyone wanting to get into building native Harmony apps. Indeed it’s something of a blocker — however that’s hopefully changing soon.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Emulators\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h3\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"For developers in China, there are cloud-based Emulator options available from the Device Manager in the IDE.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"2515b73e9051c7a94faf4265f136bac42d5763fa\",\"src\":\"https://s3-alpha-sig.figma.com/img/2515/b73e/9051c7a94faf4265f136bac42d5763fa?Expires=1768176000\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=VnPz4TC~5yrPSoZ8YT1qH7QPBLc7A-votIcVHJBjUVb5JB0JmTuR-8RNm7yx3HxdvcdOwlZPHKbjf0N5qfvC1o56l3GXzC976~yp2j-rVbW6Z89a7W4AGtrSu2IIdf5yeXDeQlJZpBoDHf~EKvV4BT0~ljp2YGgno4ZwniVCOqjDrcaQ8uS3jYklwMfADNYlxbhEPqFWvrxBj8UG2OxcP5fsP~yLaI1OEU4J9gX-FlAGXaQ5GnNthQMmg5TQKCewTnSTc9WposQqFlsPrpQoKdVZLwurKF4p~wD4bxfgK1m8Z6ysQH3iBcndeBJsZyGlc9Qjw9YfOel0V4IgFacgWQ__\",\"altText\":\"\",\"originalImageWidth\":1190,\"originalImageHeight\":789,\"isFillWidth\":false}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"However, for the rest of us there are no local emulators available, we have to use real devices…which is another challenge.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Dev Kits\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h3\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"First, there is some good news. Within the OpenHarmony project, there are some ‘official’ hardware dev kits for developing solutions for phones as well as IOT devices and microcontrollers.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"A company called Hope Run sells hardware outside China via Amazon and AliExpress that developers can use. For example:\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"657d4b84f30358d483bd8f466b56a7c57779217c\",\"src\":\"https://s3-alpha-sig.figma.com/img/657d/4b84/f30358d483bd8f466b56a7c57779217c?Expires=1768176000\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=qoPaLRNG3kY0hBdCw512hNzciPf8foaAlb0dvpe1ys79NQlCZxR0FpxB3nAstETsvN9DsqeGC~pkmLQNaacNv~lMzD96o5BiqmVG7yy7hjWsUWTSIDgcHgDs-A~9kF6Rj0mSJs7bp4RIFSe5eDewviKtu~rtgijDBWFxo1c2qF060TDqMJn4Ng1ngkWMZnZipqOvzNkD~zbVS70kaDqJJG6Sc2o2RZ~1RuNY~n1y4Wpf8-40P-icaeZ5jWeo8ysMfpDi4B1A~df9iQViexzrWlWgNnxtxKZbjfsW3w7YCPUf4KNEMvpvA9ARtwPbUQiXV5M9YVhd91-2h2BcJ5eN3w__\",\"altText\":\"\",\"originalImageWidth\":1037,\"originalImageHeight\":1000,\"isFillWidth\":false}],\"direction\":\"ltr\",\"format\":\"left\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"left\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"fab52b7f75295cd4a19becefdaa1c40407b2e653\",\"src\":\"https://s3-alpha-sig.figma.com/img/fab5/2b7f/75295cd4a19becefdaa1c40407b2e653?Expires=1768176000\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=CN55suiokxG9bEBsUV7zwIrQ~DlvcSZ5jPQTqb2ggsgLbylU-CFU9kXnj8POJco1Ih8zBOMMHiH-Ny209fS6Yu9uR4l5vlDRHxHks8ieLtKbvMewbZi59TJXcD5o837KWmSwUnrqT9TC3uJRObQevOWrHG-dg-5AFwjvLDpy9B0I7HqZAjc1w5YHH~zLqQrFrQ6vi5VSKpsRMrYDPhgDG2rz1MBddpP9CJDlAM3eTrXCvhWzO0vl6mO6~HppDlxY0xdJZilAEDhuRpH7IBNCLszZWpWaqf5CpP4Vp2KPlLlI6JiXMq576V3CnvajS0ayEjAnytms6TY2ZvctPH4NZw__\",\"altText\":\"\",\"originalImageWidth\":670,\"originalImageHeight\":340,\"isFillWidth\":false}],\"direction\":\"ltr\",\"format\":\"left\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"left\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"These dev kits are clearly pretty raw, albeit feature full. Importantly it is possible to flash your own OpenHarmony builds onto these devices which is great if you are working on operating system features.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"More familiar to most of us is an actual phone device. One such device does exist that runs vanilla OpenHarmony — this is the XXX. It is unfortunate that this is only sold in China because it makes for a good developer device (indeed it is the one we tend to use the most).\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Huawei Devices\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h3\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Whilst it might seem obvious that there are Huawei devices that one can use for app development, the picture is a bit more complicated than expected.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"The TL;DR is that most HarmonyOS apps commercially available today are based on OpenHarmony 3.1/3.2 \u0026 API level 9. Given the latest API level is 13, we would not recommend using one of these devices for native Harmony app development.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"If you want to build apps for Huawei devices it is best to have one running \",\"type\":\"text\",\"version\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"HarmonyOS Next\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"link\",\"version\":1,\"rel\":\"noopener ugc nofollow\",\"target\":\"_blank\",\"title\":null,\"url\":\"https://www.harmonyos.com/en/\"},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" so you can use the API level 13 SDKs. So far Huawei has only released on device using this OS — the Mate 70. Again, this is only sold in China for now.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"78e0f2169140418cf62b1ae18ba8dc978fd9ae09\",\"src\":\"https://s3-alpha-sig.figma.com/img/78e0/f216/9140418cf62b1ae18ba8dc978fd9ae09?Expires=1768176000\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=J1-HVoF4HQwbF2UItVtT1V4Tv~9NYhLb2~Aa3TvKnpzd5WercSJhsYaojVxOfMIfmY2n1DCjrGzDhTN0CQKE01d4Uya-jtLrmJdbMN4SvoOQSO7h5wHMiKnDIzapIVebZ5ocIVLSWH8HRcOdQlx1ClXTtY1iRbNPyejC4t8fa6MoC~a8c8ITThKvKTRF-rRpfUMAXbwWr3oQqNJfIjN-wRXcHQCtKfW6O5BydqXHJI4toxGp59fU4M00Kn-xHayYJBsUoD9VaoS7I6IWWc0zVS3kim4YIJ2nj5-gbFyku4ZlFGVRmjI9Jy-9vq1cUlCnHm-gX7nJPYJB4h5GwxkdAA__\",\"altText\":\"\",\"originalImageWidth\":1024,\"originalImageHeight\":530,\"isFillWidth\":false}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"The Mate 60 can be upgraded to HarmonyOS Next — but to my knowledge it has to be a device purchased in China and you have to enroll specially to request the upgrade (thanks goes to the guys from the OpenHarmony team for helping me do this).\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Coming Soon\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h3\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"The good news is that there are efforts ongoing within the \",\"type\":\"text\",\"version\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Eclipse Oniro\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"link\",\"version\":1,\"rel\":\"noopener ugc nofollow\",\"target\":\"_blank\",\"title\":null,\"url\":\"https://oniroproject.org/\"},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" project to port OpenHarmony to a handset available in Europe. I am expecting this hardware partnership to be announced soon, so should not reveal too much here.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"However, this will make it much easier for developers to get started with HarmonyOS app development.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Debugging\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h2\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Thanks to the decision to use JetBrains tooling, debugging is well supported for app developers.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"3d5fcf2f08bbf0c59525924adab4b74474fe4aee\",\"src\":\"https://s3-alpha-sig.figma.com/img/3d5f/cf2f/08bbf0c59525924adab4b74474fe4aee?Expires=1768176000\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=f8t4dbPZgZpfW8hbrPpjQyaqBsYbGOndUkkw4yIfpcgnr4669Ihj3miM8dNOSCUTEALvsGI1AhHzceaXZianzYroKwkTBEZo21FWvtLqWBX73IS2I5TwKFEyQ-ibSCxFgui4I9jcxHrd7r0nH~-hZ5t9C8JrRz3PjP-MOe8IA78YfcpB-bw92gIbJ~v~6Fkw86vhOAwvOi7BgRvFZ4qsm0kWerljOM1vv3qu47vgDChlohHoZN-i9Ilhrew7n~ef3kuAMIIzYATDexr1XKh544lsIG1C24Cu-8gxEdA17ZGOTEkXJfC5kIz8urhAwaVVP82s47Ly66NxTPtF~gGn4Q__\",\"altText\":\"\",\"originalImageWidth\":1892,\"originalImageHeight\":930,\"isFillWidth\":false}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"You can expect the typical features, including:\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"breakpoints\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"various stepping in/out/over code\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":2},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"inspecting \u0026 watching variables\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":3},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Attaching to devices\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":4}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"list\",\"version\":1,\"listType\":\"bullet\",\"start\":1,\"tag\":\"ul\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"These debugging features are available for the different programming languages — ArkTS, C++ and JavaScript. What’s pretty cool, is that multi-language debugging is supported — for example ArkTS code that calls C++ code.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Hot Reload\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h3\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Developers using the latest API levels (12 +), benefit from hot reload. There are some limitation, but I haven’t had enough time with this feature to write too much about it. Probably this can be a separate article.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Testing\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h2\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Quite a bit of effort has gone into support for a variety of testing tools which is very positive.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"A test framework called \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":2,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Hypium\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" is provided. This framework is well featured with test cases, test suites, scaffolding for tests (\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":2,\"mode\":\"normal\",\"style\":\"\",\"text\":\"beforeAll/beforeEach\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" etc setup \u0026 teardown hooks.) and an assortment of asset statements.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Unit Tests\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h3\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Unit testing is supported with Local Tests. These are tests that run ‘off device’ and hence are not expected to use device-specific features (like camera access). If you care about code coverage (which we don’t), it is possible to create code coverage reports from the testing framework.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"611346870b633bb2f4aafd09119b9cabc6e78018\",\"src\":\"https://s3-alpha-sig.figma.com/img/6113/4687/0b633bb2f4aafd09119b9cabc6e78018?Expires=1768176000\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=VPnqOpau~fEuLHr-ZIHlrY7vX-sdFYMDRlhjJyBTHazmx7ruRQ6XsnAMdNFKEKWyjKFRqCKx64JFpzEyJz6-sW2khEXV2Z5L3eD~iv6bHx9zQhL1xBNhuUU2KvjPigZD3MmfGflzOarb8Ct5UUeWWjFq1jndV6aHACLU7V4l-VtrCMG1FuS~phhDkga-pAeJ0CJ1hKNu0qGMjiReTSoM14B8E9QOmHoTAf98IO5ocjz2GOHAbOYojNPJePyYtbHFkJ0xgUPagt43vBKTKpZAjHFDaCLDy7af5Gup8B0F2GcYPqIZNzsi-5lHBiBVHUDXOVv40IEdbxtn-mZeBWMQXg__\",\"altText\":\"\",\"originalImageWidth\":924,\"originalImageHeight\":346,\"isFillWidth\":false}],\"direction\":null,\"format\":\"left\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"left\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Instrumented Tests\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h3\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"The \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":2,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Hypium\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" framework also makes creating instrumented tests very easy. These can only be run on a device/emulator.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"5ea496e69fe9cd42cb056de7b128363ef828a6b5\",\"src\":\"https://s3-alpha-sig.figma.com/img/5ea4/96e6/9fe9cd42cb056de7b128363ef828a6b5?Expires=1768176000\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=A9i-638m~aJZjdbDcu~wrCjbmhzEtSYUns8h77MvHc3fg2yDB4RtcWq7sO~Nwk-SQtUewBgD0k2wLe3gmHQisScnER3zFTwLrxyfe-pHk0hbBFzmYqO24q2VA5NZWNOCqRW9Yrui~OY22jcK2DKs~aPsVhDOHoK9QXTj0-6cU6KqRtPBG4qN9lu9876BfhIe4HrqnTdQcXGiCkhqmLpYGRr-LWioUvbLnCVN6Pmg6KwvqYlBF5xe9rY72I4HGo-voS4cuB3gjht0tSPVwu-jpLHWt5GoxJvHfAyWQgxkf8Fw0SGbeasR0fkvS50iUgq~Dx5MCevKN6B4zQasMWyTqw__\",\"altText\":\"\",\"originalImageWidth\":1456,\"originalImageHeight\":324,\"isFillWidth\":false}],\"direction\":null,\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"It is possible to decorate instrumented tests with meta data that can be used to filter tests when running them. The available meta data are ‘Level’ (aka importance) and size (aka execution effort). This means it is possible to tailor which instrumented tests to run (vs running all them every time).\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Mocks\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h3\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"The testing framework also provides a mocking facility. This seems to be fairly standard for a mocking kit — although it’s not a subject I know enough about to comment on meaningfully.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"UI Tests\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h3\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"The DevEco Studio tool does provide support to creating black box UI tests and there is a UI Driver bundled in HarmonyOS to run UI Tests.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"How well this works is not yet clear as we haven’t had a chance to try it out.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Profiling\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h2\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"This is another area that seems to have been important for the tool developers. Note that these capabilities are provided by DevEco Studio so cannot be run via command line.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"eaf9bcaeabbdb85b4eeff6344b3c406b7cbba768\",\"src\":\"https://s3-alpha-sig.figma.com/img/eaf9/bcae/abbdb85b4eeff6344b3c406b7cbba768?Expires=1768176000\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=fdtIUA1gnAMgn30dZoWwz-foYXTUTNyyQEhAOj4rG~b2GQPZTwJtpSW83P07gXWmbBh-X98ZESNCmarAHxwXaYaxEK0A9YpwSF5uavZi2ZcYryfLPY0-PgebV42yVo5g4LepAklinh77PPJexl6WbQwCnENlDNHJh55~kFkZDVQRezUAk0iWXTv~krJYaFFJ2CUHSel1tnLnVNBiueLo2GBCrN~LIh4Vnd0O37dll-6kFaP6nqOHVxjGB-MOdjT0jHb6bPCJlljMY2oNJDijhPkVAOqXA~PX0kGD4g0~KorWHXLjMfZj~wqx03qUkJCUEHb5j8qtNkWR5aGG9JAsNA__\",\"altText\":\"\",\"originalImageWidth\":1875,\"originalImageHeight\":777,\"isFillWidth\":false}],\"direction\":null,\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"There are several available features for different types of profiling. I will list them here as I don’t have any additional commentary to offer at this moment.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Time analysis of function execution\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Energy consumption analysis\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":2},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Memory analysis \u0026 Memory leak analysis\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":3},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Janky frames analysis\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":4},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"App cold start analysis\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":5},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Network diagnostics\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":6},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Realtime monitoring\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":7}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"list\",\"version\":1,\"listType\":\"bullet\",\"start\":1,\"tag\":\"ul\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Other cool stuff\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h2\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"With a new app development platform, we get a couple of nice features that look to be useful.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"ohpm-repo\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h3\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Bundled with the tooling is the ability to run your own private repositories for distributing libraries, components etc that you have built for your organisation.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"This removes the need for 3rd party solutions like Artefactory.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"ohpm-repo is quite feature rich already, with capabilities such as:\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"user managment\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"organisation/group access\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":2},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"managing an artifacts repository\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":3},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"public repository proxying to locally cache copies of external artifacts\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":4},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"certificate and access token based authentication for the ohpm tool to use a repository\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":5}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"list\",\"version\":1,\"listType\":\"bullet\",\"start\":1,\"tag\":\"ul\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Component / Library Store\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h3\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"To help grow the developer ecosystem, there is a ‘marketplace’ where 3rd party libraries can be found. This is called \",\"type\":\"text\",\"version\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"DevEco Marketplace\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"link\",\"version\":1,\"rel\":\"noopener ugc nofollow\",\"target\":\"_blank\",\"title\":null,\"url\":\"https://repo.harmonyos.com/\"},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\". This is similar to npm or \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":2,\"mode\":\"normal\",\"style\":\"\",\"text\":\"pub.dev\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" for Flutter.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"41e6ab015109398ecfb9701d235f605be0c25e88\",\"src\":\"https://s3-alpha-sig.figma.com/img/41e6/ab01/5109398ecfb9701d235f605be0c25e88?Expires=1768176000\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=jtbAzSQB3EtuvPxZKTl~Yt6YgZ479c~W2kI-3fjKZ4P2HcfD7MlO45QjLZtH8sj6~dd3ePHlTFiLjVhu-GyT0HaCLwesR7v85dbFJEvdRoCCcveP1e3~gGloO6QUi7Kcpo1BU9HrWR02XJlU4wggKyibr2mpmlb2U4nblYhLhxcYHFrgfUYPEYUTvj-Kk2t76oSLqYm~~0EIuZs0oOzQqE6c51s9n1ivYrhBeQYlxSUhMggCc3fkRf8mTTMD~itlNfpkTbo~-GJmepZG8XupeHgtZi8IZAQcM0Q~IoEB91k7g9gXrHGJm6PhUDq094HhJIhEg44RoL86eSAFL7EPpQ__\",\"altText\":\"\",\"originalImageWidth\":1434,\"originalImageHeight\":632,\"isFillWidth\":false}],\"direction\":null,\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Beyond libraries and components, there is also the concept of a template library where app and UI templates can be shared.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Conclusion\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h2\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"HarmonyOS apps are pretty easy to develop and have familiar tooling. The world of mobile/device app development is pretty mature and HarmonyOS certainly benefits from this.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"There have been some good choices in terms of IDE foundations and pragmatic decisions in terms of technology selection.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Challenges still remain for those outside China as device availability is constrained. The absence of a good local emulator is a big hole that would have gone some way to address this.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"However, this is an excellent starting point for a new and ambitious operating system. It sets the stage for many improvements whilst serving the core needs for app developers.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"root\",\"version\":1}}","itemId":"1a52d56d-e318-40ff-8553-f3e4be29839e","fieldSchemaId":"3084d9ba-ab55-4e5a-931b-b9db3d09105f"},{"id":"0257d47e-5492-4890-bc12-3c9bd2ac5047","value":"Jasper Morgan","itemId":"1a52d56d-e318-40ff-8553-f3e4be29839e","fieldSchemaId":"df1c88d1-4bd8-4ecd-9059-463b9589de92"},{"id":"0aa4ce34-74ff-4437-ae47-659014247ad3","value":"{\"root\":{\"children\":[{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Founder of Snapp Technology. I bring 20 years of software engineering experience to building no-nonsense, developer-friendly companies that clients genuinely love. My focus is on creating products that are clear, efficient, and built to solve real problems without unnecessary complexity.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"root\",\"version\":1}}","itemId":"1a52d56d-e318-40ff-8553-f3e4be29839e","fieldSchemaId":"0b77f83b-c31a-4889-b9b3-9a6d2e41fc86"},{"id":"81517c14-788a-4f49-b620-37ac8053456f","value":"CEO, Snapp Mobile","itemId":"1a52d56d-e318-40ff-8553-f3e4be29839e","fieldSchemaId":"0a981f8a-7dbb-440d-a940-25d9060c9b11"}]},"80345e24-6050-439b-9c3b-9e1690a6a5de":{"id":"80345e24-6050-439b-9c3b-9e1690a6a5de","index":"!r","collectionId":"d4a5b68c-8afd-4bbe-a7ac-e9a8422fedde","fields":[{"id":"1ffb85b0-f9fe-43f1-989a-accbf07dc870","value":"{\"root\":{\"children\":[{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Founder of Snapp Technology. I bring 20 years of software engineering experience to building no-nonsense, developer-friendly companies that clients genuinely love. My focus is on creating products that are clear, efficient, and built to solve real problems without unnecessary complexity.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"root\",\"version\":1}}","itemId":"80345e24-6050-439b-9c3b-9e1690a6a5de","fieldSchemaId":"0b77f83b-c31a-4889-b9b3-9a6d2e41fc86"},{"id":"85f56b90-b91b-4085-b978-cdaa50327ce9","value":"2025-08-19","itemId":"80345e24-6050-439b-9c3b-9e1690a6a5de","fieldSchemaId":"b7712ee6-f9fd-4781-8c5c-e7e10ce8f81e"},{"id":"873917fe-728c-41bf-b344-60127fefb874","value":"Cangjie — a programming language from Huawei","itemId":"80345e24-6050-439b-9c3b-9e1690a6a5de","fieldSchemaId":"f2ba59b9-49cc-4ec6-9416-bda99d4c8383"},{"id":"ae31782d-c504-4577-8af5-dfcf0ab3ab94","value":"{\"image\":\"84c9bf5fdd0dd68cdd9c8e5b7e04264cce72c4ca\",\"imageThumbnail\":\"d0bdd4d647e2619a42be18d28de5cd83f006c1f0\",\"originalImageHeight\":500,\"originalImageWidth\":1373,\"altText\":\"\",\"fileName\":\"Image_2.png\"}","itemId":"80345e24-6050-439b-9c3b-9e1690a6a5de","fieldSchemaId":"1f58afa6-2748-4188-b4a4-f1e54e37eca9"},{"id":"f603f13c-0928-40e3-adf2-093bd90b91f9","value":"cangjie-a-programming-language-from-huawei","itemId":"80345e24-6050-439b-9c3b-9e1690a6a5de","fieldSchemaId":"402ba26f-8f6d-4f5f-bf20-62e6549f4ad4"},{"id":"1a3d3634-7def-4fae-b77e-b735c3b7ab02","value":"CEO, Snapp Technology","itemId":"80345e24-6050-439b-9c3b-9e1690a6a5de","fieldSchemaId":"0a981f8a-7dbb-440d-a940-25d9060c9b11"},{"id":"2d57bdb0-17d1-4feb-97ba-d153fb27f525","value":"Jasper Morgan","itemId":"80345e24-6050-439b-9c3b-9e1690a6a5de","fieldSchemaId":"df1c88d1-4bd8-4ecd-9059-463b9589de92"},{"id":"1a1f901c-e008-4c1d-952e-99f336ffb56c","value":"{\"root\":{\"children\":[{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Huawei have been busy. Last month they open-sourced a programming language that is looking pretty interesting. Whilst you might not be writing in Cangjie next week, it’s good to see what one of the world’s largest technology companies is doing such that they have created a new programming language.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"TL;DR\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h2\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Cangjie is a C-like programming language that feels more like Swift/Kotlin than Java/C# or JavaScript/Typescript.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"The idea is for Cangjie to become the common programming language to be used throughout Huawei.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":2},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Cangjie can be used for embedded systems, mobile development, server-side cloud architectures.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":3},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"It supports a variety of programming paradigms (function, OO, procedural), compilation and integration options.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":4},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Cangjie can call C libraries (and be called from C), use Python libraries and even compile to JVM bytecode.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":5},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Cangjie supports language extension to create lightweight DSLs.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":6},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Primarily Cangjie programs are compiled into machine code — this include cross compilation which mean they can run natively on different computer architectures.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":7},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Cangjie comes with a set of in-built tools for developers such as package management, debugging, testing and IDE integration.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":8},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Cangjie is openly available since this month and is in version 0.53.13.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":9}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"list\",\"version\":1,\"listType\":\"bullet\",\"start\":1,\"tag\":\"ul\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Why create a new language?\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h2\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Simply put, Cangjie gives Huawei a level of control and an economy of scale that they cannot get from other languages.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Most mainstream languages are driven predominantly by teams in USA and Europe. It is hard to influence the road map for these languages — especially for those tightly controlled by corporations (e.g. Java/Kotlin/Swift).\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Furthermore, consolidating programming skills could be a big efficiency gain for Huawei — engineers working on products ranging from routers to petabyte storage to cloud computing and mobile devices can coalesce around one language and toolset.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Show me some code\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h2\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"I won’t go into any detail here so this is just to satisfy your curiosity. I suspect you will find the code immediately understandable anyway.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"The following 3 extracts are from the official \",\"type\":\"text\",\"version\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Cangjie examples\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"link\",\"version\":1,\"rel\":\"noopener ugc nofollow\",\"target\":\"_blank\",\"title\":null,\"url\":\"https://gitcode.com/Cangjie/Cangjie-Examples\"},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\".\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Example using Threads in Cangjie\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h3\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"3dc3f622bbde9bb3e50c4491996093c6b056b950\",\"src\":\"https://s3-alpha-sig.figma.com/img/3dc3/f622/bbde9bb3e50c4491996093c6b056b950?Expires=1765152000\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=Q2e2uo2RiYaa8A4U2OTkEzxMdL1rX45aDK0Kiy59Io~~MVBb2gIFQwxUsV60Z0x0Ae0cvFuBr7tTfO-wDOzVx9a8eRY2halO6Kw-Z8eSZG44wDagVRmDBrrntAy~OdwK4~Apaa8KXCF5pQdU0~SWoWkWp0dC6FsidtGov12Mhp6Kk7KV5crdAt8Hviyz6~XrIMN-1IOOAqKxflMroB~bRCKrUN7gNpCj0A2nnGJ0SXV28IF3L7pf1hAK4uSqlyn~B8tPWwBgEooEUbKJRk2LKY8emkcPvjtcW6G6S4ECjzDVyKiJP8OGd2Oj8CDrEy7uZrveQWSrnMO2B~-bkEQryw__\",\"altText\":\"\",\"originalImageWidth\":3484,\"originalImageHeight\":3276,\"isFillWidth\":false}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Example of Lambda functions\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h3\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"e18b8cd342126cff37dd6fd2d93e3dee5bb19dca\",\"src\":\"https://s3-alpha-sig.figma.com/img/e18b/8cd3/42126cff37dd6fd2d93e3dee5bb19dca?Expires=1765152000\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=AhK2M5Dd1wTrbXR7NFsECX1~BWtWasy9iyJZMzYWb3oJVz4ExI9JiwmR0h11q-2tfF-if9X38gfv~34FNUV4tntP4cJGW7svWia4HKMHFLcZDk-Qh8aQ4QVq4hYKlvEJKzNUtQWfnbOO6IHY9K4LidFUOY3vcT8H3oKUaExkxqEjJatu9ovCBF23Fqv~Zc2QYlBz1zs3-1GpUurTyLdAft9xjvo~Eodx-7yFquzLg87cdOMNchI6GukkinC3Qee9iq-C4tQ1LmvmKxs-aqEVLrYfqRFj7MJEGIZJHnaRhX-CP923gi6iANwSnQIRJcYHKmMcYOYBQVCXZsmJ93vqQQ__\",\"altText\":\"\",\"originalImageWidth\":3484,\"originalImageHeight\":1936,\"isFillWidth\":false}],\"direction\":null,\"format\":\"left\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"left\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Example of language extension\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h3\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"143ceb792ef9abd33339211b7d92cdb59ed78319\",\"src\":\"https://s3-alpha-sig.figma.com/img/143c/eb79/2ef9abd33339211b7d92cdb59ed78319?Expires=1765152000\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=AFnhQcsBPYZPoO7RLbE-bAeTRb8VLyCl2QbeovNilpKgRATFATFHYPKB8L8CNFOw6pZdQ0yHGhiIjmaQAo3BPDI08K4Jur9MABynfkVdgBD9RIlnRejYcQidfWbit4el-03cgs55KVPYiuBYUgwcBzDl9gL0JucCs9DhRqhtF1ts5BJ1gHJpLIyOaUotAXbBrRGw23eqQ9b3plJkWnBd8mprr-O29k1hThRX6gYbyn2OeE4dc4HEcTtLM2R4BhDVwVJCl16O9JPpgkvwgZyrGsrikRHg40m28oQ3ZowKyktlxhU7DAbL7ucQmD~J1l6L~SBLUiDXEyIm6K291YBLBw__\",\"altText\":\"\",\"originalImageWidth\":3484,\"originalImageHeight\":1860,\"isFillWidth\":false}],\"direction\":null,\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Can I try it out?\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h2\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Yes! \",\"type\":\"text\",\"version\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"There is an English language version of the documentation\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"link\",\"version\":1,\"rel\":\"noopener ugc nofollow\",\"target\":\"_blank\",\"title\":null,\"url\":\"https://cangjie-lang.cn/en/docs?url=%2F0.53.13%2Fuser_manual%2Fsource_en%2Ffirst_understanding%2Fbasic.html\"},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\".\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"The language community in China is growing — for now the language is slowly getting recognised outside of China.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"What’s coming next?\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h2\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"If you want to see the roadmap for the language, \",\"type\":\"text\",\"version\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"you can read about it here\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"link\",\"version\":1,\"rel\":\"noopener ugc nofollow\",\"target\":\"_blank\",\"title\":null,\"url\":\"https://cangjie-lang.cn/en/docs?url=%2F0.53.13%2Fwhite_paper%2Fsource_en%2Fcj-wp-future.html\"},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\".\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"If Cangjie interests you, I will be writing more articles diving into different language features over the coming weeks.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"root\",\"version\":1}}","itemId":"80345e24-6050-439b-9c3b-9e1690a6a5de","fieldSchemaId":"3084d9ba-ab55-4e5a-931b-b9db3d09105f"}]},"7c10a08b-d604-4d4d-a009-2400c53b6b59":{"id":"7c10a08b-d604-4d4d-a009-2400c53b6b59","index":"!f","collectionId":"d4a5b68c-8afd-4bbe-a7ac-e9a8422fedde","fields":[{"id":"0dc98871-bea4-4d01-9765-ca378e6bb76b","value":"{\"image\":\"b181e5d6714321368d437d93c1bcb83a5f45a3a7\",\"imageThumbnail\":\"9f0fecec711dfd78c215d4adbd83c001ae1d5737\",\"originalImageHeight\":652,\"originalImageWidth\":1326,\"altText\":\"\",\"fileName\":\"Image_1.png\"}","itemId":"7c10a08b-d604-4d4d-a009-2400c53b6b59","fieldSchemaId":"1f58afa6-2748-4188-b4a4-f1e54e37eca9"},{"id":"0f9b34eb-db1c-4126-8f3d-06d40da9cb58","value":"Multi-Module Projects with Cangjie","itemId":"7c10a08b-d604-4d4d-a009-2400c53b6b59","fieldSchemaId":"f2ba59b9-49cc-4ec6-9416-bda99d4c8383"},{"id":"34fcc9e9-a4dd-4027-8447-de70e2afb636","value":"2025-09-02","itemId":"7c10a08b-d604-4d4d-a009-2400c53b6b59","fieldSchemaId":"b7712ee6-f9fd-4781-8c5c-e7e10ce8f81e"},{"id":"b170ba9d-5d1f-41f7-a442-58466ef8adca","value":"multi-module-projects-with-cangjie","itemId":"7c10a08b-d604-4d4d-a009-2400c53b6b59","fieldSchemaId":"402ba26f-8f6d-4f5f-bf20-62e6549f4ad4"},{"id":"c7342af4-aace-410f-9f7f-31b90a68baab","value":"CEO, Snapp Technology","itemId":"7c10a08b-d604-4d4d-a009-2400c53b6b59","fieldSchemaId":"0a981f8a-7dbb-440d-a940-25d9060c9b11"},{"id":"174b00a7-4181-4286-8385-1930a642144a","value":"{\"root\":{\"children\":[{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Founder of Snapp Technology. I bring 20 years of software engineering experience to building no-nonsense, developer-friendly companies that clients genuinely love. My focus is on creating products that are clear, efficient, and built to solve real problems without unnecessary complexity.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"root\",\"version\":1}}","itemId":"7c10a08b-d604-4d4d-a009-2400c53b6b59","fieldSchemaId":"0b77f83b-c31a-4889-b9b3-9a6d2e41fc86"},{"id":"5a83a91c-35aa-41c6-84e4-6dd7055c1b14","value":"{\"root\":{\"children\":[{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"The Cangjie package manager \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":16,\"mode\":\"normal\",\"style\":\"\",\"text\":\"cjpm\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" is a cli tool which can be used to setup multi-module projects.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"A module is simply a folder with a \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":16,\"mode\":\"normal\",\"style\":\"\",\"text\":\"cjpm.toml\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" file - whilst these can also be created by hand, the cli tool simplifies the process. The approach to the setup is to create a cjpm workspace at the project root and then separate module within the workspace.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"It will look like this:\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"180d9c6e4ebe823c6039d4853465c56ceefd2df3\",\"src\":\"https://s3-alpha-sig.figma.com/img/180d/9c6e/4ebe823c6039d4853465c56ceefd2df3?Expires=1765152000\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=lZ1VyjX4438~sKDw1PJw6L3p2oH8mZP9OhVkDOuf9XiEnWVyjknuX~~cCKIE1TGjc7DX0ij55YaoPnKEOzz--q1vGaDIV~1mY59yzefIsTdBzhe6OEbu2LiG968tujm5361-Z7xwokSYXvG-wsJM4sGChKy20HiAesrumqexgo5UxmOcSdsuFJrke8Tm6gQCuGgAwnmj2y54EEgrSCJknA8POMc7cvbBCH7wyN7g6wk8pwHPH0il499LUBmfJU-V3A42FfnOTa7kP0T2a1BRQfxIWNXBfBpM6Fm84ltF0C3XOAi6TUZPsc8uGPxtnJY0fq1CQ9MkkNuU6Vzjo-T0ZA__\",\"altText\":\"\",\"originalImageWidth\":3484,\"originalImageHeight\":1040,\"isFillWidth\":false}],\"direction\":null,\"format\":\"left\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Create the workspace\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h2\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"In the root of your project, initialise a workspace:\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"695a50b96ba6cf33c609ed0363b430c5ea33fa71\",\"src\":\"https://s3-alpha-sig.figma.com/img/695a/50b9/6ba6cf33c609ed0363b430c5ea33fa71?Expires=1765152000\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=At7DbLYSd1i~Mz7ODh1nL93uWt7ZV43AsooVmPUsGOrdz2IPUNf6VcMblCFrTPxqZk1TyDBN--kzOUeWPP4YBj~38VommjHxT8izozYWasE3vRPKKdJ1YTt29yAvr0qbAw9b2MIwFmq8K~q4iLNKNaXcwCoGHAxbe69TSuR3KR5Bqkk5BlEQLNCQ-OdEN8Lj0zHtTHAl21uoeFFHiL29HCSUfIZlDWH0PTaTMUnf~KjZRjQSXl5HNhDP~0UKP23-HIM1KkV9koC0dyW7~cBXpUxXp04fInpTAbALSt6QcgdyflaLcrXGF6AS8V4tuVQhZ1RJeD7B4EOcJPQyHTAwVA__\",\"altText\":\"\",\"originalImageWidth\":3484,\"originalImageHeight\":1192,\"isFillWidth\":false}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"At this stage, your project directory will have a \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":16,\"mode\":\"normal\",\"style\":\"\",\"text\":\"cjpm.toml\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" which is the configuration for your workspace. A newly initialised workspace config will look like this.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"932b719a361b58796b674f22a9b86e2a9fa6056d\",\"src\":\"https://s3-alpha-sig.figma.com/img/932b/719a/361b58796b674f22a9b86e2a9fa6056d?Expires=1765152000\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=hnrBbFeiggKhXMyfAvStaXjs3dUfUmewLZlxjCYR4A3KKnaiYgU1YuuRfw-CdaFemJtBpMnqEPeBHtE9zEVWm36ZSzta-rS2Eeux7H04PBj-gxQ7MrUlWlXt-HVHqQRC7CJsYUatlcPuVzv3AHg4JwzCDikpSt4DWvvSO654ItxzfegDNTxktutVfphAV53odIRrs5Wbgx-ZEAcpoh51w~K197uYYqO9N792i1XUk47vQ18cmKtdQpjTvVo-R398zdAUktAx2bBpMB7CqXUq5HxKFIB67pYEwOYvKDTvqOoN3xzcaLPQH~yTwsqoWQ9jMWZJ~A-qmuM1UWQAF6UzbA__\",\"altText\":\"\",\"originalImageWidth\":3484,\"originalImageHeight\":1340,\"isFillWidth\":false}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Add the modules\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h2\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"To add a module to the project, use the \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":16,\"mode\":\"normal\",\"style\":\"\",\"text\":\"cjpm init\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" command but with the options to specify the type of module to create (executable, a static library or a dynamic library).\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Let’s add a couple of modules to our sample project.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"46a214cc3e8890aeaaf0f7262817c0e547d0daac\",\"src\":\"https://s3-alpha-sig.figma.com/img/46a2/14cc/3e8890aeaaf0f7262817c0e547d0daac?Expires=1765152000\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=sAyfso6Q4uYvNWKjxG9-oGYZNnXwyfDONgsSYXjR7GCGTRJC3~eCdugsrAzaYSJl~z5Flu6BNR4ZbgisggMko3oauRh~u6kCICJ5X3MpzGduwYv6Y-Fu7~DRR~vNVd7jjpIpXpF1qvE2S-grNh4lzVmhOig~6N5cd8mf6v3bwu9VLsCg3cmhztZiPpYDF2F39C~2w-OjqPfwXts9XL69GMe1gR~5MBeq1JXFFCD-oP-5EgqGz93gk7V~MvXo5mQb2JU~hEhFgRK6LwNVXYWnE7jAbxsp-uoDRAeksQuXbTbnTGSs0aYusH5BsS3kQthl3r1jpAMwD3IeLjosDLPkJA__\",\"altText\":\"\",\"originalImageWidth\":3484,\"originalImageHeight\":1340,\"isFillWidth\":false}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"By default, a newly created module has a \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":16,\"mode\":\"normal\",\"style\":\"\",\"text\":\"src\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" directory and it's own \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":16,\"mode\":\"normal\",\"style\":\"\",\"text\":\"cjpm.toml\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" to configure the module. (Static library modules will have no source code. Executable modules will have a main.cj file).\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Add the modules to the workspace\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h2\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"So that the workspace is aware of the modules we created, we need to add them to the \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":16,\"mode\":\"normal\",\"style\":\"\",\"text\":\"members\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" field of the workspace's \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":16,\"mode\":\"normal\",\"style\":\"\",\"text\":\"cjpm.toml\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\".\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Edit the cjpm.toml as follows:\",\"type\":\"text\",\"version\":1},{\"type\":\"linebreak\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"5d0dfa690c21e29649c8e37d33aef604547e524b\",\"src\":\"https://s3-alpha-sig.figma.com/img/5d0d/fa69/0c21e29649c8e37d33aef604547e524b?Expires=1765152000\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=IdQCQIKLGa2HF4u5Vhs0OCJiupxGN6XS5YMa3w5E4AXsgRQKQ2zf95ZRlZdSx8zbABYdL3G6clxJGKuLkiCgT~bq9i9wMAr8f-hGjM~NVCKmE5xfW958mFVRDvlJ2rz5AygoEIATjGWJd9Oj1AJyOdFWxxgoD1BtX5DgSRAvA36~fKGqeUNhFccRkwH9Ky5gWVh78mmzcReIxLi~0R7XstQzRPBQpMBJT~uqhdAP9frU9jAz9ouhcVNprFM9~60UyoDdbuBGfamb6sytDu2o69~L09KrbWXo1G7hU6S1aqMHAmdtSDr0hBryYFje1bkjfVIZ585OFGVYFJNvOvsXcA__\",\"altText\":\"\",\"originalImageWidth\":3484,\"originalImageHeight\":1340,\"isFillWidth\":false}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Add library source code\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h2\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Before we can build the project, we need to add some source code to the library modules.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"For now, we just do the following:\",\"type\":\"text\",\"version\":1},{\"type\":\"linebreak\",\"version\":1},{\"type\":\"linebreak\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"5eb55799f4c5ab6408b9c3ef49b530cb2ccbe9cb\",\"src\":\"https://s3-alpha-sig.figma.com/img/5eb5/5799/f4c5ab6408b9c3ef49b530cb2ccbe9cb?Expires=1765152000\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=fo2XNqxE7hj3MrPbVZn3vVefK0HPQwO4UNBH-zY71n9cED5GF-Y0I6t3MoOHrrFII6JsGa8YAnpyfQ8xTV0dw24N3t6g8VPfVgXS1HX1E7OrHww0hNWxnlFTaomWjBne9jY0TmEwYLhBIn-b4YNRs4qX6fKJFmz~9XihN7wGgeug1aKw2kzHgJzfVZ15xdVzILGKVw7On9qKnYMKUlX2ilXVi~j7fAhLkBjDofN9f7TBeWwgZjTFQnlh5j93RauPfhvj2kITTdmW~szXBJ-ua4VQL~Vx4lmPjiuM7xDMa29EgAjiRhbIH8Rk~3a0sEX7AyOqQ9tqn6Bf3DgBRIJy7Q__\",\"altText\":\"\",\"originalImageWidth\":3484,\"originalImageHeight\":968,\"isFillWidth\":false}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Building the project\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h2\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"By now our project structure looks as follows.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"7f2be9cf37d98687218a7e7eff5d593ef60a59fa\",\"src\":\"https://s3-alpha-sig.figma.com/img/7f2b/e9cf/37d98687218a7e7eff5d593ef60a59fa?Expires=1765152000\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=Dwu40JpfFDP-eF1edTTcytwLT7iLjrn3NJy0xKrnfL9UarejJKk9zYPgIVutTNu~2W7ZgDaAPVXJhFc8DcwmZgA4u8Jsitjelh6eRtTJEeVFk7VHAtLHIlQln84gzQ1D-GjTpz0nmLpAjWfuj7s5dw9MjEhjJnakVED5glnhBg3vco9WUc9RK3E9-5I4Ttl8OfgFqxWTM4zlvzPeFyrsINeYaeOkZf6BFRLRO11myGr8MDl1ZWvwyJ3woVlwkTBv-Mm2EI6nB25Gm-beA-2KNRem5QaLR7cKIMGmMWEg0V7fL-r7zdz4NMF04xCEYDoZ7jir9LmJVAf2tvWoOTYElQ__\",\"altText\":\"\",\"originalImageWidth\":3484,\"originalImageHeight\":1936,\"isFillWidth\":false}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"To build the project run:\",\"type\":\"text\",\"version\":1},{\"type\":\"linebreak\",\"version\":1},{\"type\":\"linebreak\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"970defbc8e10be66a438c0755b902a1d460fc136\",\"src\":\"https://s3-alpha-sig.figma.com/img/970d/efbc/8e10be66a438c0755b902a1d460fc136?Expires=1765152000\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=n9SOEy-sP6eAP6cvklaVm6yhlKmEaazs-XsHcaTkDHfIf3SJsA1J1jhZfOO1reiiX4OujPYmzQJeLGZiGsq6F8gvdi0j7n23DJ9ui0IErzkzNTe7bKnGU2DGs2mrUip52xidN7Z8fbBjes~SUzdMJntQ6nlHkyRUfnUEQSQpBH4e7aHrF1LaMZnvW92fVdToDrcDf5dWuvbaZ2OF2fNsIQhK9JHSLCvuSPNujXXNaAUa7jVn42mm75Beauwc2GrdoNMQu6t9MbpMgXgQYTXLwwcOHYW-W4xbZI0cUkj6ZKVRY6~s7~TpvO9aufs8ySYirqYf9Ben0Lshwgy34ULX3w__\",\"altText\":\"\",\"originalImageWidth\":3484,\"originalImageHeight\":820,\"isFillWidth\":false}],\"direction\":null,\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"linebreak\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Running the project\",\"type\":\"text\",\"version\":1},{\"type\":\"linebreak\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h3\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"To run the project we need to tell \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":16,\"mode\":\"normal\",\"style\":\"\",\"text\":\"cjpm\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" the executable to run.\",\"type\":\"text\",\"version\":1},{\"type\":\"linebreak\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"1419406901f7b99a957b8777b16de20cc270bca3\",\"src\":\"https://s3-alpha-sig.figma.com/img/1419/4069/01f7b99a957b8777b16de20cc270bca3?Expires=1765152000\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=moJrZZkRIuy7RIi2mMaptTHbR7cUSKh0UQVSUbow~~lMmSgNNOi1gz1Mc-qmXjfsLmSS1JmxMVY0y-MxcXUMaya~cKFBXbYLrtR9HaoNfTxDcjRpDmjzQoszHmTPHik28J0ZB8lNS2TAGRUGL4rW7iI6WSW-8U7XuiuDHgjhShpJ8wbCwQ7z~vPEjjOBhWIYC34TD2TLB68R3v7u24SKgJTRbV9isE2aHknHFBonaIlSsr8P3ZLD5m0dhLlyS0OAo~A1zMbdiNr2hTQKjflnipsW9vTNwRb9m4dW-olIvwfbFlXo8lqKk14dfPFoy36pbJDFDyUjzmPA3-Tkzar4ug__\",\"altText\":\"\",\"originalImageWidth\":3484,\"originalImageHeight\":892,\"isFillWidth\":false}],\"direction\":null,\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"9244db9223208498a73710a7986fb25d6b891d50\",\"src\":\"https://s3-alpha-sig.figma.com/img/9244/db92/23208498a73710a7986fb25d6b891d50?Expires=1765152000\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=QYXxMfMzoNuK1ot50m2bR31v7NIo7UQB1U4tCArOltai-Y-xmgTYXJJaqyKpzM0FJAgeMv5BPFayiJ-sDuEVsQWNQ2T0RAyF7zUsHjhv0tGo1~-c1PwCf1FuIxKUsJ~rLdlP8ExNdA3bbSOYGHYi6LecgYEwMgQKh7KOSL-1RPDwxZDu4eZcCqTRRMEwghHITl38AGwab3SR18uKMfWeoaIamDTI-A6e6f2692nzVdmDeEbN-81XxGPC89y4GKfoD4j4Zgev5~50BRwQqZ64W7s2714wcpRjyP4MXuqzy3iz~uclJAcSdEL~5i-BlFBmo92rkIt1TqpND~ugrinKmQ__\",\"altText\":\"\",\"originalImageWidth\":3484,\"originalImageHeight\":968,\"isFillWidth\":false}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"root\",\"version\":1}}","itemId":"7c10a08b-d604-4d4d-a009-2400c53b6b59","fieldSchemaId":"3084d9ba-ab55-4e5a-931b-b9db3d09105f"},{"id":"0672cf53-ff96-446a-bd9c-a08a51c15cb0","value":"Jasper Morgan","itemId":"7c10a08b-d604-4d4d-a009-2400c53b6b59","fieldSchemaId":"df1c88d1-4bd8-4ecd-9059-463b9589de92"}]},"d38bc66e-898e-469d-a28e-7e25efcd5e82":{"id":"d38bc66e-898e-469d-a28e-7e25efcd5e82","index":"$","collectionId":"d4a5b68c-8afd-4bbe-a7ac-e9a8422fedde","fields":[{"id":"6d69928b-4062-4ad0-b447-d24513d31abe","value":"{\"image\":\"39b7c57677dbaa98a48e9447b3db9cfc2cb2f014\",\"imageThumbnail\":\"d7f95baf792286c05c08db378e83ad0276353ff9\",\"originalImageHeight\":1235,\"originalImageWidth\":1794,\"altText\":\"\",\"fileName\":\"Image_4.png\"}","itemId":"d38bc66e-898e-469d-a28e-7e25efcd5e82","fieldSchemaId":"1f58afa6-2748-4188-b4a4-f1e54e37eca9"},{"id":"4120a9b0-8321-48c7-8c96-bfe2abe9b300","value":"Volodymyr Voiko","itemId":"d38bc66e-898e-469d-a28e-7e25efcd5e82","fieldSchemaId":"df1c88d1-4bd8-4ecd-9059-463b9589de92"},{"id":"01ca3a41-18c9-4ac1-80ee-9e7d0a0fd52f","value":"iOS Developer","itemId":"d38bc66e-898e-469d-a28e-7e25efcd5e82","fieldSchemaId":"0a981f8a-7dbb-440d-a940-25d9060c9b11"},{"id":"9efe3ac5-aeac-41ef-9ac9-fca9b11ff379","value":"2025-02-27","itemId":"d38bc66e-898e-469d-a28e-7e25efcd5e82","fieldSchemaId":"b7712ee6-f9fd-4781-8c5c-e7e10ce8f81e"},{"id":"51f55306-85a0-4837-a635-bf3171ea262a","value":"meet-snapptheming","itemId":"d38bc66e-898e-469d-a28e-7e25efcd5e82","fieldSchemaId":"402ba26f-8f6d-4f5f-bf20-62e6549f4ad4"},{"id":"d800c49b-36a1-420f-baf9-8e7ff0cf123a","value":"Meet SnappTheming","itemId":"d38bc66e-898e-469d-a28e-7e25efcd5e82","fieldSchemaId":"f2ba59b9-49cc-4ec6-9416-bda99d4c8383"},{"id":"d8550051-b54a-41a1-86c2-cfad48921f98","value":"{\"root\":{\"children\":[{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"iOS Developer at Snapp Technology 📱, where I focus on building smooth, reliable, and user-friendly mobile experiences. I started my journey on the Android side 🤖, but eventually crossed over to iOS and never looked back. Outside of work, I’m a family man who loves spending time at home, usually surrounded by a very enthusiastic collection of pets.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"root\",\"version\":1}}","itemId":"d38bc66e-898e-469d-a28e-7e25efcd5e82","fieldSchemaId":"0b77f83b-c31a-4889-b9b3-9a6d2e41fc86"},{"id":"530214dc-b3fc-4e03-aa06-3a899ef04d0a","value":"{\"root\":{\"children\":[{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Today, most applications interact with cloud-based content. In addition to content, app configurations such as feature flags, translations, and even UI elements (Server Driven UI) are often managed from the server. But what about theming? How can we hotswap or update app themes without requiring app updates?\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"I have the answer! Recently, we at \",\"type\":\"text\",\"version\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"snappmobile.io\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"link\",\"version\":1,\"rel\":\"noopener ugc nofollow\",\"target\":\"_blank\",\"title\":null,\"url\":\"https://www.snappmobile.io/\"},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" announced our open-source library, SnappTheming. This Swift framework simplifies the integration of dynamic design themes into your applications. By utilizing JSON declarations, SnappTheming facilitates the extraction and application of various theming elements, including colors, fonts, gradients, and shape styles, directly into the application’s user interface.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"In this article, we will explore how to get started with the SnappTheming library, including installation steps and basic usage.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Getting Started\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h2\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"In this section, we will create a sample app that utilizes the SnappTheming dependency. We will define a theme and use its declaration to retrieve styling elements and apply them to various UI components. This will demonstrate how easy it is to implement dynamic theming in your application.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"To get started, first create a new project in Xcode.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Creating the Project\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h3\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Before we begin, ensure that you have Xcode installed (make sure it’s a version compatible with Swift). Follow these steps to create a new Xcode project:\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Open Xcode and select “Create a new Xcode project.”\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Choose the appropriate template for your app, such as “Single View App.”\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":2},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Fill in the necessary details like project name and organisation identifier, then click “Next” to create the project.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":3}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"list\",\"version\":1,\"listType\":\"number\",\"start\":1,\"tag\":\"ol\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"0eddb726b307ac23727bd7ef114edbb6b3523219\",\"src\":\"https://s3-alpha-sig.figma.com/img/0edd/b726/b307ac23727bd7ef114edbb6b3523219?Expires=1765152000\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=Y1jIbALwhMc7WKx7HtmkCtKzgeL9ejdAI1YtospFY2EMRjWaa-UebjkjQ0jJRuoCElty84eR6n~XNOZ6H-jJ5dO7E5WHNUtjz8l-txd3rLCnhsiDHLFhJtlWbiU29uSzMzk0ogl1apNRdr-OqTI2iDZb--W6QeXTIeecg6G51L4x~ZYcDn33R8k2aBJGTvGUOczwuMXwiuunREgmdheJKgWWpBzrpkCfqSBs-1F2XZ5r1-3Rdz0CI14NdTsYEjnkJ~zw2PxmP~Se17IqDAH5u3eU-xqnxzXd8ByJGJ5htvciS9WZe-z7Npvsy4ByHldtorPK7npsEI4CdDuquTt2yg__\",\"altText\":\"\",\"originalImageWidth\":1960,\"originalImageHeight\":1402,\"isFillWidth\":false}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Adding the Framework Dependency\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h3\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Next, we need to add the \",\"type\":\"text\",\"version\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"SnappTheming\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"link\",\"version\":1,\"rel\":\"noopener ugc nofollow\",\"target\":\"_blank\",\"title\":null,\"url\":\"https://github.com/Snapp-Mobile/SnappTheming\"},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" package dependency to our project. Follow these steps:\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Open your project’s settings and navigate to the “Swift Packages” tab.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Click the “+” button to add a new package.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":2},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Enter the URL for the SnappTheming repository and select the version you want to use.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":3},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Click “Add Package” to include it in your project.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":4}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"list\",\"version\":1,\"listType\":\"number\",\"start\":1,\"tag\":\"ol\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Now that we have set up our project, we are ready to create our first theme.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"876e3b504af44f293c0853f82c417201e26e2bcd\",\"src\":\"https://s3-alpha-sig.figma.com/img/876e/3b50/4af44f293c0853f82c417201e26e2bcd?Expires=1765152000\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=hBhVuCFdFxDqCd-GeP6TM~-TrT7TMF-bUcY4bwFgLd4n5XhOdjVWlw6cwrT5UwT8MIihanC~89hpaXmKWmEJn5M50vnigmDT5fcORYDPuWIolto7iKRO0flbCYW9Tv-vDwrhyexNLVkI2HgWxsz930pCabCludoDgFRtea4NMJMf~ybq~T-8R0KcD-t2HmavTo1UZn78va93KQ~7FzqNaOLWuKhoePCq6L-cGI~1XWrYH3V9FVqvJ9ZHOxDQBSeTKMNKK6cNjJUlAmaikJQFqy5HvZf9Mtf0t3z4c5BP366e0jfoTy9VdAx8ZHSYcLkR433rE1Glh49ZsOgH8ePvuQ__\",\"altText\":\"\",\"originalImageWidth\":2148,\"originalImageHeight\":1402,\"isFillWidth\":false}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Basic Usage\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h2\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"To begin, it’s important to understand the fundamental concepts of theming. SnappTheming utilizes \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":16,\"mode\":\"normal\",\"style\":\"\",\"text\":\"JSON\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" for theme declarations, which are then parsed to allow developers to easily resolve values and map them to the appropriate UI types.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"The framework includes several foundational objects, such as \",\"type\":\"text\",\"version\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Colors\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"link\",\"version\":1,\"rel\":\"noopener ugc nofollow\",\"target\":\"_blank\",\"title\":null,\"url\":\"https://ios-theming.snappmobile.io/documentation/snapptheming/snappthemingcolordeclarations\"},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\", \",\"type\":\"text\",\"version\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Fonts\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"link\",\"version\":1,\"rel\":\"noopener ugc nofollow\",\"target\":\"_blank\",\"title\":null,\"url\":\"https://ios-theming.snappmobile.io/documentation/snapptheming/snappthemingfontdeclarations\"},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\", \",\"type\":\"text\",\"version\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Gradients\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"link\",\"version\":1,\"rel\":\"noopener ugc nofollow\",\"target\":\"_blank\",\"title\":null,\"url\":\"https://ios-theming.snappmobile.io/documentation/snapptheming/snapptheminggradientdeclarations\"},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\", \",\"type\":\"text\",\"version\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Images\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"link\",\"version\":1,\"rel\":\"noopener ugc nofollow\",\"target\":\"_blank\",\"title\":null,\"url\":\"https://ios-theming.snappmobile.io/documentation/snapptheming/snappthemingimagedeclarations\"},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\", \",\"type\":\"text\",\"version\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Lottie Animations\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"link\",\"version\":1,\"rel\":\"noopener ugc nofollow\",\"target\":\"_blank\",\"title\":null,\"url\":\"https://ios-theming.snappmobile.io/documentation/snapptheming/snapptheminganimationdeclarations\"},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\", \",\"type\":\"text\",\"version\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Metrics\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"link\",\"version\":1,\"rel\":\"noopener ugc nofollow\",\"target\":\"_blank\",\"title\":null,\"url\":\"https://ios-theming.snappmobile.io/documentation/snapptheming/snappthemingmetricdeclarations\"},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\", and \",\"type\":\"text\",\"version\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Shapes\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"link\",\"version\":1,\"rel\":\"noopener ugc nofollow\",\"target\":\"_blank\",\"title\":null,\"url\":\"https://ios-theming.snappmobile.io/documentation/snapptheming/snappthemingshapedeclarations\"},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\".\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"In addition, there are higher-level objects, including \",\"type\":\"text\",\"version\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Aliases\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"link\",\"version\":1,\"rel\":\"noopener ugc nofollow\",\"target\":\"_blank\",\"title\":null,\"url\":\"https://ios-theming.snappmobile.io/documentation/snapptheming/jsonschema#Aliases\"},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\", \",\"type\":\"text\",\"version\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Button Styles\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"link\",\"version\":1,\"rel\":\"noopener ugc nofollow\",\"target\":\"_blank\",\"title\":null,\"url\":\"https://ios-theming.snappmobile.io/documentation/snapptheming/snappthemingbuttonstyledeclarations\"},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\", and \",\"type\":\"text\",\"version\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Typography\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"link\",\"version\":1,\"rel\":\"noopener ugc nofollow\",\"target\":\"_blank\",\"title\":null,\"url\":\"https://ios-theming.snappmobile.io/documentation/snapptheming/snappthemingtypographydeclarations\"},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\". The framework also supports configurations for various UI components, such as \",\"type\":\"text\",\"version\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Toggle Styles\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"link\",\"version\":1,\"rel\":\"noopener ugc nofollow\",\"target\":\"_blank\",\"title\":null,\"url\":\"https://ios-theming.snappmobile.io/documentation/snapptheming/snappthemingtogglestyledeclarations\"},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\", \",\"type\":\"text\",\"version\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Segment Control Styles\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"link\",\"version\":1,\"rel\":\"noopener ugc nofollow\",\"target\":\"_blank\",\"title\":null,\"url\":\"https://ios-theming.snappmobile.io/documentation/snapptheming/snappthemingsegmentcontrolstyledeclarations\"},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\", and \",\"type\":\"text\",\"version\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Slider Styles\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"link\",\"version\":1,\"rel\":\"noopener ugc nofollow\",\"target\":\"_blank\",\"title\":null,\"url\":\"https://ios-theming.snappmobile.io/documentation/snapptheming/snappthemingsliderstyledeclarations\"},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\".\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"To learn more about each object, refer to the \",\"type\":\"text\",\"version\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"JSON Schema\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"link\",\"version\":1,\"rel\":\"noopener ugc nofollow\",\"target\":\"_blank\",\"title\":null,\"url\":\"https://ios-theming.snappmobile.io/documentation/snapptheming/jsonschema\"},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" article in the \",\"type\":\"text\",\"version\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"documentation\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"link\",\"version\":1,\"rel\":\"noopener ugc nofollow\",\"target\":\"_blank\",\"title\":null,\"url\":\"https://ios-theming.snappmobile.io/documentation/snapptheming\"},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" page.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Creating a Theme\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h3\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Creating a theme is a straightforward task. All you need to do is create an empty JSON file. Then, define the properties for the objects you want to include in your theme and specify their values.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"9891f54d2d5b48ec2c1a851b3494eee65277e380\",\"src\":\"https://s3-alpha-sig.figma.com/img/9891/f54d/2d5b48ec2c1a851b3494eee65277e380?Expires=1765152000\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=X-i5Z7QUUxzjgoaZMkCwl92c2V4RIIhsJshdcnFBsp8nHa8CAIPucA02EwY2bITWBFCQkDe0y5sagVZ21F3M8dTomU1POOi5544tKwi4j9Q1YCKrzfHt-peSlbY-YjBDwSYELDq7OePDwa7SpvfTTa5T1pjmkWV7HYNQuq6kIUkiTMgRiYnkSRf-ymz54BXD3PDPl6hdJzPLtgm547V6VUvmZ6LR07gpcq5ikfkEEUd9hk6ydbaY9tDmmb1vsZmXFcPZXMef3o53Kk9DQgbPr5PvS-TItKXyyWP0UPCICseHTb5ga65Yxo5AXDZ7dqfNRma-zEi7tvcYJsBzmu26Fw__\",\"altText\":\"\",\"originalImageWidth\":3484,\"originalImageHeight\":820,\"isFillWidth\":false}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Now we’ll create our first theme, which will consist of colors, metrics, fonts, and typography (utilizing the declared fonts and metrics through \",\"type\":\"text\",\"version\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"aliases\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"link\",\"version\":1,\"rel\":\"noopener ugc nofollow\",\"target\":\"_blank\",\"title\":null,\"url\":\"https://ios-theming.snappmobile.io/documentation/snapptheming/jsonschema#Aliases\"},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"), as well as shapes, and incorporate all of these elements into button styles.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Adding Colors\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h3\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"We can expand our JSON by adding a \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":16,\"mode\":\"normal\",\"style\":\"\",\"text\":\"colors\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" property and including several color values. For instance, we will incorporate \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":16,\"mode\":\"normal\",\"style\":\"\",\"text\":\"primary\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" and \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":16,\"mode\":\"normal\",\"style\":\"\",\"text\":\"secondary\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" for tints, \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":16,\"mode\":\"normal\",\"style\":\"\",\"text\":\"surfacePrimary\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" and \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":16,\"mode\":\"normal\",\"style\":\"\",\"text\":\"surfaceSecondary\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" for backgrounds, and \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":16,\"mode\":\"normal\",\"style\":\"\",\"text\":\"textPrimary\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" and \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":16,\"mode\":\"normal\",\"style\":\"\",\"text\":\"textSecondary\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" (along with \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":16,\"mode\":\"normal\",\"style\":\"\",\"text\":\"textPrimaryInverted\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" and \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":16,\"mode\":\"normal\",\"style\":\"\",\"text\":\"textSecondaryInverted\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" for light/dark text on dark/light backgrounds). Additionally, since some colors will be reused, we will also include some base colors like \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":16,\"mode\":\"normal\",\"style\":\"\",\"text\":\"white\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\", \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":16,\"mode\":\"normal\",\"style\":\"\",\"text\":\"black\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" and \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":16,\"mode\":\"normal\",\"style\":\"\",\"text\":\"gray\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" for this purpose.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"58b939eb2bab6a5724388ec7b41f1673a570d777\",\"src\":\"https://s3-alpha-sig.figma.com/img/58b9/39eb/2bab6a5724388ec7b41f1673a570d777?Expires=1765152000\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=sSQPDrtyp3i1o~wotL~c0vunUzA1CoEReHUCtbW8-lWh2cRrdM5xhbQEJWMSGFSnZiFgHBFKFH0D7~tzl8pX~o~qpHEc7LSoAWu7aZ~4vtkKOA0jPS8Bv5EnZWR5SjFrySnMI~rnU9JAhz3TY738irAeBd7KqdI6PHT2ZsChVETPAq6upksvnkXcf5RaD1m~WV8Nhe5KMxNkAsp6zZZYuZcf7yoZW3bOJTTKauW3~qMR7k1d5~uDVxQ47UTFZOIXG8cyOPkxiog9EnaR8-F3CvGYbwr6nuqCLYs3mHjJqSv~rg1aDEsjXD4RjcpbvV~v8HrjWZpVslgnsDbwEHJtmA__\",\"altText\":\"\",\"originalImageWidth\":3484,\"originalImageHeight\":1860,\"isFillWidth\":false}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Now that we have added all the colors we need, let’s move on to metrics.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Adding Metrics\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h3\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Similar to colors, we need to add a \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":16,\"mode\":\"normal\",\"style\":\"\",\"text\":\"metrics\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" property to our theme JSON and specify its values. For our demo app, we will include some spacing and radius values:\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"98b52e11dbc489b4033fbef2931871d0dc9aaf4a\",\"src\":\"https://s3-alpha-sig.figma.com/img/98b5/2e11/dbc489b4033fbef2931871d0dc9aaf4a?Expires=1765152000\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=KnAjz54oxUJXGwMy0RIKgfoJG1BKiK7c016QAd-tY4x3-AFDy1tE3CEQV2JxXCSzjd2EhzZhfufURVkDkY6gxgRtJZUSZdbXYP1lct8G9UtBe37kb3DNz-z4YVv4ZvIYs-IHUB0PbNQrU9U6G-NEGHgRl2-kebZfEg3SClQDNiyvCoC2lCs1q7xOLJ4gT~DkLPB9xa4Cougji8Ryo6LcAK710zrO-bZdAvXdmkVQkx5EaZj5ReDJR4rv3jVk5N~1TfxjYz-sl7c8wyxGZJoAHthkm~nGVdsPE~-UhrCqg7kjcLRS7ttRvF-eKkEf51BMADJQNAFJSzToyzYOYRQwgQ__\",\"altText\":\"\",\"originalImageWidth\":3484,\"originalImageHeight\":1488,\"isFillWidth\":false}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Adding Shapes\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h3\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Shapes are commonly used in any app to define the appearance of UI components, and fortunately, SnappTheming supports shapes as well. In our demo app, we will utilize shapes to style various bars and buttons. Here’s how to add some shapes:\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"74f4d7a688b696d4e0749a71e9e1238451ee37d5\",\"src\":\"https://s3-alpha-sig.figma.com/img/74f4/d7a6/88b696d4e0749a71e9e1238451ee37d5?Expires=1765152000\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=mSxkn-iyNA5RRwkvjITCTnkVXr1kGq-Tk-iTRFwEWXegGvaKRcClF1OmtyvPTEClXlSo3iyAf3jmDAYd1xgaXF-FnIeGAZRfEWlEx8mENIN8EZkEPKi19r76wZWKLhgBSlK5lM-dvM3BTC2U~NeTDuz2YG9UVBOvunxyoH29Oog9fn47IAdjJpaVUD~iNMcY4T6ih2~DWVFRAn-h9OoJVKK4fhsp2MDpNDgHRV3xcpdbt9Bvk-0QKrTXmxyWL2zyevY0yQeyGG7W0rPfN0AkAWzieGhMoW3ZeakNjQdc6RACyHhy6CqzrkApWkaF8sSkwhThqkkhWL2HlTstsbfnkw__\",\"altText\":\"\",\"originalImageWidth\":3484,\"originalImageHeight\":2980,\"isFillWidth\":false}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"We’ve built a solid foundation of styling values, but we’re still missing important elements such as images and fonts. Let’s continue exploring the framework to learn how to manage resource-based theme properties.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Adding Resource-Based Properties\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h3\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"In addition to value-based properties, the SnappTheming theme declaration also supports binary formats. For example, images and fonts can be bundled with the theme JSON. Binary data is stored as a \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":16,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Base64\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" string alongside its type. However, dealing with large strings can be cumbersome. To simplify the theme generation process, we provide a utility script called \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":16,\"mode\":\"normal\",\"style\":\"\",\"text\":\"theme_generator\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\".\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"We will demonstrate this process using fonts (the procedure is identical for images).\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"First, clone the SnappTheming repository and navigate to the generator directory:\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"bfc7efb886de90b8067ca222a049d4a4b5bc87be\",\"src\":\"https://s3-alpha-sig.figma.com/img/bfc7/efb8/86de90b8067ca222a049d4a4b5bc87be?Expires=1765152000\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=maYY9P5MB3IykW49vNCquMYrrd8CapHcLLxyZCFs8YLEnA5vQUvGI1sd~KwrYrBq23QnAmP3Z7LXXIOE0Oi0d20BK1vM3UAugoSFbw6z3y8ZYZjzVb2c9zfalGT33karJhRdzckwY7pakk~0g8dZ67IWUmUlciajA6Fu-tmtJ1ttsFmSnLf~26qCSkPeaeBdpmhAw2ABpJ2f3JGrypA5Rxlb1D9~f25GltMQbYbyEKZT1sFc8TJPPZDektBNcAwYZd1Pt~2C2Y1kPcbGX~SAU19yxi2CLsnLw2T6S6zv8FIkM1HILH3OEG4bm46Pv7YjweaGnPZTCwGn4Uzfr-soiw__\",\"altText\":\"\",\"originalImageWidth\":3484,\"originalImageHeight\":892,\"isFillWidth\":false}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Next, create a \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":16,\"mode\":\"normal\",\"style\":\"\",\"text\":\"base.json\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" file containing the contents of our theme. Here is what our completed json will look like:\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"3aaa77eedee9089ff5de31d9d6cdc9a0fd8464bb\",\"src\":\"https://s3-alpha-sig.figma.com/img/3aaa/77ee/dee9089ff5de31d9d6cdc9a0fd8464bb?Expires=1765152000\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=Ny6bvTEDXG7fKvOPI2SsnZNCe9-8gT~yg6gG1LmGjsCyawV5tiUHIlPYw1YlvaFs1DEPHRlLwlteK0XhX9LtGb2LgHZRT1tMY-iQKEUMiR-67tLJVJNAcSov38L8UNWMOzq4-2pb6WfvPz4NfKODVriCmfPq4A6GbAygun3Scx3G9pSaD0pOpcUzmqDrOuXp0pH45wWwXP~mf~SDJQfmdj2gtDfAzA8ilkWzTqiLvkOklsIUhCcaddzk9tphKtcQkWyZIKYPAEXb1Bg5oIALDw4fy8dwkVFRSseVYs6DNfYLg9wrGPrMFdXKkTUhbOBQCYfqEAgiYyL4LRQeKkJqyw__\",\"altText\":\"\",\"originalImageWidth\":3484,\"originalImageHeight\":4320,\"isFillWidth\":false}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Next, place the fonts you want to add to your theme in the fonts directory. For the demo app, we will use the free version of the \",\"type\":\"text\",\"version\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Silka Regular\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"link\",\"version\":1,\"rel\":\"noopener ugc nofollow\",\"target\":\"_blank\",\"title\":null,\"url\":\"https://www.atipofoundry.com/fonts/silka\"},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" font.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"After completing the above steps, we can run the generation script to see the results in theme.json:\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"d5843f83f873e4cb0d3bc1db4866096b48a97d97\",\"src\":\"https://s3-alpha-sig.figma.com/img/d584/3f83/f873e4cb0d3bc1db4866096b48a97d97?Expires=1765152000\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=JtJs9EIlF3KQHWfeLtW3DdFhPGMLCMTxE8fHANWaSehZBay3Gy0IHUwx6zIZLpd7K8kFu2hFxWGuoxUvAQhnnMH5hjaX8N9hfzfBcwXXoBPmAWvfZBxFINmYQpmt0dDw8nzF5Q19~IMEwHjw5FDVGeHONxbQyn-ebzez8OqOVnUuKslnAYorLYMy4wSizzSCGMFNvJmSr3-T7Qk~qVl8EcR97jLOo-dIHTkFbecjipkiSrIPW-qjrCOPZxY1HlBGn~Cgsu1eujbnt-1NAh8dKX4iI-skJyJ3MEq38jsA~eIUr68Q6vrd0yESQBtq9RlV9~BMAx5i2shN-oG6NeA6Jw__\",\"altText\":\"\",\"originalImageWidth\":3484,\"originalImageHeight\":820,\"isFillWidth\":false}],\"direction\":\"ltr\",\"format\":\"left\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"left\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"5bbacd3bb79fd76e6e881c25eb833ebaa06ad3dc\",\"src\":\"https://s3-alpha-sig.figma.com/img/5bba/cd3b/b79fd76e6e881c25eb833ebaa06ad3dc?Expires=1765152000\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=GCZUovZPwGIq08V4IsQZ7x-6JF4UCWfyoue4z8oL2zFxoB0tOuqwkttZ4X-Kz8CbS0MOAKYlpnpL2YU1zGbI~q5rk960MOww3q2XP6XzA~wmvkVxKqD1raeR7b1N~cOdIij7A3KFjPqCd7iSAjcu7hVHFCjrSvDzLOqKUr7K~bQYvtYUhqq14ghpj5xpxm3A971FSq2tYbs~2XU52nug2FV2PvmiO4QPkOrcWToVxq6wyOD6lk~pJW5egt16cHQyjG0PWLusjQm88IXFYpYFfBpP3uWEEYHoHuhLE6IBN9cCVxGajjpUP4B~gerEhjW8tdBCTOKYpsYs4Hvpvztpbw__\",\"altText\":\"\",\"originalImageWidth\":1220,\"originalImageHeight\":290,\"isFillWidth\":false}],\"direction\":\"ltr\",\"format\":\"left\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"left\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"As a result, we will have a completed \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":16,\"mode\":\"normal\",\"style\":\"\",\"text\":\"theme.json\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" that contains everything combined. It will look like this:\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"left\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"left\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"798718e2047a8ed1f08d82d3acf2556ab87dc4f6\",\"src\":\"https://s3-alpha-sig.figma.com/img/7987/18e2/047a8ed1f08d82d3acf2556ab87dc4f6?Expires=1765152000\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=gtkg~j1NSDe2bRqYKLSTcBw82b~yy56cKPgOSA8xA1R6TH-98fVnRHzzcPYWnhgy6YOzdPr7YvLWDfEUqWokHmR0MLWhEjXP~jb64~nbgX~ASKcadhFGVmUsTVh2ffR4QhV~Yu0rgSdPi~~E9LCqtmVthWHNeJkDLq~J~QdINSNqxZ~9BtuzJoWqU1dKNxg9J6CkUzEthsc5OSznp5IDzorGjBPJUFm99SW~WJO4W5olrRLaopB7qv11Bs9eUYZW~qjN5XPlpdAgpKztMxnjNRkwV01tyqAaW2DYJXxyAIvWWUVev9sh41SKrhzt8YUbDy61M7iXhtZvPz1~IEpapw__\",\"altText\":\"\",\"originalImageWidth\":3484,\"originalImageHeight\":4988,\"isFillWidth\":false}],\"direction\":\"ltr\",\"format\":\"left\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"left\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Adding Typographies\",\"type\":\"text\",\"version\":1},{\"type\":\"linebreak\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h3\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"With the fonts in place, we can now build typographies based on them. All we need to do is add a \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":16,\"mode\":\"normal\",\"style\":\"\",\"text\":\"typography\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" property and specify the typographies we want in our theme by setting the \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":16,\"mode\":\"normal\",\"style\":\"\",\"text\":\"font\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" (an alias for the font) and \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":16,\"mode\":\"normal\",\"style\":\"\",\"text\":\"fontSize\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\".\",\"type\":\"text\",\"version\":1},{\"type\":\"linebreak\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Let’s modify \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":16,\"mode\":\"normal\",\"style\":\"\",\"text\":\"base.json\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" with the following additions:\",\"type\":\"text\",\"version\":1},{\"type\":\"linebreak\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"798718e2047a8ed1f08d82d3acf2556ab87dc4f6\",\"src\":\"https://s3-alpha-sig.figma.com/img/7987/18e2/047a8ed1f08d82d3acf2556ab87dc4f6?Expires=1765152000\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=gtkg~j1NSDe2bRqYKLSTcBw82b~yy56cKPgOSA8xA1R6TH-98fVnRHzzcPYWnhgy6YOzdPr7YvLWDfEUqWokHmR0MLWhEjXP~jb64~nbgX~ASKcadhFGVmUsTVh2ffR4QhV~Yu0rgSdPi~~E9LCqtmVthWHNeJkDLq~J~QdINSNqxZ~9BtuzJoWqU1dKNxg9J6CkUzEthsc5OSznp5IDzorGjBPJUFm99SW~WJO4W5olrRLaopB7qv11Bs9eUYZW~qjN5XPlpdAgpKztMxnjNRkwV01tyqAaW2DYJXxyAIvWWUVev9sh41SKrhzt8YUbDy61M7iXhtZvPz1~IEpapw__\",\"altText\":\"\",\"originalImageWidth\":3484,\"originalImageHeight\":4988,\"isFillWidth\":false}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Adding Button Styles\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h3\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"We have added almost everything we need to style our demo app. Now, let’s combine all that we have into the last high-level object: \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":16,\"mode\":\"normal\",\"style\":\"\",\"text\":\"ButtonStyle\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\". The \",\"type\":\"text\",\"version\":1},{\"children\":[{\"detail\":0,\"format\":16,\"mode\":\"normal\",\"style\":\"\",\"text\":\"ButtonStyle\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"link\",\"version\":1,\"rel\":\"noopener ugc nofollow\",\"target\":\"_blank\",\"title\":null,\"url\":\"https://ios-theming.snappmobile.io/documentation/snapptheming/snappthemingbuttonstyledeclarations/\"},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" is similar to \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":16,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Typography\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" in that it is an aggregate of other objects containing the properties needed to style buttons.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":16,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":16,\"mode\":\"normal\",\"style\":\"\",\"text\":\"ButtonStyle\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" includes properties such as surface and text colors, border widths and colors, shapes, and typography for various button states.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":16,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"In our example, we will create two button styles using \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":16,\"mode\":\"normal\",\"style\":\"\",\"text\":\"primary\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" and \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":16,\"mode\":\"normal\",\"style\":\"\",\"text\":\"secondary\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" colors. We will also add some additional colors for button states:\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"c5241de3e6e763cdbf4901e435af72ada1974db5\",\"src\":\"https://s3-alpha-sig.figma.com/img/c524/1de3/e6e763cdbf4901e435af72ada1974db5?Expires=1765152000\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=NFX8IQVVeN8U0bskVX5UusmXhLIL9ZbMm91L2ZH-gVMCLs-e~YoVUMG-wwW0jjuE2puR48FG5~C~NymGtd-qcpQnSH~OaksSdQKOLnW4DuGey92wQ5dvYtSkKIdhaI~4fH9AtapVW6jgusz5QjfVwruA8ZG~3m29k~dgyHcbWF1edyO6mGwUmvbLveSEwOMAezKRVFvG3SxewvJf22suewY5BlJTLG7P3zwf2PIFwQK0jUVrg3tAKWjFpx7sD8~pP9I7vqYe5Kbh52PRtIXB6qpGUUU8LZxfBIeIyeSAWdJsnrMRb~dSGeeAlsBZeU52ukTHLndnDSahNYK0erreIQ__\",\"altText\":\"\",\"originalImageWidth\":3484,\"originalImageHeight\":3948,\"isFillWidth\":false}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Our Theme JSON is complete! Next, we will build some UI and style it using our theme.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Apply Theme\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h2\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Before applying the theme, let’s generate it once again. We have updated our \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":16,\"mode\":\"normal\",\"style\":\"\",\"text\":\"base.json\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" recently but the resulting \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":16,\"mode\":\"normal\",\"style\":\"\",\"text\":\"theme.json\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" hasn't been updated afterwards.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Parse Theme\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h3\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"To apply a theme we should parse its json into a \",\"type\":\"text\",\"version\":1},{\"children\":[{\"detail\":0,\"format\":16,\"mode\":\"normal\",\"style\":\"\",\"text\":\"SnappThemingDeclaration\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"link\",\"version\":1,\"rel\":\"noopener ugc nofollow\",\"target\":\"_blank\",\"title\":null,\"url\":\"https://ios-theming.snappmobile.io/documentation/snapptheming/snappthemingdeclaration\"},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\". For that purpose we have a \",\"type\":\"text\",\"version\":1},{\"children\":[{\"detail\":0,\"format\":16,\"mode\":\"normal\",\"style\":\"\",\"text\":\"SnappThemingParser\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"link\",\"version\":1,\"rel\":\"noopener ugc nofollow\",\"target\":\"_blank\",\"title\":null,\"url\":\"https://ios-theming.snappmobile.io/documentation/snapptheming/snappthemingparser\"},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\". Parsing a theme can be configured using \",\"type\":\"text\",\"version\":1},{\"children\":[{\"detail\":0,\"format\":16,\"mode\":\"normal\",\"style\":\"\",\"text\":\"SnappThemingParserConfiguration\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"link\",\"version\":1,\"rel\":\"noopener ugc nofollow\",\"target\":\"_blank\",\"title\":null,\"url\":\"https://ios-theming.snappmobile.io/documentation/snapptheming/snappthemingparserconfiguration\"},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" which contains parameters that affect how the theme is defined.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":16,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Let’s modify our \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":16,\"mode\":\"normal\",\"style\":\"\",\"text\":\"ContentView\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" and load the theme file and parse it to the declaration:\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"dc9796f39d207e43de056c321d81180c531af9bf\",\"src\":\"https://s3-alpha-sig.figma.com/img/dc97/96f3/9d207e43de056c321d81180c531af9bf?Expires=1765152000\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=lHoh7fncUWnJKsbCQr~rX2jy9N-L~z0-ZHBklJV7RCMiABI7veidRfI1udha1fR1asVy0fnpMIwyg1W~2GquJJJ5t44Sy6R7ECUcmyrB0MW0ffOHZkknHFIEcUA81u~sjm7CEmgSHjWpch4qkNr6oZk7lUUhrc2xpTZ54EjOn1WZLRBBjTQibPderFmLyOGO6isiq-BIksNDTAjVkyO9abIt~xXPru6ylEAaw01y0hUpEr4yBViTUxqnyG3rko0ij7JIKejPEfnkfzh-8kl00O2y3gILnBsRbQ5p8VA0oFZhXO6MrzOqb~Ez10Z36J2bnEyZVynWi2CnVRg6xXWc4g__\",\"altText\":\"\",\"originalImageWidth\":3484,\"originalImageHeight\":1936,\"isFillWidth\":false}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":2,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Note: force unwraps used only for example, for sure in production code you shouldn’t go in that direction.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":2,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":2,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Sample UI\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h3\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"We now have the theme defined and parsed. Next we will create some UI that we want to style.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"ebd531e61d4b90d72b87417057afa0b011a4d4f4\",\"src\":\"https://s3-alpha-sig.figma.com/img/ebd5/31e6/1d4b90d72b87417057afa0b011a4d4f4?Expires=1765152000\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=POkbBgBSzD1kLWJ~MfRycQL9rYKJZVKqYqJH-IyZ5apDCQWhGw~9uQUXKCzeqU98tVTNZjlgse5xyiTrAWDAR-NUJgudVj7Wok0CdEDYATHsM9qMl0DwuUrJq80gNv7PIA9ZxfLn4jtu1G~fC1j~cZsrkhgTq6e-6pPxorXwTyENIkc75a4o-bYOur2FNDudGtpXb~Wl6zBLkja7lSsKiKmHcuoz04qfIvhUygESbc9YHdIZCU2URhwyoWmKRiav3BxrgWP8xuS~~D2zWR9bhU71BYphL94z2o22nv~joWYAGLwpr7raS4aloQVxI7yTkH0YZRnKSMKj92ZMG5cV1g__\",\"altText\":\"\",\"originalImageWidth\":3484,\"originalImageHeight\":3724,\"isFillWidth\":false}],\"direction\":null,\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"91b07fb1c9b5b6062dcfdc712600ef5626e55a8f\",\"src\":\"https://s3-alpha-sig.figma.com/img/91b0/7fb1/c9b5b6062dcfdc712600ef5626e55a8f?Expires=1765152000\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=A11XeMe~2TABmVCZOZicoG4pIodCUmE90daVuQvKYuM3U1Bh2wRMl6LV2o1etokBkknqMPTxgixNAwUgjR1DNzu2wGdahO79YR8ReJZry-WRHqpxNwBMqlm30H62M2l2QfAB-k2dnl3HYJ485lDc2273fyEdjDSvUZb93-R7HFy1R7flcdXcSmesmVUB1tsDEI2HvChdz7qOHP6rGEq2XudpZXKcDCRXCY8G-RU9IhV3UAhPh5HyxahMkCzR3GFcU~qOFBOlpp21J2INNLDX2X6G~bzO4Cujj5rtqH04Cj2dRWgWLtWAxV~0naG6pLDrela6FOnwUiGmy~aozoDsbw__\",\"altText\":\"\",\"originalImageWidth\":1206,\"originalImageHeight\":2622,\"isFillWidth\":false}],\"direction\":null,\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"It consists of a top bar with app title, icon and button as content, and a bottom bar with another button.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Styling App Top Bar\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h3\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Now we can style it. Let’s start with the top bar. We will apply a shape to its background, use fill color, and set text color and typography for the title.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"8c060f5305362241de08626765c0b383bcb00696\",\"src\":\"https://s3-alpha-sig.figma.com/img/8c06/0f53/05362241de08626765c0b383bcb00696?Expires=1765152000\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=XJEhfDwETRKF5OGwThbYvoue15QNY5VJMyUe-xgCJPqioPuGBE2EIHYN9OzGbP33OmdQ7Hs9UkgJ5o6y13pKwGjBaQbBFyN2o-Xvz9dOf8~9V2JdbbMs5a6PvpQmHVAGdFekxAlZa4VqK4vB7Z-OWFtpyXiS0MsXk8d0Wr5jzwd2Wno23MvgtDcF2Cxu5VAdxXVCzga6i5-nN1v8pKu5TIEWtCvjvThlqdzYOR~JV-a6zE1O2m4yVqpzVnTtsjGAahCNfhsJ3TJO9eUAx8O5~nIpOO~HjamOhzKDufKRmfj9-xEYPL4FYvRy780CZrojNQ0vOlYopzZCImizs-aqSw__\",\"altText\":\"\",\"originalImageWidth\":3484,\"originalImageHeight\":2232,\"isFillWidth\":false}],\"direction\":null,\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"ec82d91d806e68c07ca9e97066643ffb5a7a4a86\",\"src\":\"https://s3-alpha-sig.figma.com/img/ec82/d91d/806e68c07ca9e97066643ffb5a7a4a86?Expires=1765152000\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=Z9ptg~ICxsdA1i8ZSMygU0CSWOwdkhs-UPyDEZ-6NUpHOQUKBgNr187YPPugfHGDfKqRRI9GIiZVKNP995sIeQTiidU1gE-S65MtjfXFepDFQH0V5mBBATsARrpzKC2owtG7ap14Xhg5t4EY~M5lBAWsC-d9WuOEgLCzmdoqWPg4sOC4bYpzq7vsHPhMRLCuax0XuAy~GwztKeF6RMY2DcbuAwGn0DyN849BmVdxaX4RykN6PDoYPxBS03-U9eOSNPUi8mf5yi5LXY~sNSmh6AVBN~O94L63BnngFU24R9W2Q3ksBC1cYyuf7QPh6mYSPO2OPsI0XAyZs24nmNbhdA__\",\"altText\":\"\",\"originalImageWidth\":1206,\"originalImageHeight\":2622,\"isFillWidth\":false}],\"direction\":null,\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Styling Bottom Bar\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h3\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Next we will do the same for the bottom bar, but only for its surface. We will style buttons later.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"b36ceb23e88968564421f55912e5c21d07752a9f\",\"src\":\"https://s3-alpha-sig.figma.com/img/b36c/eb23/e88968564421f55912e5c21d07752a9f?Expires=1765152000\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=htIZiUkY2W5CLa5ozi6CWoLhm-TQLEwy2-dBSgQwEEM63mCa7uIM18riv0EIs0xWyB7tR-G3hKOMQEimNZLz5ssc3erRKCDjF3axAMvlTtJ2LXqvDecM~i8zJhKJBQU9Lm6xmR07r9MIaZVgWQF3b8o8d7J5o1YI4HfLrjX0aMfXfZHLRTdCF~uts-D8NYgGLaoStgalcYV8ySVo-ei~nMJI~ig0C3Bv4y5zLYVqdh5b6BeDPVdihibmorE3VgqPKkMQ~8zeOx4xyKfqtmbiHNoRcIg7pvRG9H8UEDmcTdw9yWef7Os~TA3-DnsVsggqBf5EhQtdXWwqECv3MNTT0A__\",\"altText\":\"\",\"originalImageWidth\":3484,\"originalImageHeight\":1936,\"isFillWidth\":false}],\"direction\":null,\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"ae891ca63247f1d39f6debe14a7563f3e34d3de2\",\"src\":\"https://s3-alpha-sig.figma.com/img/ae89/1ca6/3247f1d39f6debe14a7563f3e34d3de2?Expires=1765152000\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=S~4kTDhtkE7kL9AumSpCGl0NqmTdM43XX4npWa21vtMxkvSAhPLgLuhJnwDaam7W1v2irApRscFx~lNBuY1ztedUXwzZd1-RxL5vkcXOLdGkEZg60IxlpFpygEicLLOHQiL9Usdn2OST-epL9tzkG33NgTxncJo~hz16FqGmpEjlQU3BYgbFUjSicDib48Y4X0nKBMMknbKbUMC-d4n3uecwsDnkL1ZUECB6RNuLNdlpLJNspJrBSu~u1XkeHghctjEplnNgmk0H7iGVv-78wElFf9RNDmHd2fM3X4kmYFc4UxX5s~peaTAmnmYErOmZ57xpFK3K5bs-HdokfbDvQQ__\",\"altText\":\"\",\"originalImageWidth\":1206,\"originalImageHeight\":2622,\"isFillWidth\":false}],\"direction\":null,\"format\":\"left\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"left\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Styling Content\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h3\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Now we can style the content. We’ll replace the dummy image with the logo provided by the theme, set surface colors, text color, etc. For better representation we will also add additional text to the content.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"4002ff5dc8dd43056d544394966faf71ebb6b2c3\",\"src\":\"https://s3-alpha-sig.figma.com/img/4002/ff5d/c8dd43056d544394966faf71ebb6b2c3?Expires=1765152000\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=sPIUuUj2JeFrUdwKcP4r94RqpSkTAAGTu2Lc6oZ1rNzAMHlVCkV2mQ2wDX55xVWpTqvr5O80PYyHt7PH3XQt1R47exC-6dyL8iSOUckick93QS~Ef2F5uMDmYgLjNDydNgC8kpY0EZH7UJPHbE1kl83r~fSvhqTYHcyPpOzNobCLcfTa016w11QBBUUDkpoVTkMTJGyd2C8PWPwYnANk5ZNRILltzeDhqvIl01-TSFKATzGNXFTc5YMH7U9KMPp8lFlhfFuNc0CtSe36ZkAKzfEBWqZM4at6zceiYLYLHsXP494YaQs-A1k-aCtYL6VSWNIPvl~lv0XAxdRd3XhUvg__\",\"altText\":\"\",\"originalImageWidth\":3484,\"originalImageHeight\":2680,\"isFillWidth\":false}],\"direction\":null,\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"874ddac91238596e2e412e5dfc4ffb5a596a030d\",\"src\":\"https://s3-alpha-sig.figma.com/img/874d/dac9/1238596e2e412e5dfc4ffb5a596a030d?Expires=1765152000\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=niYEg9xdku4-jQi1zqlUmH3yROB5bD6gYdg2a6lnyORqU~VLH18IYNuqN1ghglabkL7ZKaMzVrWmWpxV03rNMzUWSJLtIovsTA25T8lR1jcFo-KexcxVsp2es6dfIOkO9jOagvLOmrdO4Tl8sV3X2QkqwVfp04CosCFWImUqVjiS5q5SzV914XRrNFZxErA8fIrcb4GSrFi7ETA6BQQZeCKukdBW0cfk~-2wbVc~1-rDRN1Oj~Z-IKtze1vE5bC9mePL1B4r1Xb2LzzI5~WtnIRC5yjJz-j7t~8lreUkXJ0aG0Spj~rvNCU420EJbZboncihVlkE5-GL20m03Fz6KQ__\",\"altText\":\"\",\"originalImageWidth\":1206,\"originalImageHeight\":2622,\"isFillWidth\":false}],\"direction\":null,\"format\":\"left\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"left\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Styling Buttons\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h3\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Finally, we can create a style for buttons. We will use SwiftUI’s \",\"type\":\"text\",\"version\":1},{\"children\":[{\"detail\":0,\"format\":16,\"mode\":\"normal\",\"style\":\"\",\"text\":\"ButtonStyle\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"link\",\"version\":1,\"rel\":\"noopener ugc nofollow\",\"target\":\"_blank\",\"title\":null,\"url\":\"https://developer.apple.com/documentation/swiftui/buttonstyle\"},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" that is produced by \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":16,\"mode\":\"normal\",\"style\":\"\",\"text\":\"SnappThemingSwiftUIHelpers\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" out of the \",\"type\":\"text\",\"version\":1},{\"children\":[{\"detail\":0,\"format\":16,\"mode\":\"normal\",\"style\":\"\",\"text\":\"SnappThemingButtonStyle\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"link\",\"version\":1,\"rel\":\"noopener ugc nofollow\",\"target\":\"_blank\",\"title\":null,\"url\":\"https://ios-theming.snappmobile.io/documentation/snapptheming/snappthemingbuttonstyle\"},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\".\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":16,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"8fb8fac25f9cbac36c85b7b10473669f54185c6c\",\"src\":\"https://s3-alpha-sig.figma.com/img/8fb8/fac2/5f9cbac36c85b7b10473669f54185c6c?Expires=1765152000\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=YrNoQlJvK5Jk6-CHtW4L1tknR7ri4arTjHwpU3KQgvgualYOb-fJgn~w5NGauDfqvCoZpbWDMbbmaKUA8Dj~1ZVcCwB9M42QODzdeOv6iwYZcSF~PzdL9ScfG9XZmofPrMu4SWFkFqzZB5TpZ46ecHrg8goAmCnAVOFis02keRGtZHTvpt-2FPlNfp5ThiZ3B6hJ-hb2kI~KmeDkfthpnrGeG223~GsxrtW6urWClwiqeNN7qOYktUD8xbCQHJls62D7U18h6tsEZw9E7YcbHkjMd~y5NYS1XO~wxv~MFSnDqmWzKXQwV9SG-TeXHinWiv0l8yC97SJsfH3SHjN51Q__\",\"altText\":\"\",\"originalImageWidth\":3484,\"originalImageHeight\":2456,\"isFillWidth\":false}],\"direction\":null,\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"a81fc8ea6b100e120fe07ea47d9726d3c41e4093\",\"src\":\"https://s3-alpha-sig.figma.com/img/a81f/c8ea/6b100e120fe07ea47d9726d3c41e4093?Expires=1765152000\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=CLKFSSI45UxbmODVhdgbeqyb39bwfABqZkfiu9MDuGN1ChOMbMINTGm63XJy4TT7C4supCd5WmocR39hvCsV-GRMN1CoaW7HOnd5IOr-O~VySP8wK92rscpu7g~QVcfJG-d-D2wU6jsAOn6-jA0KRCLGOKVwsdU90fMXEYdQsWzYm7R1U6ciwMuKFgWGC-nZcqEJNCOvpsHeaaG580J4IPLcX7OvVBUM826rlbiyurqd76SbTS1QHjrKBXwPTXDibpX9BOPT25nu8qyWI6dstwRqI6C7~YPovSuef4T3w3PsKtWjEYb9T2vgXfHWXjbaL2LLNzZD07z2svhvWKohtw__\",\"altText\":\"\",\"originalImageWidth\":1206,\"originalImageHeight\":2622,\"isFillWidth\":false}],\"direction\":null,\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Conclusion\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h2\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"In this article, we explored the SnappTheming framework and its capabilities for integrating dynamic design themes into iOS applications. We began by setting up a project in Xcode and adding the SnappTheming package dependency. \",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Then, we delved into the core concepts of theming with SnappTheming, including the use of JSON declarations to define colors, metrics, shapes, resources, and typographies. We demonstrated the creation of a complete theme and showed how to apply it to style various UI components, such as buttons, top bars, and content areas. By leveraging SnappTheming, developers can streamline the process of theming, ensuring consistency and flexibility in their applications user interfaces. We encourage you to explore the framework further and contribute to its development.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"d0911a6d18958a8e71ad9b863ee2160e1b4ece94\",\"src\":\"https://s3-alpha-sig.figma.com/img/d091/1a6d/18958a8e71ad9b863ee2160e1b4ece94?Expires=1765152000\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=VHZwEa~ACpBiVI40XEOlTULigbrV4lWLFj~A9rNsTN1CmpuOYXxT9Ztue5dceZZDyrn95VBT2FHLUnMx45XhLmg4WICVkUhL5Pokbb--K5oEwbklRQqEpmIwmYY~191nBAQSljcrK9BCjPumCvaDO4598mxXGeJu0PyZYE~Txl75RT0EzL~txwIgBoRUvgZeOcV90IYi~bh0eYWIQlwBckW~OpPJstNvpuivWTsvD2alrglOYVH48Q9WYD0oXj-069j72gwAd0OnroVE68rb9z44y~QSfJHPO161zXGNPYIRrEQpnsWnOf20R-I5Pp9xhQsRIoRZx-byPmZqzD0fbA__\",\"altText\":\"\",\"originalImageWidth\":1202,\"originalImageHeight\":2608,\"isFillWidth\":false}],\"direction\":null,\"format\":\"left\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Additional Resources\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h2\"},{\"children\":[{\"children\":[{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"SnappTheming Official Website\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"link\",\"version\":1,\"rel\":\"noopener ugc nofollow\",\"target\":\"_blank\",\"title\":null,\"url\":\"https://ios-theming.snappmobile.io/\"}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":1},{\"children\":[{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"SnappTheming GitHub Repository\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"link\",\"version\":1,\"rel\":\"noopener ugc nofollow\",\"target\":\"_blank\",\"title\":null,\"url\":\"https://github.com/Snapp-Mobile/SnappTheming\"}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":2},{\"children\":[{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"SnappTheming Documentation\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"link\",\"version\":1,\"rel\":\"noopener ugc nofollow\",\"target\":\"_blank\",\"title\":null,\"url\":\"https://ios-theming.snappmobile.io/documentation/snapptheming\"}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":3},{\"children\":[{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"SnappTheming Tutorials\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"link\",\"version\":1,\"rel\":\"noopener ugc nofollow\",\"target\":\"_blank\",\"title\":null,\"url\":\"https://ios-theming.snappmobile.io/tutorials/meetsnapptheming\"}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":4}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"list\",\"version\":1,\"listType\":\"bullet\",\"start\":1,\"tag\":\"ul\"}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"root\",\"version\":1}}","itemId":"d38bc66e-898e-469d-a28e-7e25efcd5e82","fieldSchemaId":"3084d9ba-ab55-4e5a-931b-b9db3d09105f"}]},"9048f7a9-740a-4bde-a9e3-e779de37ca73":{"id":"9048f7a9-740a-4bde-a9e3-e779de37ca73","index":"(","collectionId":"d4a5b68c-8afd-4bbe-a7ac-e9a8422fedde","fields":[{"id":"352cb700-87d0-41ca-b8b0-054680ce024f","value":"2021-09-21","itemId":"9048f7a9-740a-4bde-a9e3-e779de37ca73","fieldSchemaId":"b7712ee6-f9fd-4781-8c5c-e7e10ce8f81e"},{"id":"efde4d85-dfa6-4826-b5eb-af9c2ae86da0","value":"{\"root\":{\"children\":[{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Co-Founder + Consultant of Snapp Technology\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Co-Founder + CEO of Snapp Automotive\",\"type\":\"text\",\"version\":1},{\"type\":\"linebreak\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"GDG (Google Developer Group) Android Munich organizer\",\"type\":\"text\",\"version\":1},{\"type\":\"linebreak\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Author of: Smashing Android UI\",\"type\":\"text\",\"version\":1},{\"type\":\"linebreak\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Trail runner\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"root\",\"version\":1}}","itemId":"9048f7a9-740a-4bde-a9e3-e779de37ca73","fieldSchemaId":"0b77f83b-c31a-4889-b9b3-9a6d2e41fc86"},{"id":"c3afc6fc-81ef-4d28-9236-bccbe85049a1","value":"bringing-flexible-rapid-development-to-automotive-infotainment-systems","itemId":"9048f7a9-740a-4bde-a9e3-e779de37ca73","fieldSchemaId":"402ba26f-8f6d-4f5f-bf20-62e6549f4ad4"},{"id":"3e4d72f9-ab5e-4761-a1ec-83a43154130a","value":"Bringing flexible, rapid development to automotive infotainment systems","itemId":"9048f7a9-740a-4bde-a9e3-e779de37ca73","fieldSchemaId":"f2ba59b9-49cc-4ec6-9416-bda99d4c8383"},{"id":"9468a1f3-9459-4019-bcaa-182f769186de","value":"{\"image\":\"237c98eff9de13be4b9206cad01791aabe31b299\",\"imageThumbnail\":\"f0a1c23a9056c29f8920ae2cdcdd33bbace6c7f9\",\"originalImageHeight\":540,\"originalImageWidth\":960,\"altText\":\"\",\"fileName\":\"Auto_1.png\"}","itemId":"9048f7a9-740a-4bde-a9e3-e779de37ca73","fieldSchemaId":"1f58afa6-2748-4188-b4a4-f1e54e37eca9"},{"id":"da0d00b9-1678-4001-98b1-29daffd8ae9d","value":"Juhani Lehtimäki","itemId":"9048f7a9-740a-4bde-a9e3-e779de37ca73","fieldSchemaId":"df1c88d1-4bd8-4ecd-9059-463b9589de92"},{"id":"6d156b5d-50b3-4e8b-9853-3c58092ba6b3","value":"Co-Founder of Snapp Technology","itemId":"9048f7a9-740a-4bde-a9e3-e779de37ca73","fieldSchemaId":"0a981f8a-7dbb-440d-a940-25d9060c9b11"},{"id":"99b08f47-c58f-4bd2-9a8a-8f5b092e4801","value":"{\"root\":{\"children\":[{\"children\":[{\"detail\":0,\"format\":2,\"mode\":\"normal\",\"style\":\"\",\"text\":\"How proven development processes from mobile development can be utilised in the new automotive domain.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":2,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":2,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"We believe that good software can only be created by iterating quickly, freely testing new ideas, and validating guesses. This comes from the decades of experience our senior management has with software development projects, some of which were successful, some not so much.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Like it or not, we usually guess incorrectly when we try to predict what users will do or would want to do. A waterfall-type approach to software development only validates these guesses once the software is ready, but if some of your fundamental guesses were wrong, you might have a product dead on arrival, which will be costly. In the mobile app industry, we have worked hard to remove all friction from \",\"type\":\"text\",\"version\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"the design and development interaction\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"link\",\"version\":1,\"rel\":\"noopener\",\"target\":null,\"title\":null,\"url\":\"https://medium.com/snapp-mobile/how-to-bring-a-product-to-reality-in-a-few-days-design-dev-cooperation-and-fast-android-850ca6f2311f\"},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" and to bring validation, using an \",\"type\":\"text\",\"version\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"evidence-based process\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"link\",\"version\":1,\"rel\":\"noopener\",\"target\":null,\"title\":null,\"url\":\"https://medium.com/we-are-systematic/why-are-systematic-8a5ed95869e1\"},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\", into product development. We avoid decisions solely being made by the highest-paid person and drive to implement systems that solve real-world problems in a functional and delightful way.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Rapid iterations, in the real context, in car\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h2\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"It’s all well and good to have newer versions quickly accessible by the developers but to get the real benefit of rapid iterations the team must be able to test and validate their ideas in the real use context, which for automotive systems is in the car.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"This is why we put a lot of effort into enabling rapid prototyping and iterations in cars, using approximations of real hardware; Tablets. \",\"type\":\"text\",\"version\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Read more on how our system runs on a Samsung tablet here\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"link\",\"version\":1,\"rel\":\"noopener\",\"target\":null,\"title\":null,\"url\":\"https://medium.com/snapp-automotive/android-automotive-os-on-a-tablet-f805beb20f96\"},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\".\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"3c4837b3e3fcf0a63e1ba126ae946d95d03eec47\",\"src\":\"https://s3-alpha-sig.figma.com/img/3c48/37b3/e3fcf0a63e1ba126ae946d95d03eec47?Expires=1768780800\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=FHDMhO3aakZf-pu10UD2bcys6mahOSgHCqpk4I97nWAfUy0~7KA8hPrLHaY2KIZoOHkgBRDzJyQemZiROs4-CBD6rg-kAZVfjfdBkQb0ouSUmp-UlX1MRuEOgndsvGLJSzK-uQKni3zHthvK1eNlgMoofEsr~7h3HuTpyw~42HuoPHIGiQXBma~b96Osk5i3JhzqA3L1W7-J-9PxOvBJavQ6yCYRWAYZi8tnGfQdZbfsKj9wO-7TQIMhWwzzbRUANEw7wASRvvtRG7ukoZ1Ln-orBopI2BNjbYj40djHD39p5OVc5TgFB6Rt7jpujp0k1Es1wH3jdRBs7y4GTp5wEg__\",\"altText\":\"\",\"originalImageWidth\":1400,\"originalImageHeight\":1050,\"isFillWidth\":false}],\"direction\":null,\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Going remote\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h2\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Hiring talent is increasingly difficult. If you try to build an on-site team it further increases the number of challenges. Assuming that the best people to work in your project happen to live within 30 km of your office, or are willing to drop their life and move to a new city, just isn’t realistic. Car software development needs to support effective remote working, just as mobile app development does today.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"The ability to run in-development software, on realistic hardware, in-situ, is a big deal; Suddenly developers don’t need permanent access to rack-mounted car hardware all the time, and software can be developed and tested in the field in parallel with prototype and EVT hardware development. When combined with the use of emulators the team can work remotely, scale easily if needed, and only a small team needs to work “hands-on” with the real hardware. The use of rapid development CI/CD and healthy testing practices help to avoid a “big bang” integration which often leads to many unforeseen problems.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"We have already applied these practices to automotive development. Currently, on one project, we have engineers and designers working across four different countries. This enabled us to demonstrate an early version of some of our work at the IAA Mobility conference in Munich a fortnight ago without the need for any of the team to physically meet.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"With remote-friendly processes, we can engage the best available people for a particular project rather than being limited to those who are, or could be, locally available to us.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Distributing app updates\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h2\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Most of the work in creating an Android Automotive OS infotainment system involves customising the core apps (Settings, media players, navigation, and home screen, etc.). All the traditional Android app development tools are available to our automotive developers which allows them to maintain development velocity and quality practices learned from years of mobile app development. These tools enable the team to release multiple new app versions daily, and these versions quickly reach other developers, designers, and product managers to see, test, validate and try.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"To facilitate this we built a “snApp Store”; a lightweight app update distribution tool that allows updates to be pushed to the devices and systems used during the development phase.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"292206b8631d5baf6cfbd18d3f0c6634ce3c8da9\",\"src\":\"https://s3-alpha-sig.figma.com/img/2922/06b8/631d5baf6cfbd18d3f0c6634ce3c8da9?Expires=1768780800\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=dy1nXwt4lzwCpgiUQENR2vz8Pa3RTf0yThbkS9wsfez9xpEUQTW6B3LPq36f4qworpqZwVikHYs-tOYpDNtEdcAHS0d9peFMAI8boJNs9o5xEjT1el7PDDT~~O3y1R5LeG4j17TzmexACb6I2lM3vYGnEfQx5S37oYXeCZpuQSM3p82jmwwJrDkeQro0jJPP8hslvZ7fYUUQu5HaF6mNbIvjKUDEaCd6hYxpn-PUuH4UAJLJHXCWU6PRiRZIA99mD3TjoZNwxRgsCe-0t0k3f1mTi4hv-zPrOSy06Ik5ptgS-PpglCvbgRWqoJJVS0DGDK7CBpG8LTJKOWK418ARFw__\",\"altText\":\"\",\"originalImageWidth\":2560,\"originalImageHeight\":1600,\"isFillWidth\":false}],\"direction\":null,\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Distributing platform updates\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h2\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Changes on the OS level, such as those to the system UI, shared components, or configuration, affect all apps running on the system. It is important that these changes propagate to the whole team quickly and without blocking their work.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Emulator\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h2\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"We utilise the built-in update-site emulator image distribution system of Android Studio. For our AAOS emulator images, we use the same emulator refresh and update process that mobile developers are already familiar with. This vastly reduces onboarding times and allows us to have developers tackling real problems in under a day when they start on automotive projects.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"2fa4335f69e75b026d66c06b60486507db0868db\",\"src\":\"https://s3-alpha-sig.figma.com/img/2fa4/335f/69e75b026d66c06b60486507db0868db?Expires=1768780800\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=kJMjbEGYaaFSTmHxh1AM2pYHLX8vZdDD7pubG8hJIBZT1g1CNez9zkxUteLKTno3HY2mwmPkQ8B-Bd9Bt0lSzcmKzZ63LWNfSIMYsku0kU9g0z8ueBsATzYkwPrpZRhVSuFraftpXEhj4z4eFZBr7lC9zW5JEcIGaXKkfBA1~iI~kaQssSPR~DsZItDhYQ-VGCpV7dJDd6VJNnQsj2BSLHDgfqb5Az0OCa95ZJcpHVXTg0iNZm~XWD15mZAigc9CbD5GlAaVoepjcn22ms9Cdxm4QRcHW0ETTE-o2EMDrHJE08mxIp40SrHvPIDW~HVQ0gLi~mv0oQOs4oQJBSaADQ__\",\"altText\":\"\",\"originalImageWidth\":2453,\"originalImageHeight\":708,\"isFillWidth\":false}],\"direction\":null,\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"475fcce63d5ef24d68cb11c09494b390558c89d2\",\"src\":\"https://s3-alpha-sig.figma.com/img/475f/cce6/3d5ef24d68cb11c09494b390558c89d2?Expires=1768780800\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=S2WzTGtZNNc5fK5zRRzy7bbwRrURWIyBD9Koxks7nREBzLGiwqGqbh155scUyTO4l73W2DkImEnUmIawn21EyghrO8qWBTaBc2Tn9ZkSzLKhzpNMyIkY13sOchVguDC7ZNmWhzgI9Z6SzdD18WEZTKmqNjk0CQUD8G6hvn0t3wJLqCyp0vO0YXU0s2PkIXfEYYYjKcWKqEsgKzTfVa4B7Jw2JFYK8ZS0Nev43yjTjgkApnFbgtN42RKdlOP1jHcG9bheoddmJoDBviBm4dR08QraPgfe5p3I2w8X0uUYU-CFUePvxxyE4a0wSvSlRLQUoDgsadGrHysshPzp~HMehw__\",\"altText\":\"\",\"originalImageWidth\":3840,\"originalImageHeight\":1600,\"isFillWidth\":false}],\"direction\":null,\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Physical devices\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h2\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"We decided early in the project to make use of the wide device support offered by \",\"type\":\"text\",\"version\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"the Lineage project\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"link\",\"version\":1,\"rel\":\"noopener ugc nofollow\",\"target\":\"_blank\",\"title\":null,\"url\":\"https://lineageos.org/\"},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\". Their Android distribution includes a firmware updater responsible for updating the entire OS in one go. We use a modified version of it to get updates from our servers and install them on the physical devices we use.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"3f3771a7348618c0b6ed2f185f77434f517a5c2f\",\"src\":\"https://s3-alpha-sig.figma.com/img/3f37/71a7/348618c0b6ed2f185f77434f517a5c2f?Expires=1768780800\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=YuZIAsBKrczJzufKLo2KPTM-7Qfz~S0qlF8B9DOLn02YN7maurhAHOYXh5RU5khSGzTkS8qNTLnjDQduOjSsunIAFG3G7cjvIGlYeLQzjlMOstwjbSsFKgzTOesDqciYwLfo944E28hotbwkCC0pR0s4AvRADt10mU9bFvxWzrmX3bAhTgJZQRto9hVK-DwjRcaE61pcu9mOwExGVQSrOmLULnP0EZZCnfiq4E4X0q7PwIDfo7UK1lhbklyFMkUZc~FJZPCxGShw7-jgXvflQdaisHPzf1qwamn3CI~aN9rLXSDUGT1YVo6T5mQgPe8IcH7-mbePmoo6OxICFvMo0A__\",\"altText\":\"\",\"originalImageWidth\":2560,\"originalImageHeight\":1600,\"isFillWidth\":false}],\"direction\":null,\"format\":\"left\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Having a user-friendly firmware update system allows us to distribute changes that can only be made at the OS level to everyone with a device. This means that designers, developers, and stakeholders can all update their own devices without the need to return them to an IT or engineering department, which saves on distribution delays and administrative costs.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"The firmware updates can operate over cellular or WiFi networks, which also allows us to understand the experience a user will go through when they have to update their head-unit so we can adapt our designs to make this a smooth and seamless experience.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"root\",\"version\":1}}","itemId":"9048f7a9-740a-4bde-a9e3-e779de37ca73","fieldSchemaId":"3084d9ba-ab55-4e5a-931b-b9db3d09105f"}]},"eb24ef1b-0fd4-4f84-b203-869d6e19431e":{"id":"eb24ef1b-0fd4-4f84-b203-869d6e19431e","index":"!YO","collectionId":"d4a5b68c-8afd-4bbe-a7ac-e9a8422fedde","fields":[{"id":"c086d88a-150b-491f-8e19-abcebdd5b192","value":"{\"root\":{\"children\":[{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Oleksii is an iOS alchemist at Snapp Mobile 📱✨, turning concepts into beautifully crafted Swift code and smooth, user-friendly interfaces. He’s passionate about shaping mobile experiences that feel effortless and refined. A firm believer in the power of simplicity, he focuses on writing clear, thoughtful code that brings ideas to life without unnecessary complexity.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"root\",\"version\":1}}","itemId":"eb24ef1b-0fd4-4f84-b203-869d6e19431e","fieldSchemaId":"0b77f83b-c31a-4889-b9b3-9a6d2e41fc86"},{"id":"270fbb55-321f-4bc7-8fe6-256a69b26e2f","value":"ship-it-right-a-swift-package-quality-checklist-part-3-of-3","itemId":"eb24ef1b-0fd4-4f84-b203-869d6e19431e","fieldSchemaId":"402ba26f-8f6d-4f5f-bf20-62e6549f4ad4"},{"id":"d8a21c29-9f7f-4e13-beb5-36abfd6fbd8f","value":"Ship It Right: A Swift Package Quality Checklist. Part 3 of 3.","itemId":"eb24ef1b-0fd4-4f84-b203-869d6e19431e","fieldSchemaId":"f2ba59b9-49cc-4ec6-9416-bda99d4c8383"},{"id":"4641653b-5149-444c-afc3-e1f89627afea","value":"2026-01-06","itemId":"eb24ef1b-0fd4-4f84-b203-869d6e19431e","fieldSchemaId":"b7712ee6-f9fd-4781-8c5c-e7e10ce8f81e"},{"id":"6e0f96b1-cf5f-439b-b249-213ecee39c57","value":"Oleksii Kolomiiets","itemId":"eb24ef1b-0fd4-4f84-b203-869d6e19431e","fieldSchemaId":"df1c88d1-4bd8-4ecd-9059-463b9589de92"},{"id":"7d7b16d1-86bd-41bf-b520-d5339d7ade93","value":"iOS Developer","itemId":"eb24ef1b-0fd4-4f84-b203-869d6e19431e","fieldSchemaId":"0a981f8a-7dbb-440d-a940-25d9060c9b11"},{"id":"732cddd2-12d0-418a-9a6a-df453f1062ef","value":"{\"root\":{\"children\":[{\"children\":[{\"detail\":0,\"format\":2,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Parts 1 \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"and\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":2,\"mode\":\"normal\",\"style\":\"\",\"text\":\" 2\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" established everything you need for a solid, maintainable Swift package: documentation, automated quality checks, contributor-friendly processes, and professional releases. Your package is technically excellent and easy to contribute to.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":2,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"But here’s the problem: good code doesn’t promote itself.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"I’ve experienced this with every project. I spent weeks building \",\"type\":\"text\",\"version\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"SwiftFormatLintPlugin\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"link\",\"version\":1,\"rel\":\"noopener ugc nofollow\",\"target\":\"_blank\",\"title\":null,\"url\":\"https://github.com/Snapp-Mobile/SwiftFormatLintPlugin\"},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\", writing documentation, setting up CI, creating examples. Then I pushed it to GitHub and… waited. \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":2,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Nothing happened\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\". No stars, no issues, no discussions.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":3,\"mode\":\"normal\",\"style\":\"\",\"text\":\"This series is\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":2,\"mode\":\"normal\",\"style\":\"\",\"text\":\"for Swift developers turning internal packages into polished public repositories.\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" \",\"type\":\"text\",\"version\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Parts 1\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"link\",\"version\":1,\"rel\":\"noopener\",\"target\":null,\"title\":null,\"url\":\"https://medium.com/@oleksii_24924/34d58d16f581\"},{\"detail\":0,\"format\":2,\"mode\":\"normal\",\"style\":\"\",\"text\":\"–\",\"type\":\"text\",\"version\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"2\",\"type\":\"text\",\"version\":1}],\"direction\":null,\"format\":\"\",\"indent\":0,\"type\":\"link\",\"version\":1,\"rel\":\"noopener\",\"target\":null,\"title\":null,\"url\":\"https://medium.com/@oleksii_24924/b1a0ed970e4e\"},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":2,\"mode\":\"normal\",\"style\":\"\",\"text\":\"covered documentation, quality, and community. This final part focuses on growth and visibility.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"The same code, after I actually shared it on social media, started getting traction. Developers discovered it. The difference wasn’t the code — it was \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":2,\"mode\":\"normal\",\"style\":\"\",\"text\":\"visibility\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\".\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"You can build the best Swift framework in the world, but if developers don’t know about it, the impact is \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":2,\"mode\":\"normal\",\"style\":\"\",\"text\":\"zero\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\".\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Tutorials: Interactive Learning with DocC\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h3\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"We have DocC to create tutorials — quick-starts or how-tos with code and screenshots in a playful way. Tutorials are interactive, step-by-step guides that walk users through actual implementation. They’re more engaging than articles and more structured than example code.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"I saw the impact tutorials can have when we added them to \",\"type\":\"text\",\"version\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"SnappTheming\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"link\",\"version\":1,\"rel\":\"noopener ugc nofollow\",\"target\":\"_blank\",\"title\":null,\"url\":\"https://ios-theming.snappmobile.io/tutorials/meetsnapptheming/\"},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\". Instead of users asking “how do I get started?” in issues, they will work through the tutorial and show up with specific, advanced questions. The tutorial does the heavy lifting of onboarding.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"7ff3e24db7d96a138a922cf68a683fde49c0918b\",\"src\":\"https://s3-alpha-sig.figma.com/img/7ff3/e24d/b7d96a138a922cf68a683fde49c0918b?Expires=1768780800\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=LW5g4tU-GuOxKmkfQTx5WR~00GJsSlHGgjs7GTaZuqZzlvvyQbi4G8~o2Vd~9RdXiVDeq1tAuaXj7hsJYwMVMZM3sJZHENhq87X7CB3TAyMJFs3boVIY4lBjK0FXWmlDiQSK1qpR0DIA4qE5sTq3nfhAwiDJn05SPO90EI0GeEMEUPdM8MndiJi1cZkHkD~wJ7tIDkFd6veFWvLO~5H1jze~Q8spu1YNB5HC9Wdtw4znl1Zk57qKrdqIyF2UfNl8Lo536INsOzHojMlHEwtqWnj3wVI5WJ8SdDCzvLEu0Y5a8BGULbj5LCr5fMp7EETkRtiY3gCTMmtnOA0FMm5NcA__\",\"altText\":\"\",\"originalImageWidth\":2026,\"originalImageHeight\":1096,\"isFillWidth\":false}],\"direction\":null,\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Tutorials vs Articles\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":1,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":1,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Both are valuable, but they serve different purposes:\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":2,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Tutorials\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" — “Let’s build something together.” Interactive, step-by-step, with specific outcomes. Best for getting started or learning a workflow.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":2,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":2,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Articles\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" — “Here’s how this works.” Explanatory, reference-oriented. Best for understanding concepts or exploring features.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":2,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Use tutorials for getting started guides, common integration patterns, and building complete examples. Use articles for API reference, architecture explanations, and configuration guides.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"When to Create Tutorials\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":1,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":1,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Create tutorials for \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":2,\"mode\":\"normal\",\"style\":\"\",\"text\":\"getting started\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" (every framework should have one), \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":2,\"mode\":\"normal\",\"style\":\"\",\"text\":\"common patterns\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" (frequent integration scenarios), and \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":2,\"mode\":\"normal\",\"style\":\"\",\"text\":\"complex features\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" (anything taking more than a few lines to set up).\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Don’t create tutorials for every single API method (that’s what articles are for), edge cases, or internal implementation details.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"The Playful Advantage\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":1,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":1,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Tutorials are playful in a way that API documentation isn’t. Users actively build something, see results at each step, and feel progress. This builds confidence and engagement.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"I’ve seen users work through tutorials and then immediately integrate the framework into their projects. The tutorial gave them enough confidence to commit. That’s the power of interactive learning.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"If you want users to quickly grasp your framework and start using it confidently, tutorials are one of the highest-value investments you can make.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Promotion: Good Code Doesn’t Promote Itself\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h3\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"You built something valuable. Now make sure the people who need it can find it. This isn’t about being pushy or spammy. It’s about respectfully connecting your work with developers who have the problems your tool solves.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"The Problem: The Silent Launch\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":1,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":1,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"I made this mistake with my first few open-source tools. I’d build something useful, write great documentation, push to GitHub, and wait for people to discover it. They didn’t.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"5cd9bdbd4c09543300720ebb7ed6b97c57239187\",\"src\":\"https://s3-alpha-sig.figma.com/img/5cd9/bdbd/4c09543300720ebb7ed6b97c57239187?Expires=1768780800\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=d9I-GWOfSBAVmmBFZlLN42czkUh7quLSAjv~FyqteEh7T~~JiCOFryuYssmj1TuTAt0BkMTywx~FfyeL63q~QQf4icpT6NBZHhlCYOAIwpEwZyJBmElWAo4K0PN4nqsrGSGpK-r7SC56XzyF8pLM3CdCV0lGSGUE2ee-1OvgEeSl0a7dCEfQeMXZQS6E-o0A83Prrq7tnnsCSp~UpTly4A31bOb5LAHFKJ4nxMp6o3lifvQaW1Ex5edu3V3uelz711OPwhksqI06NPoLeOLp4op3Hotd2ybDQy0qHFghv~M1wFFJP5ruNqskA3HxgUM7avQOOxBQzVED71wsYAL76Q__\",\"altText\":\"\",\"originalImageWidth\":1400,\"originalImageHeight\":933,\"isFillWidth\":false}],\"direction\":null,\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"GitHub has millions of repositories. Nobody randomly discovers your package through divine intervention. You have to tell people it exists.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"The tools that succeeded were the ones I actually promoted: posting to Swift forums, sharing on social media, submitting to newsletters. Same code quality, different outcomes — all because of visibility.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Where to Share\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":1,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Social media works best when you meet developers where they already hang out. The Swift community is active and engaged on \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Bluesky\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" and \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Mastodon\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\", making both great places to share updates and start conversations. \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"LinkedIn\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" has also become surprisingly effective lately, especially for reaching professionals who care about real-world usage and product decisions.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Share \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":2,\"mode\":\"normal\",\"style\":\"\",\"text\":\"launch announcements\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" with clear screenshots or short demo GIFs. Post about \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":2,\"mode\":\"normal\",\"style\":\"\",\"text\":\"major releases\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\", highlight \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":2,\"mode\":\"normal\",\"style\":\"\",\"text\":\"interesting features\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\", and show practical \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":2,\"mode\":\"normal\",\"style\":\"\",\"text\":\"usage examples\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\". Focus on being informative rather than promotional — developers value clarity and substance. Use relevant hashtags to help the right people find your posts:\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"2b99aeaa99931e6d369b49c762654dba70d778f3\",\"src\":\"https://s3-alpha-sig.figma.com/img/2b99/aeaa/99931e6d369b49c762654dba70d778f3?Expires=1768780800\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=egFFhNbYTw1WeFK8Ry6uKA2Sb3ikg9UZKcBiKmQp~QxC8DOlINXWv~-og9UKHtHlLUzEB2GJIVqQvKQ8t8wfYLCYGywjsBdMTzWJcx3MCSQeqIfmZG~gNOXC~H5QvnabkrrLkPMz68itV-xqA~4lNnLQjVbwJ-iPeE4trZIf8Iv77Lcq0uFJGhl8OVriOU-UbRIh~wsUJgRuBi5GuOqQyVAO~s8VoPEiM1zAphJ9fKmLzHRcCu5zn3FcaPT8~dbFkG91Jkddrju7U32gjwy9C3SxnSrDe8kQ4uAAcUJ6KPC267zEvEvZkjiDrK34zvJg0V2rEdUcoFikQAQhcs8YxA__\",\"altText\":\"\",\"originalImageWidth\":3484,\"originalImageHeight\":892,\"isFillWidth\":false}],\"direction\":null,\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Newsletters\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":1,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":1,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"There are a bunch of good newsletters. Submit your project through their submission form. Getting featured exposes your tool to thousands of iOS developers. If there is no form, do some research and find the newsletter’s social accounts to send a direct message.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Submit when you launch version 1.0, add significant new features, or have an interesting technical write-up about building it.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Reddit\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":1,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":1,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Relevant subreddits: r/swift and r/iOSProgramming. Reddit appreciates substance. Don’t just drop a link — explain what problem you’re solving and why you built it. Engage with comments.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Technical Blogs\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":1,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":1,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Write about building your tool: technical challenges you solved, design decisions you made, lessons learned. Post on Dev.to, Medium, your \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"personal blog\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\", or company engineering blog. These articles serve dual purposes: they \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":2,\"mode\":\"normal\",\"style\":\"\",\"text\":\"promote\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" your tool and provide \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":2,\"mode\":\"normal\",\"style\":\"\",\"text\":\"valuable\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":2,\"mode\":\"normal\",\"style\":\"\",\"text\":\"content\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" to the community.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"How to Announce: Simple, Clear, Honest\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":1,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":1,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"When announcing:\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Lead with the problem — What does this solve?\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Show, don’t just tell — Include a code example, screenshot, or demo\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":2},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Link to documentation — Make it trivial to learn more\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":3}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"list\",\"version\":1,\"listType\":\"bullet\",\"start\":1,\"tag\":\"ul\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Example announcement of \",\"type\":\"text\",\"version\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"CounterPicker\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"link\",\"version\":1,\"rel\":\"noopener ugc nofollow\",\"target\":\"_blank\",\"title\":null,\"url\":\"https://github.com/oleksiikolomiietssnapp/CounterPicker\"},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\":\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"859fe8eabe4323eefd91c2abdb6e93ee6a9c5f78\",\"src\":\"https://s3-alpha-sig.figma.com/img/859f/e8ea/be4323eefd91c2abdb6e93ee6a9c5f78?Expires=1768780800\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=cND8zlVgjQSkjG6yhXC9HZOCAmANdELNeOlYIXMRhFUhfEsFZcSbXUVJVMiN2Ap4Xw1y0o~5N76~~7BIPRDkzcM7yO66VOEitAiJrs2gipdE3pEZjT3R2W6JIdOPVPV8vIivK2N5JfwWB-G83wO1GNvboWkrfxZkLcAuVqFIjAp1Jx161n3-EwJUxl3KuWOT5dOj7yeyQC28jwmAUUBGc~iOsIBscvcH1t2WEtt-DH0t54v51lVDKMt~kpF0WeJwzazS~izvsMuH9TOdB1KhccHpOU7Xb7LC5CZ-ZWrouuXid93noIqzvEtfErKNvFGzrVXWt-WUyoUUG44DXoMs7A__\",\"altText\":\"\",\"originalImageWidth\":1418,\"originalImageHeight\":1068,\"isFillWidth\":false}],\"direction\":null,\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Ongoing Engagement\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":1,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":1,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Promotion isn’t just the launch. Stay engaged: \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":2,\"mode\":\"normal\",\"style\":\"\",\"text\":\"answer questions\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" promptly, \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":2,\"mode\":\"normal\",\"style\":\"\",\"text\":\"share updates\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" when you ship significant releases, \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":2,\"mode\":\"normal\",\"style\":\"\",\"text\":\"highlight\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" community \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":2,\"mode\":\"normal\",\"style\":\"\",\"text\":\"contributions\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" publicly, and \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":2,\"mode\":\"normal\",\"style\":\"\",\"text\":\"write follow-up\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" content.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"What Not to Do\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":1,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":1,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Don’t\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":2,\"mode\":\"normal\",\"style\":\"\",\"text\":\" spam\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" (posting to 10 subreddits is spam), don’t\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":2,\"mode\":\"normal\",\"style\":\"\",\"text\":\" beg\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":2,\"mode\":\"normal\",\"style\":\"\",\"text\":\"for stars\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\", don’t \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":2,\"mode\":\"normal\",\"style\":\"\",\"text\":\"over-promote \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"every minor commit, don’t be defensive about critical feedback, and don’t make promises you can’t keep.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"You Built Something Valuable — Share It\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"You invested time building a tool that solves a real problem. The final step is making sure the developers who need it know it exists.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Promotion isn’t self-aggrandizement. It’s connecting your solution with people who have the problem it solves. Share your work. The community wants to know about it.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Swift Package Index: Free Documentation Hosting\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h3\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"There’s a free way to have documentation hosted at \",\"type\":\"text\",\"version\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Swift Package Index\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"link\",\"version\":1,\"rel\":\"noopener ugc nofollow\",\"target\":\"_blank\",\"title\":null,\"url\":\"https://swiftpackageindex.com/\"},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\". You need to register your framework at their GitHub and meet their expectations with an \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":16,\"mode\":\"normal\",\"style\":\"\",\"text\":\"spi.yml\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" file. This gets you professional documentation hosting without paying for servers.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"I host documentation for my packages on Swift Package Index. It’s free, reliable, and integrates perfectly with the Swift ecosystem.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"The Swift Package Index team reviews submissions (usually within a day) and merges if your package meets basic requirements: valid Swift package with \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":16,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Package.swift\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\", public repository, and semantic versioning tags.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"18a8c893c18a55b0afde67eeff06d283ff35d363\",\"src\":\"https://s3-alpha-sig.figma.com/img/18a8/c893/c18a55b0afde67eeff06d283ff35d363?Expires=1768780800\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=UolXqr-FQbWjucc0SFNo8zgPUjUsrLzS25HaDuIcPL~PL1~Pjzsrejg~sGYy5rpuX5kiM3j6oLGzoFee9AweEyAEICCN27264qU8KkGmc4vj6-1OsPG2mpyneXVk1zaBeutAUL8ESGEx8xGwenHOkQ7n3Yi6mBAkNROE2DW-8HqGQC-SkopRvIVAHuKKlteitCKYtu9nCAVUDd29A~k7bBk-5ghk-fFRv-mpnuNQ9eaK3TJ-v9yA5KmiUq8kWHdn26p37NHvcoSStVyJdCQsHChUmpUb6-aDY5FTIUAwTk6MYrNJRJWML4Nsm0BYPdr7OfthV5QP9O5auQajM7jhOA__\",\"altText\":\"\",\"originalImageWidth\":3484,\"originalImageHeight\":1116,\"isFillWidth\":false}],\"direction\":null,\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"This tells Swift Package Index which targets to build documentation for, what platform to build on, and what Swift version to use.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Documentation updates automatically when you push new release tags.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Documentation URL\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":1,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":1,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"635c4f78c5a78bc6e17ec8b6b1a94b73783da41b\",\"src\":\"https://s3-alpha-sig.figma.com/img/635c/4f78/c5a78bc6e17ec8b6b1a94b73783da41b?Expires=1768780800\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=P1nWYSPFbtxSEvxEsDtSAO~TKYZEnZQqbqcKhYw4VGvqJVfsNh28PctCtlIY9pojCZSU~JBNKhTaPCplbcf76Bh27S9eu4MMjFtkgx5Xo0UCmsfOLxHe64VZ52cVtmMyuCTswWswHCaqA2SmeezOaHZXJqUGm9r3Uwo-nfFZzJUe-u3ZjV7xelm4YxgsPvV6A286TnYq-I5kRnpPtsp901TEVWWEiUxqPU~jy4Zzs5p8MYxWtb6So6a4Wyk3TrgX9fuo1EFWuk~ECYP2SxRl-yI4od8xUQ6sj3ZuwkOE6nr3DJIgLIvygulH6QEHZaMhP3rW0lXAytuHNuhzAu8QyA__\",\"altText\":\"\",\"originalImageWidth\":3350,\"originalImageHeight\":1688,\"isFillWidth\":false}],\"direction\":null,\"format\":\"left\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"left\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Link this in your README:\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"left\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"left\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"b0b56d5ccfc0b6301b205c40018ea473873cdf62\",\"src\":\"https://s3-alpha-sig.figma.com/img/b0b5/6d5c/cfc0b6301b205c40018ea473873cdf62?Expires=1768780800\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=I74Wq-S8CfyQDadOAHQH18iiZJrtDDgL76zN1Zbs9K~OwB0iN-Lk7XnRo6AhWTS67t2cwfmS3Lyi7TaXwZSNutsWvvOkI0FNfMWb0Q35WqZEdxPZ7bK6n5hXJadiBxPsjwEgft5pBqc1FacLFb1ls~VZPSnPWBKDLvhSathwGQWvEAbKG5M4g7OW8iVraoYN3ud5M4yIJ1vejUqmxNRDlrR7rlI4RMiheTW0Qxl~d3YQacle0mvOWOQWUal1h93n5UcuVzqDsMzeiBxtymW-fnGGRQqsWSUDcK8it2JTNUzpujfUD8u29lmlcS58fszke44hNAie9Vr7srRpFpgNmA__\",\"altText\":\"\",\"originalImageWidth\":3484,\"originalImageHeight\":1116,\"isFillWidth\":false}],\"direction\":null,\"format\":\"left\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"left\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Discoverability Benefits\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":1,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":1,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Being on Swift Package Index helps developers find your package through search, categories, trending packages, and quality signals. SPI shows more than just a list — it shows which packages are well-maintained.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Part 3 Checklist: Growth and Ecosystem\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h3\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"- [ ] DocC tutorial for getting started\",\"type\":\"text\",\"version\":1},{\"type\":\"linebreak\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"- [ ] Submit to Swift Package Index\",\"type\":\"text\",\"version\":1},{\"type\":\"linebreak\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"- [ ] .spi.yml configuration for docs hosting\",\"type\":\"text\",\"version\":1},{\"type\":\"linebreak\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"- [ ] Announce on Swift Forums\",\"type\":\"text\",\"version\":1},{\"type\":\"linebreak\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"- [ ] Share on Bluesky and Mastodon\",\"type\":\"text\",\"version\":1},{\"type\":\"linebreak\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"- [ ] Submit to iOS Dev Weekly\",\"type\":\"text\",\"version\":1},{\"type\":\"linebreak\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"- [ ] Add SPI badges to README\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Final Thoughts\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h3\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Building open-source Swift packages is rewarding. Seeing other developers use your work, contribute improvements, and build things you never imagined — that’s the magic of the Swift open-source community.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"These practices won’t guarantee success, but they remove the obstacles that prevent success. They make your package discoverable, understandable, and contributable. They signal \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":2,\"mode\":\"normal\",\"style\":\"\",\"text\":\"professionalism \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"and \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":2,\"mode\":\"normal\",\"style\":\"\",\"text\":\"care\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\".\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"The framework you’ve written deserves to be seen and used. These practices help make that happen.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Now go build something great and share it with the Swift community.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Previous: \",\"type\":\"text\",\"version\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Part 2: Community and Lifecycle\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"link\",\"version\":1,\"rel\":\"noopener\",\"target\":null,\"title\":null,\"url\":\"https://medium.com/@oleksii_24924/b1a0ed970e4e\"}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"See also: \",\"type\":\"text\",\"version\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Part 1: Foundation and Quality\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"link\",\"version\":1,\"rel\":\"noopener\",\"target\":null,\"title\":null,\"url\":\"https://medium.com/@oleksii_24924/34d58d16f581\"}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"root\",\"version\":1}}","itemId":"eb24ef1b-0fd4-4f84-b203-869d6e19431e","fieldSchemaId":"3084d9ba-ab55-4e5a-931b-b9db3d09105f"},{"id":"edb7dfad-fb46-46dd-a9dd-2ab29f35e12a","value":"{\"image\":\"8d8cf0627ae5135da376b408fdda972862f9dd03\",\"imageThumbnail\":\"3c987badd794abc1d294ddc0b93ba567182118fb\",\"originalImageHeight\":1080,\"originalImageWidth\":1920,\"altText\":\"\",\"fileName\":\"jakub-zerdzicki-QUtrcUo5-GI-unsplash.jpg\"}","itemId":"eb24ef1b-0fd4-4f84-b203-869d6e19431e","fieldSchemaId":"1f58afa6-2748-4188-b4a4-f1e54e37eca9"}]},"3e0aa220-8995-4e40-8d59-99da7a944021":{"id":"3e0aa220-8995-4e40-8d59-99da7a944021","index":"!Z","collectionId":"d4a5b68c-8afd-4bbe-a7ac-e9a8422fedde","fields":[{"id":"80379718-1aa0-4c84-b796-41140b1f67c8","value":"Oleksii Kolomiiets","itemId":"3e0aa220-8995-4e40-8d59-99da7a944021","fieldSchemaId":"df1c88d1-4bd8-4ecd-9059-463b9589de92"},{"id":"64b9675f-b11d-49d7-a572-137b7bea20c4","value":"iOS Developer","itemId":"3e0aa220-8995-4e40-8d59-99da7a944021","fieldSchemaId":"0a981f8a-7dbb-440d-a940-25d9060c9b11"},{"id":"54bff1b7-7d6e-4bd4-93ac-a7e2e9ab3fe3","value":"Ship It Right: A Swift Package Quality Checklist. Part 2 of 3.","itemId":"3e0aa220-8995-4e40-8d59-99da7a944021","fieldSchemaId":"f2ba59b9-49cc-4ec6-9416-bda99d4c8383"},{"id":"87e04f66-f24a-4cac-9f6e-b0a9afbf5b4b","value":"{\"root\":{\"children\":[{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Oleksii is an iOS alchemist at Snapp Mobile 📱✨, turning concepts into beautifully crafted Swift code and smooth, user-friendly interfaces. He’s passionate about shaping mobile experiences that feel effortless and refined. A firm believer in the power of simplicity, he focuses on writing clear, thoughtful code that brings ideas to life without unnecessary complexity.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"root\",\"version\":1}}","itemId":"3e0aa220-8995-4e40-8d59-99da7a944021","fieldSchemaId":"0b77f83b-c31a-4889-b9b3-9a6d2e41fc86"},{"id":"c0fdc805-13cf-4f71-8105-b4e390e43b3a","value":"ship-it-right-a-swift-package-quality-checklist-part-2-of-3","itemId":"3e0aa220-8995-4e40-8d59-99da7a944021","fieldSchemaId":"402ba26f-8f6d-4f5f-bf20-62e6549f4ad4"},{"id":"ace6c7d7-e7fc-40e2-80f6-2d0782e22265","value":"2026-01-05","itemId":"3e0aa220-8995-4e40-8d59-99da7a944021","fieldSchemaId":"b7712ee6-f9fd-4781-8c5c-e7e10ce8f81e"},{"id":"0bb16786-ac21-4d98-b7f8-5bcf29adbbb5","value":"{\"root\":{\"children\":[{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"In \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":2,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Part 1\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\", we built the foundation: documentation, tests, automated quality checks. Your Swift package is technically solid. The code works, it’s well-documented, and it maintains consistent quality.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Now comes the shift: from “my code works” to “others can contribute.”\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":3,\"mode\":\"normal\",\"style\":\"\",\"text\":\"This series is\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":2,\"mode\":\"normal\",\"style\":\"\",\"text\":\"for Swift developers turning internal packages into polished public repositories.\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" \",\"type\":\"text\",\"version\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Part 1\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"link\",\"version\":1,\"rel\":\"noopener\",\"target\":null,\"title\":null,\"url\":\"https://medium.com/@oleksii_24924/34d58d16f581\"},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":2,\"mode\":\"normal\",\"style\":\"\",\"text\":\"covered documentation and quality. This part focuses on community and lifecycle.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":2,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"This is where many solo-developed projects stumble. The code is great, but there’s no clear path for contributions. Issues pile up without organization. Releases happen chaotically. The infrastructure that worked for solo development doesn’t scale to community development.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"The gap isn’t technical — it’s process. You need infrastructure for guiding contributions, managing work, communicating changes, and shipping professional releases.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"The first time someone outside your organization contributes to your project is special. They took time to understand your code, fix something, and send it back. Make their experience smooth. A clear contribution path, simple templates, and responsive feedback turn one-time contributors into regular contributors.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"The infrastructure we’re building isn’t bureaucracy — it’s hospitality. It shows contributors that you value their time and want to make contributing easy.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h4\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"PR and Issue Templates: Keep Them Simple\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h3\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Here’s my philosophy on templates: they should be easy and optional. PR templates with fifteen sections and required checkboxes don’t increase quality — they discourage contributions. Three sections are enough.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"I learned this watching pull requests to my own projects. Early on, I created comprehensive templates with sections for “Testing Strategy,” \",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"“Performance Implications,” “Breaking Changes,” “Documentation Updates,” and more. Nobody filled them out completely. Contributors would either skip most sections or write “N/A” repeatedly, which helped nobody.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Now I use minimal templates that guide without overwhelming. Contributions increased because the barrier to entry dropped.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"The Simple PR Template\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h3\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Create \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":2,\"mode\":\"normal\",\"style\":\"\",\"text\":\".github/pull_request_template.md\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" in your repository:\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"f5f20adbf08723a62dcac60b1e1f8be5fd347941\",\"src\":\"https://s3-alpha-sig.figma.com/img/f5f2/0adb/f08723a62dcac60b1e1f8be5fd347941?Expires=1768780800\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=tzFLEt-zPH7KqStc50OOVM4GTRL6x4ZLJOkIRn1sEDCu2fmBrQc2yOal4qRPux9U9rZj~L0JVu7g4ALHdZcXKlHImOEERcsKXvCZIyf87LJM5aEhipGdcurSeTzFsOOGDK8zgmaWv1YB0NjkiPioEtrT~OOPGVlh1kxP9noQb-hP-y3u~31QQrYRFIqZwX0xwokdPwvw8ic6Z5QVaHbWqnftg0JvQfmkrXH-Zwo9hQLzhGMj-N3eyFZgW6Q0xoDlwSJv56Ttq0227PGeScVAv-fFzKVa6ff44MSVbtdKKjJBkryTPL8RFptxca-DRN9IOVdFsm8Q0Q-bxFJ7WEJTLg__\",\"altText\":\"\",\"originalImageWidth\":3484,\"originalImageHeight\":1340,\"isFillWidth\":false}],\"direction\":null,\"format\":\"left\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"96f055fc0fdaae9ca1dbf7aadc4e148c1de1232a\",\"src\":\"https://s3-alpha-sig.figma.com/img/96f0/55fc/0fdaae9ca1dbf7aadc4e148c1de1232a?Expires=1768780800\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=hJcSV23AzDNBl-lAg7D852TaO9inLTKQovF-rthOAKdky8jW4D00~7B6u78Q-wZAF7c6KheM~lKPlE7aiFgIelpSfHed11cbmUd9Cf35aDSqtnylQGxdZ2o0Qt6fHW-0jVd-xtSWip-b~09hvRbtOgr-LaOm7W1Cq4Cmwauiob1AW9rxFPD1eniho-ICSWeJjQeSRu9Lvq4HGrspNNP8FH8Y7qoL1OicgHTGjybMDNTEbrOGS3sHTTxSERRh4bnQa0AUd2IX4zJo72Dc~kPqEVriMP32ETrI2OdmiiBfwMP7-mu3tZ-A9KAXmqEhZ-1sAXZrKZgvaIDbOEfim36RTg__\",\"altText\":\"\",\"originalImageWidth\":1672,\"originalImageHeight\":520,\"isFillWidth\":false}],\"direction\":null,\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Issue Templates\",\"type\":\"text\",\"version\":1},{\"type\":\"linebreak\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h3\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"47496d848c05a93ecde836adf828e300b60811aa\",\"src\":\"https://s3-alpha-sig.figma.com/img/4749/6d84/8c05a93ecde836adf828e300b60811aa?Expires=1768780800\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=o4gDOR0mCrmZcSvobKq9xg7wOOFQAcrpo2QCryB5eNjLujrr6NYtAVG30aZun0dfhpgim-u7S8fJEIsvSmPXkQBmUOs9a5KgLWjKY5XxKrfgUlgLGMSTv6yDvbHOMEZvVPepXVlNBHK-Qtcm65BmduOgBYHqmwKCVRPZjbuqQrUkbCU124GiBCEbcT-TyF4LnMGbY-xek-GCh6l-OlkHNbkcXucNI3nvZD-OMFQTkSjsnZ7nVIVeBBjPAuRsnRpOQuCRUnhKl2Zd8P6LrG~ck4s74o1jQchjrMkp3eQ6HPYq-Eg-7t7uo--Sj9BBbPLPdLaIoznK~s~pkSWzQ78xAg__\",\"altText\":\"\",\"originalImageWidth\":3484,\"originalImageHeight\":1788,\"isFillWidth\":false}],\"direction\":null,\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"For issue templates, see this example: \",\"type\":\"text\",\"version\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"SnappDesignTokens\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"link\",\"version\":1,\"rel\":\"noopener ugc nofollow\",\"target\":\"_blank\",\"title\":null,\"url\":\"https://github.com/Snapp-Mobile/SnappDesignTokens/tree/main/.github/ISSUE_TEMPLATE\"},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\".\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"CONTRIBUTING.md\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h3\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Create a brief \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":2,\"mode\":\"normal\",\"style\":\"\",\"text\":\"CONTRIBUTING.md\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" that welcomes contributors and points to essentials:\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"a7c613707f0c0e2d6ec4ab035d152ce4de312228\",\"src\":\"https://s3-alpha-sig.figma.com/img/a7c6/1370/7f0c0e2d6ec4ab035d152ce4de312228?Expires=1768780800\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=KF0LDR4BLsNUwmMEirDQzbWPsCBmRD9fYZZsGabrPlNO6xQvghLnkAFSz2hJt1HA9pXBzNvCEt9LoZQ2KLtQ1aEHBy6YafVEO5jYae2sNc31Bvsbz5HUd4JK0Zm4mcGTBYI9lhzOhjeZ4JcBlThsTADW16FzuKn8kXdtDY5Ho3V-oypmD5iDFiRNH-t~wHdgM~FXym0osLOsYys9wWQ~7rVkeID60EwSabeEX~AYbCOPAnZUyhIKpTwqfvH-Nsy8R5jP~meaYnCSX1GbKjaP31WWhH9dHADwfA-Aqdi2bOljrEYrvFR8JGUMobAcmS9LBXubF9LA~ClDbQsOl2v1aw__\",\"altText\":\"\",\"originalImageWidth\":3484,\"originalImageHeight\":1564,\"isFillWidth\":false}],\"direction\":null,\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"The Philosophy\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h3\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Templates exist to help contributors provide useful context, not to enforce process for process’s sake. I’d rather get a PR with minimal template completion but good code than scare away a contributor with a 15-section form. You can ask for clarification during review. You can’t rescue a contribution that never happened because the process felt like too much work.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Issue Management: Planning Beats Stale Ideas\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h3\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Issues aren’t just for bug tracking. They’re your public roadmap, your planning tool, and your communication channel with users.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"An idea without a plan becomes a stale issue. Planning turns ideas into action.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Label Strategy: Keep It Simple\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":1,\"textStyle\":\"\"},{\"children\":[{\"children\":[{\"detail\":0,\"format\":2,\"mode\":\"normal\",\"style\":\"\",\"text\":\"bug\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" — Something is broken\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":1},{\"children\":[{\"detail\":0,\"format\":2,\"mode\":\"normal\",\"style\":\"\",\"text\":\"enhancement\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" — New feature or improvement\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":2},{\"children\":[{\"detail\":0,\"format\":2,\"mode\":\"normal\",\"style\":\"\",\"text\":\"documentation\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" — Docs need updating\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":3},{\"children\":[{\"detail\":0,\"format\":2,\"mode\":\"normal\",\"style\":\"\",\"text\":\"help wanted\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" — Good for contributors\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":4}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"list\",\"version\":1,\"listType\":\"bullet\",\"start\":1,\"tag\":\"ul\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Milestones: Group by Version\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":1,\"textStyle\":\"\"},{\"children\":[{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"1.0.0 — Issues planned for initial release\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"1.1.0 — Issues for first feature update\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":2},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"2.0.0 — Breaking changes for next major version\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":3},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Future — Ideas we like but haven’t scheduled\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":4}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"list\",\"version\":1,\"listType\":\"bullet\",\"start\":1,\"tag\":\"ul\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Avoiding Stale Issues\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":1,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":1,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Stale issues make repositories look abandoned. Combat this with regular triage. \",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"For stale issues:\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":2,\"mode\":\"normal\",\"style\":\"\",\"text\":\"This issue hasn’t had activity in 6 months. Is this still relevant? If we don’t hear back in 2 weeks, we’ll close this to keep the issue tracker focused.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":2,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"For won’t-fix issues:\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":2,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Thanks for the suggestion. After discussion, we’ve decided not to pursue this because [specific reason]. Closing as wontfix, but appreciate you taking the time to open this issue.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":2,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":2,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Communication Through Issues\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":1,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":1,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Issues are public communication. How you respond matters:\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Be welcoming: “Thanks for reporting this! I’ll investigate.”\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Be clear about timing: “I won’t have time to look at this until next month, but PRs welcome.”\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":2},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Be honest about priorities: “This is a nice idea but not currently on the roadmap. Would love a PR if you’re interested.”\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":3},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Close decisively: If you won’t fix something, say so and close it.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":4}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"list\",\"version\":1,\"listType\":\"bullet\",\"start\":1,\"tag\":\"ul\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"An issue is valuable only if it has a path forward. If an issue has no path forward, close it. You can always reopen if circumstances change.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h4\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"CHANGELOG.md: Simple Version History\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h3\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"A changelog lists what changed in each version. Users need to know what changed between versions, especially when deciding whether to upgrade.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"I keep a CHANGELOG.md in every repository. When I cut a release, I update the changelog. When users ask “what changed in 1.2.0?”, we can point them to the changelog.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"93c70f98292d30561875d49a0688c62f7de1ae38\",\"src\":\"https://s3-alpha-sig.figma.com/img/93c7/0f98/292d30561875d49a0688c62f7de1ae38?Expires=1768780800\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=O0Ryesizk0Gnsf00YOOA19bQCan0yNTvzYmRxXZ6Kf9~5SFbzaVK5MaIR9Q1dZwXyYK-klM0SmuNJxUSAdiMkS0BhKESF-oHqtMTj0nSMih-zDoHzkRYCoRliNTzOfmnDK5AbkX-6uZYy1Q3VNXK64YPIChyg2~9ofS24Wf5WPu3RMj148faemEBpgrPaTWmliRrwLnkkChSR8hwTr05NxeMCXo6sGmhESSCzauMbLAVZ-xqf82aadWI~iM2nix1ahjjV6YuojhYYaTsPsCe-2~fZbpfI0N8LHF5qSDOyfq5eau5GdhP-nThIYMmVPQwloCFwHTSXvS69ICG3GTKvw__\",\"altText\":\"\",\"originalImageWidth\":3484,\"originalImageHeight\":2084,\"isFillWidth\":false}],\"direction\":null,\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Categories: \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":2,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Added, Changed, Deprecated, Removed, Fixed, Security\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\". Not every release needs every category. Use what’s relevant.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Keeping It Updated\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":1,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":1,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Update the changelog as you merge changes, not at release time. When you merge a PR:\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"If it adds a feature, add an entry under [Unreleased] → \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Added\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"If it fixes a bug, add an entry under [Unreleased] → \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Fixed\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":2},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"If it’s a breaking change, add an entry under [Unreleased] → \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Changed\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":3}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"list\",\"version\":1,\"listType\":\"number\",\"start\":1,\"tag\":\"ol\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"This is easier than trying to remember everything at release time.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":1,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Integration With Releases\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":1,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":1,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"When you create a GitHub Release, copy the changelog entry into the release notes:\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"8a96a94c3171ebf7ed27aa3ee2d1561ff528a1ef\",\"src\":\"https://s3-alpha-sig.figma.com/img/8a96/a94c/3171ebf7ed27aa3ee2d1561ff528a1ef?Expires=1768780800\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=TfpMYkSLTckZdifOgYGPNuIcBktggBc4O4nLUjk0jmfjlTcQwJDQnuFsdLGEd9AqEEsf065qrE-fKs6PZ~d0vAzT98qR7ZvKz7sUFTbqQrOCM9clhAuUeAqeNYBt4-U~oRuunGqwCxFmtKYakf71ITW9M7qUzPvDDAaN666ZELfHk2v3U-bkyXF-oDnMflRU6GkFtuthpoDGbxFlDmvz2W-UFNk6NxJdJex7txNvsxxd6kl~UpDRzOmcYLnIXIMkPArJ4i70Po2QxH2pRmrcA3DbwZB6Fe0v-wY9aDEKYoTs87-~67Uk71XAR84HZ2bS~Mk3MCC0Y6OlerjqSfLXKA__\",\"altText\":\"\",\"originalImageWidth\":3484,\"originalImageHeight\":1712,\"isFillWidth\":false}],\"direction\":null,\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"fae032e759112d126f28e2e14967caf735312c40\",\"src\":\"https://s3-alpha-sig.figma.com/img/fae0/32e7/59112d126f28e2e14967caf735312c40?Expires=1768780800\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=lBen9GLiJnLkl-stAdt7xYEORyeNsRL-tYov~7GGv60arOBOnkP-dybn~JWWXPgd9lljhkhH~MkuuUGydUM91A4I-9Cd6xKK3fYoBFXXm7NbhjO9TDHnMlfCruYGxzejug8ZqfR4D7mJqUXfyZB0jWAUBviWTRqZ2iG1M-UCDDZMeSM0dDt0L8fDaCRpEkE9e0bJkY0~MTs-M7n7Nih8mojlZzgx951zsk1-uoKLAzJNH~-cPupG4BvLr6DjgzL-oJ6klOyer8pw5wDkSm9PBRNYoxjDdUzj0lGR1toHHC~PZKSPAyzYOVVbqLLqnHNWnLXaUqKZt6kDemEMoEii0w__\",\"altText\":\"\",\"originalImageWidth\":2500,\"originalImageHeight\":1258,\"isFillWidth\":false}],\"direction\":null,\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Releases and Tags: Semantic Versioning Made Easy\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h3\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Releases communicate stability and progress. A well-managed release process tells users “this version is stable and ready” while giving them clear expectations about what changed.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"For Swift Package Manager projects, tags are particularly important — they’re how users specify which version of your package to use.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Semantic Versioning\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":1,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":1,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":2,\"mode\":\"normal\",\"style\":\"\",\"text\":\"SemVer\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" uses three numbers: \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"MAJOR.MINOR.PATCH\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":2,\"textStyle\":\"\"},{\"children\":[{\"children\":[{\"detail\":0,\"format\":2,\"mode\":\"normal\",\"style\":\"\",\"text\":\"MAJOR\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" — Breaking changes that require users to modify their code\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":1},{\"children\":[{\"detail\":0,\"format\":2,\"mode\":\"normal\",\"style\":\"\",\"text\":\"MINOR\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" — New features, backward-compatible additions\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":2},{\"children\":[{\"detail\":0,\"format\":2,\"mode\":\"normal\",\"style\":\"\",\"text\":\"PATCH\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" — Bug fixes, no API changes\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":3}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"list\",\"version\":1,\"listType\":\"bullet\",\"start\":1,\"tag\":\"ul\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"This convention sets clear expectations. When I see 1.2.3 to 1.2.4, I know it’s safe. When I see 1.2.4 to 2.0.0, I know to check the changelog.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":1,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Creating Git Tags\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":1,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Tags mark specific commits as releases:\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"983ea9c4508cb806dee13db9a5671cadface2b99\",\"src\":\"https://s3-alpha-sig.figma.com/img/983e/a9c4/508cb806dee13db9a5671cadface2b99?Expires=1768780800\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=dqm8cd9L-GwjVbGKP4rifLn8zV8~B3zQ184fIqDX3GijrEQQH0uyZjLOIWjok1CTK-wL~yxyCaEAxtjhmeboxdMfFI8mSybuPoftKQn9SGOX2Cg3EOl2F1IpsZSKtmTyn7y9NJqfQ5Tye8do4LuoQAx3XILaewKInU-apnoeHW5JBssRxSOgCh34odX6SMlETC5p35JJy1ZE88xOChgVO81DbteRxRxaD~YtTK3v-JXf4f0cxh0yPU9Ub9YiFlBAbHSJJ77m-BThmgvmQ1tgQmjF0SA8h7g0MPbiVtfgDjQoOGMEvU53VK16uaygnfbv4kt15BIEQhcPI3QD8OOwbA__\",\"altText\":\"\",\"originalImageWidth\":3484,\"originalImageHeight\":892,\"isFillWidth\":false}],\"direction\":null,\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Always use annotated tags (-a) rather than lightweight tags. Be consistent with naming — I prefer 1.2.0 without the v prefix because it matches SPM convention.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"SPM Compatibility\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":1,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":1,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Swift Package Manager uses git tags for versioning. When you specify:\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"4b1e4f5c0908a9da439815495cb748261e679187\",\"src\":\"https://s3-alpha-sig.figma.com/img/4b1e/4f5c/0908a9da439815495cb748261e679187?Expires=1768780800\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=jQ6y8RueDpcDOh5HmbFKkeLL2YPu1fyKPWKXHJqgb6vqZJ4zK2hjBqk-QRVr3hecAbQ6Z0fzF-8HkNKXM7hNUz6ZTGSmu3DXzI7Hs9qC0MRrqWynI1FzWwfaQjGHcQHpw6OKPKFWqz7i51g8o5EdhiKd0lsb5M8wr4WQKaieAZSh98mzPi3YKTJLrtBvmNULHjszHg4xSPejjWrRhqI3wBqpL5TxRXj7zxlrgsrE4UDv0kLlWEjbPrlhDIEDEfXoHX7cljxHLDRsyMhH~~~WnW1u-ewu0wmkE3PF8iIzo2Lt1wJcj0GAqq4WMnFA6Mf55pzm6YVOdIrDyh~M~lPT9A__\",\"altText\":\"\",\"originalImageWidth\":3484,\"originalImageHeight\":892,\"isFillWidth\":false}],\"direction\":null,\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"SPM looks for tags like 1.2.0, 1.2.1, 1.3.0, etc. Your tags directly control what versions are available.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"This means:\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Every release needs a tag\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Tag names must follow semantic versioning\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":2},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Bad tags can’t be easily removed (they break existing dependencies)\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":3}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"list\",\"version\":1,\"listType\":\"bullet\",\"start\":1,\"tag\":\"ul\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Tag \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":2,\"mode\":\"normal\",\"style\":\"\",\"text\":\"carefully\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\". Verify the commit is correct before pushing.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":1,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Release Checklist\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":1,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Before creating a release:\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"✅ All milestone issues are \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"closed\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"✅ Tests \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"pass\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" on all platforms\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"✅ \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"CHANGELOG\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\".md is updated\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"✅ Version number \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"follows\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" semantic versioning\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"✅ Documentation \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"is\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" current\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Then:\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"1. Update CHANGELOG.md (move [Unreleased] to version number)\",\"type\":\"text\",\"version\":1},{\"type\":\"linebreak\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"2. Commit: git commit -m \\\"Release 1.2.0\\\"\",\"type\":\"text\",\"version\":1},{\"type\":\"linebreak\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"3. Create tag: git tag -a 1.2.0 -m \\\"Release 1.2.0\\\"\",\"type\":\"text\",\"version\":1},{\"type\":\"linebreak\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"4. Push: git push \u0026\u0026 git push origin 1.2.0\",\"type\":\"text\",\"version\":1},{\"type\":\"linebreak\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"5. Create GitHub Release with changelog content\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"The Professional Touch\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":1,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":1,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Regular, well-documented releases signal that your project is actively maintained. Users trust packages with clear versioning and release notes. Your release process is your communication with users about stability and progress.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Part 2 Checklist: Community and Lifecycle\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h3\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"- [ ] Simple PR template (What/Why/Changes)\",\"type\":\"text\",\"version\":1},{\"type\":\"linebreak\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"- [ ] Bug report and feature request issue templates\",\"type\":\"text\",\"version\":1},{\"type\":\"linebreak\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"- [ ] CONTRIBUTING.md with getting started guide\",\"type\":\"text\",\"version\":1},{\"type\":\"linebreak\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"- [ ] Label strategy (bug, enhancement, help wanted, etc.)\",\"type\":\"text\",\"version\":1},{\"type\":\"linebreak\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"- [ ] Milestones for version planning\",\"type\":\"text\",\"version\":1},{\"type\":\"linebreak\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"- [ ] CHANGELOG.md following Keep a Changelog format\",\"type\":\"text\",\"version\":1},{\"type\":\"linebreak\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"- [ ] Semantic versioning with git tags\",\"type\":\"text\",\"version\":1},{\"type\":\"linebreak\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"- [ ] GitHub Releases with release notes\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Previous: \",\"type\":\"text\",\"version\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Part 1: Foundation and Quality\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"link\",\"version\":1,\"rel\":\"noopener\",\"target\":null,\"title\":null,\"url\":\"https://medium.com/@oleksii_24924/34d58d16f581\"}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Next: \",\"type\":\"text\",\"version\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Part 3: Growth and Ecosystem\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"link\",\"version\":1,\"rel\":\"noopener\",\"target\":null,\"title\":null,\"url\":\"https://medium.com/@oleksii_24924/e6afbb6f0a0e\"}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"root\",\"version\":1}}","itemId":"3e0aa220-8995-4e40-8d59-99da7a944021","fieldSchemaId":"3084d9ba-ab55-4e5a-931b-b9db3d09105f"},{"id":"3c3b5bb2-c474-46c5-82c8-0d34900133d0","value":"{\"image\":\"da13da006bf625c3725b28063f3a4b8d4601a7ae\",\"imageThumbnail\":\"d96cac1b7a361a0f31774300876081dd26d2f8cc\",\"originalImageHeight\":1280,\"originalImageWidth\":1920,\"altText\":\"\",\"fileName\":\"luca-bravo-XJXWbfSo2f0-unsplash.jpg\"}","itemId":"3e0aa220-8995-4e40-8d59-99da7a944021","fieldSchemaId":"1f58afa6-2748-4188-b4a4-f1e54e37eca9"}]},"934a726a-65e7-4441-a00f-dcdba787d4c0":{"id":"934a726a-65e7-4441-a00f-dcdba787d4c0","index":"(O","collectionId":"d4a5b68c-8afd-4bbe-a7ac-e9a8422fedde","fields":[{"id":"ed3c93b7-9dc2-4b37-b277-a37e76bc387d","value":"{\"root\":{\"children\":[{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"If you are an Android developer, chances are you might have been working on your own Android libraries. A library is a useful way to create a reusable set of features that need to be integrated through different apps (or even different libraries).\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"A library is a self-contained package including code and resources required to execute some functionality. Importing a library in our Android app is the same process as importing a .JAR file in a Java app, except that for Android the library file has the extension .AAR, which extends for Android archive (however, Android apps can also import libraries with a .JAR extension). \",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"There are detailed guides on the Internet on how to create Android libraries, but in this article I would like to focus on some aspects that are more subjective, and not always defined in every guide. We will discuss today the following aspects:\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Keeping in mind exposed functionality\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Kotlin/Java interaction\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":2},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Exposing resources\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":3},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Transitive dependencies and strategies to solve them\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":4}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"list\",\"version\":1,\"listType\":\"bullet\",\"start\":1,\"tag\":\"ul\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Keep in mind which functionality will be exposed\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h2\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"A library likely offers an interface to the user to access its functionality. Regardless of whether the particular library encapsulates UX functionality, some interface towards an API… there will also be some classes and methods that are not relevant to the end-user, and that they will likely be exposed. How to prevent this?\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Use properly visibility modifiers. If you are using Java, tend to prioritise the default modifier \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"package private\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\". If you are using Kotlin, lend towards \",\"type\":\"text\",\"version\":1},{\"children\":[{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"internal\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"link\",\"version\":1,\"rel\":\"noopener ugc nofollow\",\"target\":\"_blank\",\"title\":null,\"url\":\"https://kotlinlang.org/docs/reference/visibility-modifiers.html\"},{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\" \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"(this means that it will be visible for the module).\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Sometimes, packages need to be transitively exposed. For instance, think of the following setup for a library we are working with:\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":2}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"list\",\"version\":1,\"listType\":\"bullet\",\"start\":1,\"tag\":\"ul\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"2a31a60a86aea9bf701b294a5adfb22f4202cf20\",\"src\":\"https://s3-alpha-sig.figma.com/img/2a31/a60a/86aea9bf701b294a5adfb22f4202cf20?Expires=1769990400\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=FdUynzBDXv214Hyd7TmKMw5j6qtlCnV5X6ET7TZhWYtElgmgA45t54aqTwentR0HyZs9~zBD35aHZ5qzqVHKTSsYkBrQrtpOjGv3nSm3cLUIMTWwOfBt4hiHWpw6k4TQtYRSQdB8Rm6JJBtoNtOuOxVG~bCbQbx-erhZvf-bOY52E87jRgIbj7fpbh3jrzqZ0ZLUG6UC~bnwkiZwZbc3KcrFfLrWXI2czGTOOkdgteZa-G3C6mbZR~7C1AkdPmqJ05SjPeX656KxA6JSbF6Ks~4z9V2uVF01I0l7CUPqPGarKmeTqz~0XOTaC4OiEyADLdhvbXx5TkmfYojWhxjXug__\",\"altText\":\"\",\"originalImageWidth\":303,\"originalImageHeight\":221,\"isFillWidth\":false}],\"direction\":\"ltr\",\"format\":\"center\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Library structure including a module using an internal model\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"center\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"My library \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"has a dependency on \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"My module\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\", which is an internal module used by the library. My library needs to access some data from the module (let’s say, some internal models). We need to declare them as public. But then, every class that integrates the library will be able to access those models, which is rather uncomfortable.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":1,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"You could name the package of the model as internal (for instance, \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"my.package.internal.models\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"). This is a common industry practice, and it *should* discourage the usage of those classes. For instance, \",\"type\":\"text\",\"version\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Retrofit \",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"link\",\"version\":1,\"rel\":\"noopener ugc nofollow\",\"target\":\"_blank\",\"title\":null,\"url\":\"https://github.com/square/retrofit/search?q=internal\"},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"or \",\"type\":\"text\",\"version\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"OkHttp \",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"link\",\"version\":1,\"rel\":\"noopener ugc nofollow\",\"target\":\"_blank\",\"title\":null,\"url\":\"https://github.com/square/okhttp/search?q=internal\"},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"have the same naming for their internal classes.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Since Kotlin 1.4 there is an Explicit API mode, that enforces to operate on a short of library mode. In order to activate it, write the following on your Gradle file:\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"cab8551bc2bd16d2c125d9568264659b3593834a\",\"src\":\"https://s3-alpha-sig.figma.com/img/cab8/551b/c2bd16d2c125d9568264659b3593834a?Expires=1769990400\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=XDk2SM8SO79Vn4AAdnOMeaWOZ5g00c4-G597Z-tYIet7yk4jOvdLj0B9rNf4v45-3EBCstQ3VXUpaR9dbZ4pCWrOoUWQAT7RNhPAPT2GuLJ7gPEN4tu-4G6naX5GG2ZsbG04MyFR5FV3Ae~rBJTKS1HHKT8hgmpFvM7gD2uFNMRx1kcLy3uz-Uz4wUVEBy2NTezG0uyHkTFmV-Kyvh8u5xKriTX6B-jOHI1eqvhAkw5-6l~Ow7JZU~E6mdjdKpFIO2jywG4Jzpr-kWFYuZuoEerciBGoaFaNt6pkiLhBzGt-sihigEPIPbqBTXNyWHjQjVCsSUTrVd91rw8ougIAPQ__\",\"altText\":\"\",\"originalImageWidth\":3484,\"originalImageHeight\":1564,\"isFillWidth\":false}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"The setup is fairly straightforward: one mode will be strict and trigger errors, and the less strict mode will trigger warnings.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"When the Explicit API mode is activated, visibility modifiers are required for declarations if the default visibility means they will be public. This will enforce visibility to be specifically declared.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Kotlin/Java interaction\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h2\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Kotlin should not be a strange word for you anymore. And this means that you should be aware of how Kotlin and Java interact with each other, and keep this in mind to ensure that the library can be called seamlessly. This means: you might be calling your Kotlin library from a Java codebase, or you might be calling your Java library from a Kotlin codebase. In those cases you will need to put an extra dose of attention, to improve the experience of the users implementing your library.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Package level functions\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h3\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Since Java does not allow standalone functions outside classes, all the standalone functions or properties that you declare in a file \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"file.kt\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" will be compiled as static methods of a class called org.file.FileKt:\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"c610fe12738c2650334d9d4844f6d7e6da2d03e2\",\"src\":\"https://s3-alpha-sig.figma.com/img/c610/fe12/738c2650334d9d4844f6d7e6da2d03e2?Expires=1769990400\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=fCIGC-mZahboF0M~qgSv-fY1QwIUEJFsAd7XADr6Cw47MWgKKG9faotU3oAZR3jn~EIwkEBsulJ3OOft3tfzpV2w4BvoFArTtRIDCguhf9TAUpQxRhbWXV23d74BciH0K-hnqSPMx-SDBLMRGCT2bTpuvEHSNG06GNPcCQHIzlshpK13Pk1MayJgRGA7cAoRYQer8rGkRfn4n7L7NrGgNXaed88Dcy7gSLFTyfoub6RFwgHgdgVb8s~PdOuLWgxtNtjxsSXBpgxZ7005vQF2sfoprX70dPu4kkJupv~cflEFkZb-wcHN69eAy1aV9L1TP9hKbhMRLrzw9muwpNNzEQ__\",\"altText\":\"\",\"originalImageWidth\":3484,\"originalImageHeight\":1040,\"isFillWidth\":false}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"This would compile in a Java class like the following:\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"16480960ce305588685d7c6d5e140501010abd4f\",\"src\":\"https://s3-alpha-sig.figma.com/img/1648/0960/ce305588685d7c6d5e140501010abd4f?Expires=1769990400\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=sJRIF~2JWrA0tgu4RDbgMAlBr8GKTnQRy863QmaDPd9K0Z4j5yyyGuFpjqNngCvvTFBRH4DYoHbbTjpQSqaxyfqUOzFNlcdkoBYVbo3YGCEncV4ZC8u0FXOWxThgqJDX0HfB6KiyksrOGJsDGZRxfbb9r7JXrIefsTek2H~bsiL9fXlD12MZCgPGl~5sL8f4hA9C1Qx03SfVq6liFzaGUVDqsPx2TVI5NAt3gTP5twEoyFEF6~coyJmTz30U8dn~4tpxoPuq~5pEsJaF4S6l62DhqxlKv5Uj7O82yYdTUjyVViVewgzYaIUe68Fyr6XXmiJtFC0wteG~NaThe5Kanw__\",\"altText\":\"\",\"originalImageWidth\":3484,\"originalImageHeight\":892,\"isFillWidth\":false}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Of course, having the classes automatically named is something that we want to avoid. By using the annotation \",\"type\":\"text\",\"version\":1},{\"children\":[{\"detail\":0,\"format\":16,\"mode\":\"normal\",\"style\":\"\",\"text\":\"@JvmName\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"link\",\"version\":1,\"rel\":\"noopener ugc nofollow\",\"target\":\"_blank\",\"title\":null,\"url\":\"https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.jvm/-jvm-name/index.html\"},{\"detail\":0,\"format\":16,\"mode\":\"normal\",\"style\":\"\",\"text\":\" \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"we can specify the name of the destination class:\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":16,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"cd635bff18a00114abbbd1fecf745d740baab37a\",\"src\":\"https://s3-alpha-sig.figma.com/img/cd63/5bff/18a00114abbbd1fecf745d740baab37a?Expires=1769990400\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=ezimCxQv9RvaDLZ1NxqCCZ0Q0eSmOES5by8HAxld7e705ZsRZS3gPOf4cQbCp7Mv0BmkJLUDxk1AJpVEF~jU7jAWC20ph50E7qanRixQxXFrApje2lgbGqas8vqJP~Lrlh9bK4OG-K5b1wL5F96wveEm7Qxcq~W1mJFa6cj4~Ou3LfEjMaOBnAxXzi92XKxU3hYqClkLvqmymUc8S8rMQHwllI53i6AY3rhzRM3CHMs4dln7m2rDNqSHebGRjVudPpRUibK3om-EnHPlbL--tgWH7JEYgnZEHeg3uVcDvG1S-XGaL--9LgrEGQrum1yjXXlf9DuCRuceiAm5lEc6sw__\",\"altText\":\"\",\"originalImageWidth\":3484,\"originalImageHeight\":1116,\"isFillWidth\":false}],\"direction\":null,\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"You can also use \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":16,\"mode\":\"normal\",\"style\":\"\",\"text\":\"file:JvmMultifileClass\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" to combine the top-level members from multiple files into a single class.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Instance fields\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h3\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"If you need to expose any underlying property in Kotlin to a Java class, use the annotation \",\"type\":\"text\",\"version\":1},{\"children\":[{\"detail\":0,\"format\":16,\"mode\":\"normal\",\"style\":\"\",\"text\":\"@JvmField\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"link\",\"version\":1,\"rel\":\"noopener ugc nofollow\",\"target\":\"_blank\",\"title\":null,\"url\":\"https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.jvm/-jvm-field/index.html\"},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\". This will make the property accessible from your Java class.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":16,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Functions with default parameters\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h3\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"When you define a function in Kotlin with default parameters, you don’t need to continuously pass them when you are calling that function. If they are not specified, the default value is taken.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Java does not support default parameters, so what happens when we call these functions in Java? By default, we need to specify all the parameters, and this does not scale well if you have been using default parameters in Kotlin. This is where we can use \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":16,\"mode\":\"normal\",\"style\":\"\",\"text\":\"@JvmOverloads.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":16,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Let’s consider the following fictional function in Kotlin:\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":16,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"091e1727dde98c000dba6526c2f83f4fe3949849\",\"src\":\"https://s3-alpha-sig.figma.com/img/091e/1727/dde98c000dba6526c2f83f4fe3949849?Expires=1769990400\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=VfGgP5-mM2izbeoFBjxoTyPyBjeUdG5WfO3u6KAyRFZBHt9S9camyRcUcZgo0xoDYQ4VZmeEHmYcKgOs02G5bvKgalsFnBvUDE6JL8IUJh8BAFnsl8v7MrzAr1QZktAd-NwFxPLhSD0lGFRYFNEE8GcZyzx5tyMG-xktgPRrdTEU150YHyjKIRtZnYrulGUvSk9ASMkohfFM2cBgTuBOdVWGpP~0Cq18WV6ZmrkuXUqqnhwKR61jmRxD7jT6o21BU-iUmfehiyw9WNCZLNBwY~hVT3OLymYBrCCTh5fjjWalonxFtN7XiqMO2nwvWw4fGlhDrX59EOtcFWRgRMQK1g__\",\"altText\":\"\",\"originalImageWidth\":3484,\"originalImageHeight\":1192,\"isFillWidth\":false}],\"direction\":null,\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":16,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":16,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"The function is using the annotation \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":16,\"mode\":\"normal\",\"style\":\"\",\"text\":\"@JvmOverloads,\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"and it also has two default parameters as arguments. From a Java point of view, this function will compile as follows:\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":16,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"312fb4b1a25d35024c63ff45e60a00bcbaa6afb6\",\"src\":\"https://s3-alpha-sig.figma.com/img/312f/b4b1/a25d35024c63ff45e60a00bcbaa6afb6?Expires=1769990400\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=PTT1tTGRQqXn6KT7pHcHoF7QBjstjXwEkiPTBXlZUnjZ7OvJX6FnvFOWHQw9qzlLn-1VtNqvgUW0pIZ~vaaoZ6bMo7qYjxXeaAb03U~5i3kvJZ2iomLrvKhBpVokflVtDLRmDi5p8rXb18hKTKLH3DzaR7e2-RmknUt9U1YVe0lOIS3SGDFoLnp0bbcX-ZOsohGJ3qA~qBW~kLiIi4Q5SZVN5B~8iZ6zxDvEU7pyL5NIXR3sA92wJeVQ-YX07kj-6ZkBLas6sSQuG1xJYuc3PrJ8RNm5PitNPQHdRcwj26bKwlDPoqfvFe7-p8ozDyl0ETz0qzEx-zHNel~wqYYUug__\",\"altText\":\"\",\"originalImageWidth\":3484,\"originalImageHeight\":1192,\"isFillWidth\":false}],\"direction\":null,\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":16,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"The advantages are obvious when we are dealing with long constructors that are using some default parameters, and that we do not need to specify again in our Java classes.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Nothing generics in Kotlin\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h3\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"A Kotlin type with a generic parameter \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":16,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Nothing\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" is exposed as a raw type in Java. This should be avoided, since raw types are rarely used in Java.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Companion functions and constants\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h3\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"When Companion functions and constants are rawly compiled and accessed from Java, they are only available as instance methods on a static Companion field. For instance, the following Kotlin class:\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"be3750abf872997860606f70120e3630a3b85680\",\"src\":\"https://s3-alpha-sig.figma.com/img/be37/50ab/f872997860606f70120e3630a3b85680?Expires=1769990400\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=t3uhjjFOrpISqUyUy8cHCow9FczwaqH4niJ02f80pQtuwXGP5exwMwExFzKHUk1OCUHeIiTegEb6ms~5TYeiiQBrrfl7Dzj040if~ODUAzgcf2PvQzr2Zt70Mt7JUh1WVU2ATg5ag3olWn~r58sy-emQeiChoI9xm78QdXDE3-jIfsCKsRlrRWEDU1TT1-VXxfqO4VRVAg~dle5jbkMI5L64e9vss9zZfGjn-K3hm1pcg95rNRv7gm6q1wQWRtLPG8DlIaZjY3OPQwWfJsuPxPKnCV2dRGa9x1P3hwdM3X~SlT48UvOMvS5uHjRMisVzy0lx~nSDQmK3s5mmPW9R2g__\",\"altText\":\"\",\"originalImageWidth\":3484,\"originalImageHeight\":1192,\"isFillWidth\":false}],\"direction\":null,\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"is exposed as follows in Java:\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"f4fe5ad81d561f52c9890303b01558b155c71ea1\",\"src\":\"https://s3-alpha-sig.figma.com/img/f4fe/5ad8/1d561f52c9890303b01558b155c71ea1?Expires=1769990400\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=IJb1McB30ebxlk4b~iDPHHS5~595iKXJHkb2o-hlgT6SzVyJIMHE4ccCuAPY9Z9tW5KOxNr2zwkXBgThV5tJjmDNUXKjsOh1Ftdb2saLF29S~risX7UTlsm1r2i5yfdGxVGph9ycqgDpNlzWC1VgZ30pt2a0o2RIzbNK2A3gprxy0v3fpe1Z-8e1RSkexpLyw0JkHfi8Lv7D0VpbmM1HZj1E0bNP1r1ldq5pByig7XftvaWQ9Fs5NSIewn~hNft06uIJRm9TyoKZDYBSMmIUsMrIgN~wqBTUG7VNFKo~q8O8D9RWQN3UiWEPwSCCjvubxlkH1DzpJmDpH2mDK0QJxA__\",\"altText\":\"\",\"originalImageWidth\":3484,\"originalImageHeight\":1116,\"isFillWidth\":false}],\"direction\":null,\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Using a \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":16,\"mode\":\"normal\",\"style\":\"\",\"text\":\"@JvmStatic\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" annotation for the function makes the compiled code cleaner:\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"c72e473ddafdcf692687d4e414086b2c76c777f6\",\"src\":\"https://s3-alpha-sig.figma.com/img/c72e/473d/dafdcf692687d4e414086b2c76c777f6?Expires=1769990400\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=n3r8WeenBWdjsq536o1eBByRR9BGe-smtlbKp3tHWz5EzJ739BB0l75w7Rbu1KE-XK9zjhYo64VIAle9DAksCSK8a6BOwzKpo0gXWF3NLRul0U~LyGnzZwXzlzxTNqcrsXdAGRuTUOhtUcRduN6XEp4fnYghdDG0ed87Ryc4iSorK7TcUkToFPZx-GjxRFNtpEXlCU9yWnRd7jcw~DsvxwJ9MB4kfMjhggfIxsVbh4jwtwHyYWVXIauuq77I01-v9DZbXgPVwSPpOVLRCR-eS~fmLKDWw1HP30LDQXOxa57vXAg6JDqOOgL197UPOEoP37wpMcnG7WndvPtAhoR5Dg__\",\"altText\":\"\",\"originalImageWidth\":3484,\"originalImageHeight\":1116,\"isFillWidth\":false}],\"direction\":null,\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"For companion constants, is better to use the annotation\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":16,\"mode\":\"normal\",\"style\":\"\",\"text\":\"@JvmField\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\", since \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":16,\"mode\":\"normal\",\"style\":\"\",\"text\":\"@JvmStatic\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"creates a weird getter. For instance, consider the following companion constant:\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"348d7eb5b4f93f1e87ea6dc0074f2148ffc7f787\",\"src\":\"https://s3-alpha-sig.figma.com/img/348d/7eb5/b4f93f1e87ea6dc0074f2148ffc7f787?Expires=1769990400\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=sfVpg2taCdmIBLwAbJx7mGO5IQZiCHYAAA-PQwdfMxzorDZVjloboormAbksPwNXcwvPE7mjiWSueQ8M-O4Ww4LkeBXQ5Ejn-dEvDUc4WJQidmMNk3p5IX6ObST7kjCX4s0kgS9zpp5a78B9bjTat2qWn2fGhqsPH-CtqYQRvQTcZZkRsLetWxk491UkZn6eOr5iPbiQ6Pnb-a-26pZNC724XQZDKNAZfSBt3N4QHvw6If7Qka6jpvJXa0oY2VxKyHQoJR8bmQO9fGD7agbwfB3CgVJQxWp8s5F6ipw12jgQdT6w1M8AJ33WFg93zKGZuR~IwfgU758IXACAJWo9Og__\",\"altText\":\"\",\"originalImageWidth\":3484,\"originalImageHeight\":1116,\"isFillWidth\":false}],\"direction\":null,\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Annotating the companion value with \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":16,\"mode\":\"normal\",\"style\":\"\",\"text\":\"@JvmField\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"will result again in a Java code much more comprehensive:\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"44f2d215af84d080ed6458ed01b66738954bed65\",\"src\":\"https://s3-alpha-sig.figma.com/img/44f2/d215/af84d080ed6458ed01b66738954bed65?Expires=1769990400\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=Ol4TNwYadQ5PFTNdUz0nkPbOK6R-RzYrYA5oY~qsGSf9pYbx~Iitlra4GPXz2NgWGxA~Ey~8gVSNR2se9O5o65jiQLfb4NTC27rnvnEmCNz0WC8Y7RLoMWSOgOjp~DcWO7NMcbEtEdS1G1T7BPkUhCuoplsYhIJ~7fgYW~6EMunc2KvAfMvVM6BMYxgQ3fgolTOnyERJdk1cpQntq9vxB48Sy~Ta8~SRQDxxC7Cx2qNamFDQw9ZcC9Z5c1OA6CnSxrFP-Zwmtn0vR6l8YK~ewIouAHkRU7-jBWAqx8vk~VdNWbNiViffoFEqNaWErPL1ze4aXU083ZFoYCAFUD18mg__\",\"altText\":\"\",\"originalImageWidth\":3484,\"originalImageHeight\":1116,\"isFillWidth\":false}],\"direction\":null,\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Exposing resources\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h2\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Something that some folks are not aware of is that, by default, all the resources in an Android library are public! This means that everything that is included in your \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"res\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" folder (images, drawables, strings…). It is somehow a convoluted and counterintuitive method, but in order to make all your resources private, you should define at least one resource as public.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"A good practice is to make public only a string specifying the library name. Do this when you start developing your app, and you will not have to worry about the external visibility of your resources anymore (that is, unless you really want to make them public).\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"bc40f1fe06a6619432384676dcd9260d47775c1f\",\"src\":\"https://s3-alpha-sig.figma.com/img/bc40/f1fe/06a6619432384676dcd9260d47775c1f?Expires=1769990400\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=oiFGj1tybVVgrbhAbopZbv1CM3NnfguIB7TkJhNJSNymyWTUacVikn4RqFIZk7auNw0uGhOHYTCbc7heONmo5B3nYzsaN38pyLyMZeP1XQhJwGKfzhmB4mXPL9tdxjnbh0ttIMRMhJw397ndEnCK7qiCGHcAJyImQpNj3fEin14v5e9xmpK7IE0CfApr9EnATRb389JzzRoxawtTq~sfEiMLJ4BN6Z~gUAJGl75B-mQIvF25UuYKBv7-gpH0gnLfY-SgL09RNfSJb1a~p94~rSEFYmX~2g2oOSCQVxDOaSV8iR2l-IcBVLY63kfVmRyTGKrg3JDi98myQwRiurejGw__\",\"altText\":\"\",\"originalImageWidth\":3484,\"originalImageHeight\":968,\"isFillWidth\":false}],\"direction\":null,\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Be aware of transitive dependencies\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h2\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Libraries might depend on external dependencies, and ideally you want to deliver all of them within the same .AAR. Otherwise, the user will need to manually include them, and this is complicated to handle.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"On the other hand, we might be enforcing the user to include certain libraries that might conflict with the ones included at their app level.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"There is no silver bullet here, and a few strategies to solve this issue.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Include all the transitive dependencies\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h3\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"A. AAR file can be generated including all the dependencies it needs. This is not done automatically out of the box by the .AAR file, and needs to be somehow hacked.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"You can add and call a Gradle task that copies all the dependencies into the .AAR when this is packed:\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"12faa9c523108433410702db588100cd59bd222f\",\"src\":\"https://s3-alpha-sig.figma.com/img/12fa/a9c5/23108433410702db588100cd59bd222f?Expires=1769990400\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=VSOlZ~qu2gtMR2p-js~6gg9RZNv8HOYU2u37rMHbOIeoA7tfqxYH6i6K49rNGGVhFizVylXcsbx1bUu3oo2AZ7ueRuUuzmoDSTURnGGlblh4jjfqq4IY2oMFysHmSC5gms4uThMaTmShxLVHDuism1mpSSWqkiHUNzHyunGwaZyoZ-u2u8ih9lmSAqWVA4T6Jr9hT3IugR30u2NkjSeNTfla9CKC4hXCA-JNSW1jot~L0WS9Nk~duWq6Y33NlrWFwY-80AWPUC6hBAZ6ovminznzN8kW023bllPDS84h7xMyVKhKEKIywMGa51dLmWpJy9y3xX15nU72hPXejJTo7g__\",\"altText\":\"\",\"originalImageWidth\":3484,\"originalImageHeight\":1040,\"isFillWidth\":false}],\"direction\":null,\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"There is a facilitation plugin, \",\"type\":\"text\",\"version\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"fat-aar\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"link\",\"version\":1,\"rel\":\"noopener ugc nofollow\",\"target\":\"_blank\",\"title\":null,\"url\":\"https://github.com/kezong/fat-aar-android\"},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\", that ameliorates this task. It does a few more things, but I found it a bit unstable (by the time I have to release a new library version, a new Gradle version is also available that generally breaks the plugin).\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Strategies to force or remove dependencies\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h3\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Also known as hell. Let’s say that your main app includes a \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"RandomLibrary \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"version 2.1. The app needs to include your \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"FancyLibrary\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\", which includes the version 3.1 of \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"RandomLibrary\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\", with a lot of breaking changes. You might need to force the resolution of a particular version, or remove some libraries from the build. In projects heavily modularised this can exponentially increase the complexity of your build script.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"The following Gradle lines can exclude a library from the build:\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"595a1b97d0fb6d26000c82ec067e65f7e32d439d\",\"src\":\"https://s3-alpha-sig.figma.com/img/595a/1b97/d0fb6d26000c82ec067e65f7e32d439d?Expires=1769990400\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=keOmVKNJQwY1FU9uS~N3FPH~GUl7WGAEAtM9LU-BWOig7swjySWoTtzDLWBfcb4o76TuFH4oz~LruTcn-bMAa8J31zot3CKxw7g32GN6zviCfKT7Zv3JI4KjY7nWtuG6ZlodP10xdWvESjl8EWWTxYA241IaGXKHZedSHohQmS6-tARr6fK1E6WRqsDXr-4vngPfly0f3f94SrYCeOEqFp8fALE99EZlf1VPd89229Y3LI5Ue0vqoVNb~uBNRBB3svbWUEBrK6OwdHqayU5M0Ok7t4Jfv17yBlrEOs72p8-TqQF45bIvDKgW9WTlW3gz4M4eskl93HLIjl~2AJomAQ__\",\"altText\":\"\",\"originalImageWidth\":3484,\"originalImageHeight\":968,\"isFillWidth\":false}],\"direction\":null,\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Summary\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":1,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":1,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Designing and writing a library is more than packaging a few classes. Ideally, a phase of design needs to take place where you think about the structure and classes’ organization. Your company structure will affect this heavily as well (Do you have different teams working on different modules? Do you have an open repository policy? Do you have any restrictions to use external libraries? How much politics influence your development work?).\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Thanks \",\"type\":\"text\",\"version\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Florina Muntenescu\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"link\",\"version\":1,\"rel\":\"noopener\",\"target\":\"_blank\",\"title\":null,\"url\":\"https://medium.com/u/d5885adb1ddf?source=post_page---user_mention--c80940d79ae---------------------------------------\"},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\", \",\"type\":\"text\",\"version\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Marton Braun\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"link\",\"version\":1,\"rel\":\"noopener\",\"target\":\"_blank\",\"title\":null,\"url\":\"https://medium.com/u/ec2087b3c81f?source=post_page---user_mention--c80940d79ae---------------------------------------\"},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" and \",\"type\":\"text\",\"version\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Marius Budin\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"link\",\"version\":1,\"rel\":\"noopener\",\"target\":\"_blank\",\"title\":null,\"url\":\"https://medium.com/u/a8c7d12ff9c1?source=post_page---user_mention--c80940d79ae---------------------------------------\"},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" for the review, you rock.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"root\",\"version\":1}}","itemId":"934a726a-65e7-4441-a00f-dcdba787d4c0","fieldSchemaId":"3084d9ba-ab55-4e5a-931b-b9db3d09105f"},{"id":"085975f7-89d4-4961-8fa2-246b493f6d08","value":"Considerations when creating Android libraries","itemId":"934a726a-65e7-4441-a00f-dcdba787d4c0","fieldSchemaId":"f2ba59b9-49cc-4ec6-9416-bda99d4c8383"},{"id":"27ccd562-e9b4-45ce-9e36-ae63092bc9ca","value":"considerations-when-creating-android-libraries","itemId":"934a726a-65e7-4441-a00f-dcdba787d4c0","fieldSchemaId":"402ba26f-8f6d-4f5f-bf20-62e6549f4ad4"},{"id":"7aa7da69-3a71-4450-9f54-15ae4281db7b","value":"2021-02-18","itemId":"934a726a-65e7-4441-a00f-dcdba787d4c0","fieldSchemaId":"b7712ee6-f9fd-4781-8c5c-e7e10ce8f81e"},{"id":"12c7f8c7-aebc-4b5a-a91c-1811766ff2e4","value":"Enrique López-Mañas","itemId":"934a726a-65e7-4441-a00f-dcdba787d4c0","fieldSchemaId":"df1c88d1-4bd8-4ecd-9059-463b9589de92"},{"id":"88cc2c33-5700-493c-b846-fd309ae43b06","value":"{\"image\":\"e3b9812c4d176b81022bff7246701860f0ae7c46\",\"imageThumbnail\":\"e3b9812c4d176b81022bff7246701860f0ae7c46\",\"originalImageHeight\":611,\"originalImageWidth\":800,\"altText\":\"\",\"fileName\":\"image_17 1.png\"}","itemId":"934a726a-65e7-4441-a00f-dcdba787d4c0","fieldSchemaId":"1f58afa6-2748-4188-b4a4-f1e54e37eca9"},{"id":"54a36a55-3827-40e9-9532-db738cfd6756","value":"CTO - Snapp Mobile","itemId":"934a726a-65e7-4441-a00f-dcdba787d4c0","fieldSchemaId":"0a981f8a-7dbb-440d-a940-25d9060c9b11"},{"id":"997e8175-3b65-4cd3-a331-b0e291e5ed04","value":"{\"root\":{\"children\":[{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Enrique López Mañas is the CTO at Snapp Technology. He has been working with mobile technologies and learning from them since 2007. He is an avid contributor to the open source community and a FLOSS (Free Libre Open Source Software) kind of guy, being among the top 10 open source Java contributors in Germany. He is a part of the Google LaunchPad accelerator, where he participates in Google global initiatives to influence hundreds of the best startups from all around the globe. He is also a big data and machine learning aficionado. In his free time he rides his bike, take pictures, and travels until exhaustion. He also writes literature and enjoys all kinds of arts. He likes to write about himself in third person.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"root\",\"version\":1}}","itemId":"934a726a-65e7-4441-a00f-dcdba787d4c0","fieldSchemaId":"0b77f83b-c31a-4889-b9b3-9a6d2e41fc86"}]},"1425c56f-1ef8-4ab9-b2dc-c0088893fd3e":{"id":"1425c56f-1ef8-4ab9-b2dc-c0088893fd3e","index":"%w","collectionId":"d4a5b68c-8afd-4bbe-a7ac-e9a8422fedde","fields":[{"id":"7334062a-9f18-4b15-80d8-82bad994eb3a","value":"{\"image\":\"4fba42cc8cf2fdbcfc2dec3a961b32a7b59970e3\",\"imageThumbnail\":\"33ffa40676b6c1932f666a28e7f8795c503a5881\",\"originalImageHeight\":630,\"originalImageWidth\":1200,\"altText\":\"\",\"fileName\":\"droidcon-berlin_24-speakercard-Enrique-Lopez-Manas.jpg\"}","itemId":"1425c56f-1ef8-4ab9-b2dc-c0088893fd3e","fieldSchemaId":"1f58afa6-2748-4188-b4a4-f1e54e37eca9"},{"id":"a534f7c9-4957-4bd6-adab-1bdff1f6b315","value":"Enrique López-Mañas","itemId":"1425c56f-1ef8-4ab9-b2dc-c0088893fd3e","fieldSchemaId":"df1c88d1-4bd8-4ecd-9059-463b9589de92"},{"id":"1f2178d4-6043-49f9-b46d-1933497e4415","value":"CTO - Snapp Mobile","itemId":"1425c56f-1ef8-4ab9-b2dc-c0088893fd3e","fieldSchemaId":"0a981f8a-7dbb-440d-a940-25d9060c9b11"},{"id":"74913f2a-fd56-4e55-93e6-a26b65ab5db4","value":"{\"root\":{\"children\":[{\"children\":[],\"direction\":null,\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"}],\"direction\":null,\"format\":\"\",\"indent\":0,\"type\":\"root\",\"version\":1}}","itemId":"1425c56f-1ef8-4ab9-b2dc-c0088893fd3e","fieldSchemaId":"3084d9ba-ab55-4e5a-931b-b9db3d09105f"},{"id":"d843d1b3-19d7-4e36-8a0b-4a58259cf8cd","value":"Android Open-source repositories 101","itemId":"1425c56f-1ef8-4ab9-b2dc-c0088893fd3e","fieldSchemaId":"f2ba59b9-49cc-4ec6-9416-bda99d4c8383"},{"id":"79e48353-327e-46e7-8938-ab25e6597dfc","value":"2024-07-03","itemId":"1425c56f-1ef8-4ab9-b2dc-c0088893fd3e","fieldSchemaId":"b7712ee6-f9fd-4781-8c5c-e7e10ce8f81e"},{"id":"ed6acf54-0a78-4bd1-a251-254d667be23f","value":"android-open-source-repositories-101","itemId":"1425c56f-1ef8-4ab9-b2dc-c0088893fd3e","fieldSchemaId":"402ba26f-8f6d-4f5f-bf20-62e6549f4ad4"},{"id":"ddf5ebda-8408-421e-9e51-57c7df02c7f7","value":"{\"root\":{\"children\":[{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Enrique López Mañas is the CTO at Snapp Technology. He has been working with mobile technologies and learning from them since 2007. He is an avid contributor to the open source community and a FLOSS (Free Libre Open Source Software) kind of guy, being among the top 10 open source Java contributors in Germany. He is a part of the Google LaunchPad accelerator, where he participates in Google global initiatives to influence hundreds of the best startups from all around the globe. He is also a big data and machine learning aficionado. In his free time he rides his bike, take pictures, and travels until exhaustion. He also writes literature and enjoys all kinds of arts. He likes to write about himself in third person.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"root\",\"version\":1}}","itemId":"1425c56f-1ef8-4ab9-b2dc-c0088893fd3e","fieldSchemaId":"0b77f83b-c31a-4889-b9b3-9a6d2e41fc86"}]},"801904a3-de95-4dee-930a-d8b66953403e":{"id":"801904a3-de95-4dee-930a-d8b66953403e","index":")","collectionId":"d4a5b68c-8afd-4bbe-a7ac-e9a8422fedde","fields":[{"id":"086c143e-ecf1-49d7-b7cb-cbe3f384ce03","value":"Enrique López-Mañas","itemId":"801904a3-de95-4dee-930a-d8b66953403e","fieldSchemaId":"df1c88d1-4bd8-4ecd-9059-463b9589de92"},{"id":"72f7ce7d-90a0-4258-b94a-16cd6aa90b7e","value":"Creating a library for Android: The Good, the Bad and the Ugly","itemId":"801904a3-de95-4dee-930a-d8b66953403e","fieldSchemaId":"f2ba59b9-49cc-4ec6-9416-bda99d4c8383"},{"id":"439e4875-6727-4a10-9683-b176b73cc4af","value":"creating-a-library-for-android-the-good-the-bad-and-the-ugly","itemId":"801904a3-de95-4dee-930a-d8b66953403e","fieldSchemaId":"402ba26f-8f6d-4f5f-bf20-62e6549f4ad4"},{"id":"3c047a9b-1802-4524-bb19-9d98786225c3","value":"2018-09-27","itemId":"801904a3-de95-4dee-930a-d8b66953403e","fieldSchemaId":"b7712ee6-f9fd-4781-8c5c-e7e10ce8f81e"},{"id":"cb5f4c3f-0366-4801-9cbc-b2db86a3949a","value":"{\"image\":\"642841fff70dfcbfbc2fe54f6aca2d7d1c7835fa\",\"imageThumbnail\":\"6a12b361137fefc7f9f7346210494e281d81b637\",\"originalImageHeight\":678,\"originalImageWidth\":1024,\"altText\":\"\",\"fileName\":\"image 27.png\"}","itemId":"801904a3-de95-4dee-930a-d8b66953403e","fieldSchemaId":"1f58afa6-2748-4188-b4a4-f1e54e37eca9"},{"id":"af0b2fce-00b7-4674-b381-e504f2a7fa04","value":"CTO - Snapp Mobile","itemId":"801904a3-de95-4dee-930a-d8b66953403e","fieldSchemaId":"0a981f8a-7dbb-440d-a940-25d9060c9b11"},{"id":"7543757c-3ed1-449b-8b2b-fcef263a97b2","value":"{\"root\":{\"children\":[{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Enrique López Mañas is the CTO at Snapp Technology. He has been working with mobile technologies and learning from them since 2007. He is an avid contributor to the open source community and a FLOSS (Free Libre Open Source Software) kind of guy, being among the top 10 open source Java contributors in Germany. He is a part of the Google LaunchPad accelerator, where he participates in Google global initiatives to influence hundreds of the best startups from all around the globe. He is also a big data and machine learning aficionado. In his free time he rides his bike, take pictures, and travels until exhaustion. He also writes literature and enjoys all kinds of arts. He likes to write about himself in third person.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"root\",\"version\":1}}","itemId":"801904a3-de95-4dee-930a-d8b66953403e","fieldSchemaId":"0b77f83b-c31a-4889-b9b3-9a6d2e41fc86"},{"id":"a43a0ea3-b401-4fbb-812e-66f4effb4431","value":"{\"root\":{\"children\":[{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Software Development is like an \",\"type\":\"text\",\"version\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Ouroboros\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"link\",\"version\":1,\"rel\":\"noopener ugc nofollow\",\"target\":\"_blank\",\"title\":null,\"url\":\"https://en.wikipedia.org/wiki/Ouroboros\"},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\". You end up going to the place you have previously resided, with requirements and knowledge updated and refashioned. You might have started working on an initial prototype that began the journey as a basic \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":2,\"mode\":\"normal\",\"style\":\"\",\"text\":\"HelloWorld\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\", and it has evolved into one of those mythological Nordic monsters. Or maybe Greek monsters are more terrifying and frightening. I do not know.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"At one of my projects we recently came up with the requirement of extracting some of the functionality well buried there to expose to third-party consumers. Our code connects to our API and performs some operations (authentication, managing our entities, etc…) that now were required to be used by another client. I have seen this frequently and previously at other workplaces — the need to create a MobileKit or MobileLibrary, you name it, that can be reused in different applications. Therefore, this functionality can be reused among applications at the same company, or they can be offered to third-party users to access their APIs.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"There are different methods you can follow for the development and distribution of such components in the Android ecosystem. In this article, I want to outline them and give you the arguments to decide which one can adapt better to your particular scenario.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Creating your Android library\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h2\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Starting here, we have different approaches. Generally, if we are following a principle of isolation, I would concur with keeping from the beginning our library in its own BitBucket, GitHub or whatever repository. We want to fence off our components, and bring all the benefits from different software philosophies (\",\"type\":\"text\",\"version\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"open/closed principle\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"link\",\"version\":1,\"rel\":\"noopener ugc nofollow\",\"target\":\"_blank\",\"title\":null,\"url\":\"https://en.wikipedia.org/wiki/Open/closed_principle\"},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\", \",\"type\":\"text\",\"version\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"software reuse\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"link\",\"version\":1,\"rel\":\"noopener ugc nofollow\",\"target\":\"_blank\",\"title\":null,\"url\":\"https://en.wikipedia.org/wiki/Code_reuse\"},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\", etc). Maybe adding a sample to the same repository to showcase how to use and access the library is fine (this is, in fact, a very common state-of-the-art approach). \",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"In your Android Studio, it is very easy to add a new \",\"type\":\"text\",\"version\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"library module\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"link\",\"version\":1,\"rel\":\"noopener ugc nofollow\",\"target\":\"_blank\",\"title\":null,\"url\":\"https://developer.android.com/studio/projects/android-library.html\"},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\". Now the arduous task that we will flagrantly diminish starts: it is time to start and develop your own library, eventually with samples, documentation and anything you consider proper to include.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Providing access to your brand new library\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h2\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"You are finished with your library, ready to publish a first beta version or glad about sharing with others for the first time your superb functionality. Now it is the time to provide access and distribution. There are different possibilities here, each of them providing an assorted handful of benefits and drawbacks.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Providing access to your library as a Git submodule\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h3\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Git Android library project as a sub-module as a submodule means that you will be able to access the source code of the newborn library. The source code is checked out as the code of your main application, and it can be as well modified locally (eventually also committed directly from the main project). This might make sense is some particular contexts:\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"You work in the same organisation with people working on apps that require access to the same APIs that might needed to be changed by any team member.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"The same people working on the apps are working as well on the library.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":2},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"The tempo for developing the library is steady, your CI process cannot guarantee a continuous delivery of new versions of the library and you need to commit them as soon as possible to the repository.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":3}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"list\",\"version\":1,\"listType\":\"bullet\",\"start\":1,\"tag\":\"ul\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"The methodology to perform this it is straightforward. From your local git repository, you need to add your submodule:\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"32852de7b013d44bed8de6a0334cf5538b6a5a6a\",\"src\":\"https://s3-alpha-sig.figma.com/img/3285/2de7/b013d44bed8de6a0334cf5538b6a5a6a?Expires=1769990400\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=kjsArd7c4relbpBKrYbfaPEEM5ZDoHqbq9sAr2iANEkm3EkzfifNQDGaJu8H9qiqCTPTA~xc8REFvJ1s6InR17FHj9wXsXgB3ese8bx5d3hFwpmH7ab7lLfWO6xqrvFXEejkSOm2sCV-nF-lffpLoaIQpCmBFUgH5YkpStYMfmY1f6kPFgvV68UX1fnhhyYrEY-ij5EDF3g9GObJsocUwi-soRvCLi95kQR4mh2Dc-zkDLD9M450uuVxryKGOFzBKl9ElEvUMMFBMndRKM-YPuudSMaSOuaUnIPwK0lLSPOb4BpaKgopM1o11Z0LaWRxxlmDXNfpKz835fl83~bioQ__\",\"altText\":\"\",\"originalImageWidth\":3484,\"originalImageHeight\":892,\"isFillWidth\":false}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"And update consequently your \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"settings.gradle\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" and \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"build.gradle\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" files.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Ah! There is something I always forget when I am cloning a directory with submodules. That is, you need to specify that the module you are cloning contains… submodules.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"47b61b9d5d321a68d0db3a538220b96ea3ae79b4\",\"src\":\"https://s3-alpha-sig.figma.com/img/47b6/1b9d/5d321a68d0db3a538220b96ea3ae79b4?Expires=1769990400\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=Qmk8StIa7m13LrfJI7RieLSQY3gJZ3XTE6q~nHs2hVoov8JkvH4tOVOB6zkzi0WfXFk56Lj1zSMGIMSDb-yTTOWU3lUXEHkfry1qyV~uIuAyIdCvI8MOZdhAQxGK61UxrDTJdovEn7uubOkXquVLdYxJQFVgqkmiv15MkA8UI5S-pEfrSfLiRMae3fQxxp0NQo39PVhb37B~bql3lQpP8O5TMccmQSI~LjnzUlsfjAE2nPR7tb2JXWukGSAjFjhYQlDdWCSE0Bs74zy3gZoPqLPBUO426yCmBuHnMCdbySMxINnkTsxP9uVt4Hhg3O-bx3S-QjbawPsjiDvFmT-A1Q__\",\"altText\":\"\",\"originalImageWidth\":3484,\"originalImageHeight\":892,\"isFillWidth\":false}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Any human mean of having this behavior as default by Git? Not that I am aware of. I remember I always clone the repository without the submodules, and then I have to download the submodules manually. It is one of those facts that always entail an issue left aside, such as adding an Activity to an Android project and forgetting to add the same Activity to the AndroidManifest.xml.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Distributing the new Android library in a self-contained file\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h3\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"You might be lacking the infrastructure to provide your library as a Git submodule, or you might want to choose another mean of distribution for different reasons:\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Privacy and/or security: nobody needs to be aware of the code of the new library.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Better isolation: even if people work in the same organisation, they do not need to get involved with the technicality of the library and just access the source code.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"listitem\",\"version\":1,\"value\":2}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"list\",\"version\":1,\"listType\":\"bullet\",\"start\":1,\"tag\":\"ul\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"I am not including in this section distribution through a Nexus Server, and I see reasons to keep it separately. For my aforementioned client, I suggested to keep the distribution of the library through a Nexus repository, and the argued reason was that the Nexus repository of the organisation was only accessible from the internal network, whereas most of the Mobile workforce was remote or partial remote.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":2,\"mode\":\"normal\",\"style\":\"\",\"text\":\"In any organisation you will encounter different truths, scenarios, complications, limitations and situations you need to deal with. Never take a single methodology as the Holy Grail. Instead, learn as many methodologies to solve a problem as you can, and decide which one applies better in your particular storyline.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":2,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":2,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"So let’s return to our primal origin: distributing the Android library in a self-contained file. In the Green Droid realm, we can tackle mainly two file formats: \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\".aar\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" and .\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\"jar\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\". The first one stands for Android archive, and the latter stands, unsurprisingly, for Java archive. They are both zipped files containing many classes, metadata and resources. It has been claimed that \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\".aar\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" can contain Android resources, whereas \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\".jar\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" cannot. This is not true: there is no actual limitation against the file types that a \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\".jar\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" file can contain (check the .jar file \",\"type\":\"text\",\"version\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"overview\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"link\",\"version\":1,\"rel\":\"noopener ugc nofollow\",\"target\":\"_blank\",\"title\":null,\"url\":\"https://docs.oracle.com/javase/6/docs/technotes/guides/jar/jar.html\"},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" and \",\"type\":\"text\",\"version\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"specification\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"link\",\"version\":1,\"rel\":\"noopener ugc nofollow\",\"target\":\"_blank\",\"title\":null,\"url\":\"https://docs.oracle.com/javase/6/docs/technotes/guides/jar/jar.html\"},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\").\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"As a de facto industry standard, if you are using Android Studio as a build and are aiming to target mainly Android clients, you are better off with a \",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":1,\"mode\":\"normal\",\"style\":\"\",\"text\":\".aar\",\"type\":\"text\",\"version\":1},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\" file.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"When you are creating your files, it is a good idea to upload the resulting libraries to your GitHub repository, keep your branches up-to-date, organising releases in Git and of course using \",\"type\":\"text\",\"version\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Git tagging\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"link\",\"version\":1,\"rel\":\"noopener ugc nofollow\",\"target\":\"_blank\",\"title\":null,\"url\":\"https://git-scm.com/book/en/v2/Git-Basics-Tagging\"},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\".\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Distributing through a Nexus repository\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h3\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"You have your library ready. You have versioned it, and you are ready for deployment (this might sound more appealing for people deploying rockets into orbit, but I can ensure the alluring feeling of finally unlock your software to third-parties after a long development period is equally enchanting). Now it is time to release it through a Nexus Repository.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"A Nexus repository manages artifacts for download. You develop your software, upload it to a Nexus repository and make it public to the world. It is a very convenient way, and keeps every aspect of the development wheel quite framed in a domain. As I mentioned, there might exist limitations in your organisation, but this is, in my opinion, the most optimal option to release an artifact.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"When you add a file from a Nexus repository, you typically include the following line in your Gradle script:\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"fcf24384879266eb0c762f6bf8b55497b6a1c5e3\",\"src\":\"https://s3-alpha-sig.figma.com/img/fcf2/4384/879266eb0c762f6bf8b55497b6a1c5e3?Expires=1769990400\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=jWDGFtf58lqUG-wnKGNHQU14jZJOgYrwmrc4oa2uBUWkmb1Lp5NrUQ5NELsd~-j5VqGpnctKcAPZQig33KpIMMHd6wjld7ipwcDv4FByeSYOMAScJC699RRXMi6QGmrFHZaree3d~UuDMzsCjD7iC3r7N5jrGmPq~TlcnCpTLY96NgHV7Peoa4r2SQAZRq7fDdgXgCjCDzzNicbXovxkuWI1HubdeFgwu5JpdM5zydytbvOgYU8kPNP3wbkMo0TM6sUpfqD7tN73KgUJk~C6Jp2rkf37c8QQfOIipbqapojI1M4SfMHm8aMlIJ~cmGMSJUNJEtnQ9beq-tafj9QnUw__\",\"altText\":\"\",\"originalImageWidth\":3484,\"originalImageHeight\":892,\"isFillWidth\":false}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"A Nexus repository can be public or private. As I mentioned in the case of my client, the Nexus repository was only accessible from their internal network, and it was therefore not an optimal solution. There are well-known public Nexus repositories, such as \",\"type\":\"text\",\"version\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Maven Central\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"link\",\"version\":1,\"rel\":\"noopener ugc nofollow\",\"target\":\"_blank\",\"title\":null,\"url\":\"https://search.maven.org/\"},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\", which you are very likely already using, or \",\"type\":\"text\",\"version\":1},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Sonatype\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"link\",\"version\":1,\"rel\":\"noopener ugc nofollow\",\"target\":\"_blank\",\"title\":null,\"url\":\"https://www.sonatype.com/nexus-repository-oss\"},{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\". \",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"If you are developing OSS this will be your instant choice, since the offer a free-tier and you can expose your work to the world. This can as well be automated, and therefore being uploaded automatically to a repository through a Gradle script:\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"type\":\"image\",\"version\":1,\"hash\":\"0756a9745d23181f78543e200ee6b60eaa4e7dd9\",\"src\":\"https://s3-alpha-sig.figma.com/img/0756/a974/5d23181f78543e200ee6b60eaa4e7dd9?Expires=1769990400\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=sPbQ23zdYJDWs15SHMJOWfrvd-gM6FPkn9VVUwEuXs~q0b-pxdkRv8UhISAPJ0ASmX0zdDcLObUzwNyhIYtPUfozwrp3xd2QVf0det5x5BqQno6GRlQFtCKxwtBq20LOuk7rlU~vlbFpjpIjlYnJl68j2M7CCzwp1PVTp3QNJR8BdFhkynnRjXgBtGHgJcGJC91GqHRRKTEp8mLPjrNha~OIi-Qx8K0lJ-7IPOE9L6hp2NIbp-z8h4ge0Ip-YhnC8b2AxNyLIoKy0LG~~Hdy~dz8A0AZXueJDNvgo2lJet5wzCQF-djrlxbuOn-Nkal0lnoLFXBRxMVP2u0tMuaGPw__\",\"altText\":\"\",\"originalImageWidth\":3484,\"originalImageHeight\":1712,\"isFillWidth\":false}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Conclusions\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"heading\",\"version\":1,\"tag\":\"h2\"},{\"children\":[],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"},{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"There will never exist an approach with no flaws to the needs of the software, organisation and product you are trying to build. For a standard OSS, the distribution through a Nexus repository (and having the obvious choice as well of cloning the library as a submodule) is an ideal alternative. For other scenarios, you need to balance all the requirements and take one decision that might mix some of the previously introduced elements.\",\"type\":\"text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"start\",\"indent\":0,\"type\":\"paragraph\",\"version\":1,\"textFormat\":0,\"textStyle\":\"\"}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"root\",\"version\":1}}","itemId":"801904a3-de95-4dee-930a-d8b66953403e","fieldSchemaId":"3084d9ba-ab55-4e5a-931b-b9db3d09105f"}]}}}},"slugByItemId":{"e893ce81-635b-48b0-bd01-c3f39aa1c453":"linting-a-swift-package-with-swift-format","54d55d03-8f64-4a4e-94a6-397cf873c405":"do-we-need-another-os","3c5b467e-c8c3-4e68-b2fc-d0ea238942cb":"ship-it-right-a-swift-package-quality-checklist-part-1-of-3","a9458e2b-bfb5-4cf8-883d-d6edb7f1113d":"how-we-found-the-perfect-android-automotive-developer-kit-solution","d170bf6b-3352-42d5-a55b-7bd99f0f7709":"we-really-need-to-take-infotainment-error-handling-seriously","74a1903b-5353-4325-b47a-2610388e8506":"how-we-created-a-multi-brand-design-system-in-figma","840b0f15-1e38-49a9-8e49-be9e609cb518":"ci-cd-for-openharmony-project-github-action","f4e5f709-ebad-44e5-8d9c-69abed2fdf8b":"a-deep-dive-into-our-powerful-theming-engine-for-android-automotive","1a52d56d-e318-40ff-8553-f3e4be29839e":"harmonyos-app-development-101","80345e24-6050-439b-9c3b-9e1690a6a5de":"cangjie-a-programming-language-from-huawei","7c10a08b-d604-4d4d-a009-2400c53b6b59":"multi-module-projects-with-cangjie","d38bc66e-898e-469d-a28e-7e25efcd5e82":"meet-snapptheming","9048f7a9-740a-4bde-a9e3-e779de37ca73":"bringing-flexible-rapid-development-to-automotive-infotainment-systems","eb24ef1b-0fd4-4f84-b203-869d6e19431e":"ship-it-right-a-swift-package-quality-checklist-part-3-of-3","3e0aa220-8995-4e40-8d59-99da7a944021":"ship-it-right-a-swift-package-quality-checklist-part-2-of-3","934a726a-65e7-4441-a00f-dcdba787d4c0":"considerations-when-creating-android-libraries","1425c56f-1ef8-4ab9-b2dc-c0088893fd3e":"android-open-source-repositories-101","801904a3-de95-4dee-930a-d8b66953403e":"creating-a-library-for-android-the-good-the-bad-and-the-ugly"}}