PageSourceSearch

https://pixelpoint.io/component---src-templates-blog-post-jsx-cont…-macos-app-index-md-d88cd5a9ce934385a91b.js

js pixelpoint.io collected 2026-10-03 22:12:27 UTC 17,643 bytes, 2 lines download raw bytes

1"use strict";(self.webpackChunkpixelpoint_website=self.webpackChunkpixelpoint_website||[]).push([[8664],{9135:function(e,t,a){a.r(t),a.d(t,{Head:function(){return b},default:function(){return h}});var n=a(8453),i=a(6540);function A(e){const t=Object.assign({p:"p",ul:"ul",li:"li",a:"a",h2:"h2",span:"span",h3:"h3"},(0,n.RP)(),e.components);return i.createElement(i.Fragment,null,i.createElement(t.p,null,"Two years ago, we began the process of building a simple, open-source MacOS app as a side project, but this turned out to be a much more challenging journey than we initially thought. Here, we talk about the various stages of this journey, including:"),"\n",i.createElement(t.ul,null,"\n",i.createElement(t.li,null,"how we built the app to mute/unmute microphones using the shortcut or touch bar icon;"),"\n",i.createElement(t.li,null,"why taking an open-source approach did not meet our expectations;"),"\n",i.createElement(t.li,null,"what limitations Apple placed on the touchbar that rendered it useless for our needs."),"\n"),"\n",i.createElement(t.p,null,"We’ve just released our Mutify app on ",i.createElement(t.a,{href:"https://www.producthunt.com/posts/mutify"},"Product Hunt"),", so now we’re waiting for your feedback and support!"),"\n",i.createElement(t.h2,{id:"initial-idea"},i.createElement(t.a,{"aria-hidden":"true",tabIndex:"-1",href:"#initial-idea"},i.createElement(t.span,{className:"icon icon-link"})),"💡Initial Idea"),"\n",i.createElement(t.p,null,"I often spend a lot of time on calls in the middle of work days discussing tasks, solutions and future plans with tech teams working on various different projects. While on these calls, I prefer to mute my mic anytime I’m not speaking. However, I often switch between browser tabs or look at presentations while in these meetings, which makes it hard to quickly unmute myself as I search for the tab and unmute icon I need. To resolve this, I began using a MacBook 2016 with the touchbar, thinking that adding a mute button to the touchbar could be an effective solution. This is what sparked the journey that eventually led to our new app."),"\n",i.createElement(t.span,{dangerouslySetInnerHTML:{__html:'<figure class="gatsby-resp-image-figure" style="">\n    <span\n      class="gatsby-resp-image-wrapper"\n      style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 696px; "\n    >
1\n      <span\n    class="gatsby-resp-image-background-image"\n    style="padding-bottom: 56.32183908045977%; position: relative; bottom: 0; left: 0; display: block;"\n  ></span>\n  <picture>\n          <source\n              srcset="/static/5dc25e603a1517582fc6b27e76351cff/09400/mutify.webp 174w,\n/static/5dc25e603a1517582fc6b27e76351cff/3266f/mutify.webp 348w,\n/static/5dc25e603a1517582fc6b27e76351cff/657d2/mutify.webp 696w,\n/static/5dc25e603a1517582fc6b27e76351cff/e644e/mutify.webp 1044w,\n/static/5dc25e603a1517582fc6b27e76351cff/8daba/mutify.webp 1392w,\n/static/5dc25e603a1517582fc6b27e76351cff/2dc7d/mutify.webp 1890w"\n              sizes="(max-width: 696px) 100vw, 696px"\n              type="image/webp"\n            />\n          <source\n            srcset="/static/5dc25e603a1517582fc6b27e76351cff/88093/mutify.png 174w,\n/static/5dc25e603a1517582fc6b27e76351cff/91d18/mutify.png 348w,\n/static/5dc25e603a1517582fc6b27e76351cff/871fd/mutify.png 696w,\n/static/5dc25e603a1517582fc6b27e76351cff/4e07d/mutify.png 1044w,\n/static/5dc25e603a1517582fc6b27e76351cff/aeb15/mutify.png 1392w,\n/static/5dc25e603a1517582fc6b27e76351cff/9e653/mutify.png 1890w"\n            sizes="(max-width: 696px) 100vw, 696px"\n            type="image/png"\n          />\n          <img\n            class="gatsby-resp-image-image"\n            src="/static/5dc25e603a1517582fc6b27e76351cff/871fd/mutify.png"\n            alt="Mutify"\n            title=""\n            loading="lazy"\n            decoding="async"\n            style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;"\n          />\n        </picture>\n    </span>\n    <figcaption class="gatsby-resp-image-figcaption">Mutify</figcaption>\n  </figure>'}}),"\n",i.createElement(t.h2,{id:"from-open-source-to-paid-app"},i.createElement(t.a,{"aria-hidden":"true",tabIndex:"-1",href:"#from-open-source-to-paid-app"},i.createElement(t.span,{className:"icon icon-link"})),"From Open Source to Paid App"),"\n",i.createElement(t.p,null,"We’re pretty happy with open source in principle, so we initially developed the first version of the app as an open source project, investing in the costs ourselves. We released it and made some promotions, and got positive feedback, but also noticed some bugs. MacOS turned out to be more of a problem than we thought. Particular problems we faced include:"),"\n",i.createElement(t.ul,null,"\n",i.createElement(t.li,null,"problems with other apps attempting to control the mic"),"\n",i.createElement(t.li,null,"compatibility between different versions of MacOS"),"\n",i.createElement(t.li,null,"limitations put in place by Apple that needed careful investigation"),"\n"),"\n",i.createElement(t.p,null,"We on the app’s community regularly growing so that we could get some contributors able to help handle issues that arose. Unfortunately, this didn’t happen. From day one, all development was done by ourselves; open-source development on Swift turned out to be quite different than the JS or PHP communities, where you can rely on small bug fixes from outside devs. This lack of helpful community is a major weakness of MacOS development."),"\n",i.createElement(t.p,null,"We got 159 stars on Github, more than 8000 installations, and zero contributors. The app, however, still needed lot of work to complete, so we decided to rebuild it from scratch and change to a paid model to guarantee at least some support for future development and app improvements. That how Mut
1ify was born."),"\n",i.createElement(t.h2,{id:"mutify-features"},i.createElement(t.a,{"aria-hidden":"true",tabIndex:"-1",href:"#mutify-features"},i.createElement(t.span,{className:"icon icon-link"})),"Mutify Features"),"\n",i.createElement(t.h3,{id:"mute-and-unmute-microphone"},i.createElement(t.a,{"aria-hidden":"true",tabIndex:"-1",href:"#mute-and-unmute-microphone"},i.createElement(t.span,{className:"icon icon-link"})),"Mute and unmute microphone"),"\n",i.createElement(t.p,null,"Mute and unmute with a hotkey or touchbar icon available at all times."),"\n",i.createElement(t.h3,{id:"noise-level"},i.createElement(t.a,{"aria-hidden":"true",tabIndex:"-1",href:"#noise-level"},i.createElement(t.span,{className:"icon icon-link"})),"Noise level"),"\n",i.createElement(t.p,null,"Display the current ambient noise level, helping you track when you need to mute yourself."),"\n",i.createElement(t.span,{dangerouslySetInnerHTML:{__html:'<figure class="gatsby-resp-image-figure" style="">\n    <span\n      class="gatsby-resp-image-wrapper"\n      style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 696px; "\n    >
1\n      <span\n    class="gatsby-resp-image-background-image"\n    style="padding-bottom: 56.32183908045977%; position: relative; bottom: 0; left: 0; background-image: url(\'data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAALABQDASIAAhEBAxEB/8QAGAAAAgMAAAAAAAAAAAAAAAAAAAEDBAX/xAAVAQEBAAAAAAAAAAAAAAAAAAAAAv/aAAwDAQACEAMQAAAB04LyowEf/8QAGRAAAwADAAAAAAAAAAAAAAAAAQIDABAU/9oACAEBAAEFAqWnNumWKQ6gA7//xAAVEQEBAAAAAAAAAAAAAAAAAAAAEv/aAAgBAwEBPwFT/8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAgEBPwE//8QAHBAAAQQDAQAAAAAAAAAAAAAAAAECETEQEkGR/9oACAEBAAY/AtXTJ3wRyUpWf//EABoQAAMBAAMAAAAAAAAAAAAAAAABESExQXH/2gAIAQEAAT8hqDC4hL7LipKhJqP0iWRFP//aAAwDAQACAAMAAAAQUw//xAAXEQADAQAAAAAAAAAAAAAAAAAAARFR/9oACAEDAQE/EGoRh//EABYRAQEBAAAAAAAAAAAAAAAAAAABEf/aAAgBAgEBPxBlf//EABsQAQEAAgMBAAAAAAAAAAAAAAERACExQVHR/9oACAEBAAE/EJsockjj+t+9v7lgOQEZg1YexXLolfDBGhQOjP/Z\'); background-size: cover; display: block;"\n  ></span>\n  <picture>\n          <source\n              srcset="/static/689eee7d6357d53644658dc7c69d462b/09400/noise.webp 174w,\n/static/689eee7d6357d53644658dc7c69d462b/3266f/noise.webp 348w,\n/static/689eee7d6357d53644658dc7c69d462b/657d2/noise.webp 696w,\n/static/689eee7d6357d53644658dc7c69d462b/e644e/noise.webp 1044w,\n/static/689eee7d6357d53644658dc7c69d462b/8daba/noise.webp 1392w,\n/static/689eee7d6357d53644658dc7c69d462b/2dc7d/noise.webp 1890w"\n              sizes="(max-width: 696px) 100vw, 696px"\n              type="image/webp"\n            />\n          <source\n            srcset="/static/689eee7d6357d53644658dc7c69d462b/f52d2/noise.jpg 174w,\n/static/689eee7d6357d53644658dc7c69d462b/14ab8/noise.jpg 348w,\n/static/689eee7d6357d53644658dc7c69d462b/a4476/noise.jpg 696w,\n/static/689eee7d6357d53644658dc7c69d462b/4ef30/noise.jpg 1044w,\n/static/689eee7d6357d53644658dc7c69d462b/16454/noise.jpg 1392w,\n/static/689eee7d6357d53644658dc7c69d462b/783cc/noise.jpg 1890w"\n            sizes="(max-width: 696px) 100vw, 696px"\n            type="image/jpeg"\n          />\n          <img\n            class="gatsby-resp-image-image"\n            src="/static/689eee7d6357d53644658dc7c69d462b/a4476/noise.jpg"\n            alt="Noise level"\n            title=""\n            loading="lazy"\n            decoding="async"\n            style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;"\n          />\n        </picture>\n    </span>\n    <figcaption class="gatsby-resp-image-figcaption">Noise level</figcaption>\n  </figure>'}}),"\n",i.createElement(t.h3,{id:"variety-app-support"},i.createElement(t.a,{"aria-hidden":"true",tabIndex:"-1",href:"#variety-app-support"},i.createElement(t.span,{className:"icon icon-link"})),"Variety app support"),"\n",i.createElement(t.p,null,"Use it with Hangouts, Zoom, GoToMeeting, Skype, Telegram, etc. Different calls apps try to control the mic, but the app allows you to keep control."),"\n",i.createElement(t.span,{dangerouslySetInnerHTML:{__html:'<figure class="gatsby-resp-image-figure" style="">\n    <span\n      class="gatsby-resp-image-wrapper"\n      style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 696px; "\n    >
1\n      <span\n    class="gatsby-resp-image-background-image"\n    style="padding-bottom: 56.32183908045977%; position: relative; bottom: 0; left: 0; background-image: url(\'data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAALABQDASIAAhEBAxEB/8QAGAAAAwEBAAAAAAAAAAAAAAAAAAECAwX/xAAVAQEBAAAAAAAAAAAAAAAAAAAAAf/aAAwDAQACEAMQAAAB7a0aQUH/xAAYEAACAwAAAAAAAAAAAAAAAAAAEQEQMf/aAAgBAQABBQIQrjP/xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAEDAQE/AT//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAECAQE/AT//xAAUEAEAAAAAAAAAAAAAAAAAAAAg/9oACAEBAAY/Al//xAAbEAEAAQUBAAAAAAAAAAAAAAABABEhMUFhcf/aAAgBAQABPyEM0v2AC29QN/Y5J2CgJ//aAAwDAQACAAMAAAAQz/8A/8QAFREBAQAAAAAAAAAAAAAAAAAAABH/2gAIAQMBAT8QiP/EABYRAAMAAAAAAAAAAAAAAAAAAAABEf/aAAgBAgEBPxCsrP/EABoQAQEAAwEBAAAAAAAAAAAAAAERACFRcaH/2gAIAQEAAT8QGhIFtWPJhpp0et+52PWffiG43JcIQgaM/9k=\'); background-size: cover; display: block;"\n  ></span>\n  <picture>\n          <source\n              srcset="/static/11a11f1ab4d918b7b86b9eec56a34b11/09400/apps.webp 174w,\n/static/11a11f1ab4d918b7b86b9eec56a34b11/3266f/apps.webp 348w,\n/static/11a11f1ab4d918b7b86b9eec56a34b11/657d2/apps.webp 696w,\n/static/11a11f1ab4d918b7b86b9eec56a34b11/e644e/apps.webp 1044w,\n/static/11a11f1ab4d918b7b86b9eec56a34b11/8daba/apps.webp 1392w,\n/static/11a11f1ab4d918b7b86b9eec56a34b11/2dc7d/apps.webp 1890w"\n              sizes="(max-width: 696px) 100vw, 696px"\n              type="image/webp"\n            />\n          <source\n            srcset="/static/11a11f1ab4d918b7b86b9eec56a34b11/f52d2/apps.jpg 174w,\n/static/11a11f1ab4d918b7b86b9eec56a34b11/14ab8/apps.jpg 348w,\n/static/11a11f1ab4d918b7b86b9eec56a34b11/a4476/apps.jpg 696w,\n/static/11a11f1ab4d918b7b86b9eec56a34b11/4ef30/apps.jpg 1044w,\n/static/11a11f1ab4d918b7b86b9eec56a34b11/16454/apps.jpg 1392w,\n/static/11a11f1ab4d918b7b86b9eec56a34b11/783cc/apps.jpg 1890w"\n            sizes="(max-width: 696px) 100vw, 696px"\n            type="image/jpeg"\n          />\n          <img\n            class="gatsby-resp-image-image"\n            src="/static/11a11f1ab4d918b7b86b9eec56a34b11/a4476/apps.jpg"\n            alt="Variety app support"\n            title=""\n            loading="lazy"\n            decoding="async"\n            style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;"\n          />\n        </picture>\n    </span>\n    <figcaption class="gatsby-resp-image-figcaption">Variety app support</figcaption>\n  </figure>'}}),"\n",i.createElement(t.h2,{id:"difficulties-of-macos-app-development"},i.createElement(t.a,{"aria-hidden":"true",tabIndex:"-1",href:"#difficulties-of-macos-app-development"},i.createElement(t.span,{className:"icon icon-link"})),"Difficulties of MacOs App Development"),"\n",i.createElement(t.p,null,"We encountered problems at almost every step of development. It was hard to build a fully customized UI, as we didn’t want to use standard components. When we developed a method of low-level muting apps, some apps unmuted without user input or notification. For example, when attempting to mute a microphone and showing it disabled at all in MacOS settings, GoToMeeting or GoToWebinar simply unmuted the mic again when detecting it had been muted. After discussing this with the support team for these apps, they insisted that this is correct behaviour. From our perspective, this is dangerous, since it suggests that meeting apps just want to listen you all of the time. We had to find complicated workarounds to ensure that the mic was always muted when we wanted it to be."),"\n",i.createElement(t.p,null,"Since the day one, we thought that Apple would extend the functionality of the touchbar API, but there are no changes as yet. Touchbar API has a lot of limitations that prevent developers using it to build potentially useful software."),"\n",i.createElement(t.p,null,"For example:"),"\n",i.createElement(t.ul,null,"\n",i.createElement(t.li,null,"Third party apps can’t be displayed in the list of actions for the touchbar in the “Cutomize Touchbar” settings;"),"\n",i.createElement(t.li,null,"You only could add one third-party app icon that is always displayed in the touchbar together with Apple developed tools;"),"\n"),"\n",i.createElement(t.p,null,"Those limitations significantly reduce the possible options for extending touchbar functionality. That’s why we also support mute by hotkey functionality. Even for a simple, one-action app, you need time to build features like the following:"),"\n",i.createElement(t.ul,null,"\n",i.createElement(t.li,null,"Onboarding screens"),"\n",i.createElement(t.li,null,"Update functionality"),"\n",i.createElement(t.li,null,"Integrated payment functions"),"\n",i.createElement(t.li,null,"Open at login functions"),"\n",i.createElement(t.li,null,"Hotkey support"),"\n",i.createElement(t.li,null,"Website"),"\n"),"\n",i.createElement(t.h2,{id:"effort--quality"},i.createElement(t.a,{"aria-hidden":"true",tabIndex:"-1",href:"#effort--quality"},i.createElement(t.span,{className:"icon icon-link"})),"Effort = Quality"),"\n",i.createElement(t.p,null,"The main lesson we learned from this project is that doing something well always means a lot of hard work from different people with different skills, including some that don’t always relate to the primary functionality of the app. In the end, however positive feedback from our customers and personal satisfaction of using using our own application made it feel worth the effort."),"\n",i.createElement(t.p,null,"Support us on ",i.createElement(t.a,{href:"https://www.producthunt.com/posts/mutify"},"Product Hunt")," for a 30% discount! Mutify also has a seven-day free trial, so feel free to test it out and we hope you enjoy!"))}var o=function(e){void 0===e&&(e={});const{wrapper:t}=Object.assign({},(0,n.RP)(),e.components);return t?i.createElement(t,e,i.createElement(A,e)):A(e)},s=a(2532),l=a(1021),c=a(545),r=a(9072),p=a(3669),d=a(9063),u=a(352),m=a(84);const f=e=>{let{data:{mdx:{author:t,frontmatter:a,fields:{slug:n}},allMdx:{nodes:A}},location:o,pageContext:{videoCovers:s},children:u}=e;return i.createElement(d.A,{headerTheme:"black",headerShowThemeButton:!0},i.createElement("article",{className:"safe-paddings pt-32 sm:pt-24"},i.createElement("div",{className:"container"},i.createElement("div",{className:"relative mx-auto max-w-[696px] xl:mx-0 xl:flex xl:max-w-none xl:justify-center xl:space-x-20 lg:space-x-8 md:block md:space-x-0"},i.createElement("div",{className:"xl:max-w-[696px] lg:max-w-[626px] md:max-w-none"},i.createElement(c.A,Object.assign({},a,{slug:n})),i.createElement(l.A,{content:u,videoCovers:s})),i.createElement(r.A,{author:t,readMorePosts:A,socialShareUrl:o.href})))),i.createElement(p.A,{withTopMargin:!0}))};function h(e){return i.createElement(f,e,i.createElement(o,e))}const b=e=>{let{data:{mdx:{frontmatter:{title:t,summary:a,ogImage:n}}}}=e;const A=(0,s.d)(n);return i.createElement(u.A,m.A.blogPost({title:t,description:a,ogImage:A}))}}}]);
2//# sourceMappingURL=component---src-templates-blog-post-jsx-content-file-path-content-posts-2019-04-25-the-c
2hallenges-of-building-own-macos-app-index-md-d88cd5a9ce934385a91b.js.map

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.