CINXE.COM
List of macOS apps built with Catalyst — RoaringApps
<!DOCTYPE html> <html lang="en" ng-app="RoaringApps"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> <meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="description" content="See which Mac apps are built with Catalyst! RoaringApps maintains a list of macOS apps built with Apple's Catalyst framework. Catalyst allows developers to release their iOS apps as native Mac apps."> <meta name="keywords" content="mac,macos,mac os x,mojave,catalina,big sur,monterey,apple silicon,arm macs,m1 macs,catalyst apps,32-bit apps,app,application,application compatibility,apple,roaringapps,mac app store,table,windows,ios,ios 14,ios 15"> <title> List of macOS apps built with Catalyst — RoaringApps </title> <!-- Stylesheets --> <link rel="stylesheet" href="/../assets/css/site-2-7-1.css"> <!-- Webfonts --> <link href='https://fonts.googleapis.com/css?family=Lato:100,400,700,100italic,400italic,700italic|Rancho|Merriweather+Sans:400,300,300italic,400italic,700,700italic|Cookie' rel='stylesheet' type='text/css'> <!--[if lt IE 9]> <script src="/../assets/js/ie8-responsive-file-warning.js"></script> <![endif]--> <!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries --> <!--[if lt IE 9]> <script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script> <script src="https://oss.maxcdn.com/libs/respond.js/1.3.0/respond.min.js"></script> <![endif]--> <!-- Favicons --> <link rel="shortcut icon" href="/assets/ico/favicon.png"> <link rel="shortcut icon" href="/favicon.ico"> <!-- Angular $location.html5Mode = true requires this --> <base href="/"> <script async src="https://www.googletagmanager.com/gtag/js?id=G-3G6DX7LY1W"></script> <script> window.dataLayer = window.dataLayer || []; function gtag() { dataLayer.push(arguments); } gtag('js', new Date()); gtag('config', 'G-3G6DX7LY1W'); </script> <script async src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script> <script type="text/javascript"> (adsbygoogle = window.adsbygoogle || []).push({ google_ad_client: "ca-pub-4932023458712014", enable_page_level_ads: true }); </script> <script src="/../assets/js/vendor/modernizr.js" data-cfasync='true'></script> <!-- First input delay polyfill - used by Firebase Performance Monitoring. Ref: https://firebase.google.com/docs/perf-mon/get-started-web Ref2: https://github.com/GoogleChromeLabs/first-input-delay --> <script type="text/javascript"> ! function(n, e) { var t, o, i, c = [], f = { passive: !0, capture: !0 }, r = new Date, a = "pointerup", u = "pointercancel"; function p(n, c) { t || (t = c, o = n, i = new Date, w(e), s()) } function s() { o >= 0 && o < i - r && (c.forEach(function(n) { n(o, t) }), c = []) } function l(t) { if (t.cancelable) { var o = (t.timeStamp > 1e12 ? new Date : performance.now()) - t.timeStamp; "pointerdown" == t.type ? function(t, o) { function i() { p(t, o), r() } function c() { r() } function r() { e(a, i, f), e(u, c, f) } n(a, i, f), n(u, c, f) }(o, t) : p(o, t) } } function w(n) { ["click", "mousedown", "keydown", "touchstart", "pointerdown"].forEach(function(e) { n(e, l, f) }) } w(n), self.perfMetrics = self.perfMetrics || {}, self.perfMetrics.onFirstInputDelay = function(n) { c.push(n), s() } }(addEventListener, removeEventListener); </script> <!-- Sentry.io error monitoring --> <script src="https://js.sentry-cdn.com/9bccfd17b53521da4d6c21b201931d8c.min.js" crossorigin="anonymous"></script> <script> window.ENVIRONMENT = 'production'; </script> </head> <body class="{{bodyClass}}" ng-cloak> <a class="sr-only" href="#content">Skip to main content</a> <div class="wrapper"> <!-- Navigation component --> <header class="navbar navbar-fixed-top " role="banner" ng-controller="HeaderCtrl"> <div class="container"> <div class="navbar-header"> <button class="navbar-toggle collapsed" type="button" data-toggle="collapse" data-target=".bs-navbar-collapse"> <span class="sr-only">Toggle navigation</span> <svg class="icon"> <use xlink:href="/assets/svg/icons.svg#shape-chevron-down" /> </svg> </button> <a href="/" class="navbar-brand">RoaringApps</a> </div> <nav class="collapse navbar-collapse bs-navbar-collapse" role="navigation"> <ul class="nav navbar-nav navbar-centre"> <li> <a href="/apps">Apps</a> </li> <li class="dropdown main-dropdown"> <a href="#" class="dropdown-toggle" data-toggle="dropdown">Collections</a> <ul class="dropdown-menu" role="menu"> <li> <a href="/collections/list-of-apple-silicon-native-apps">Apps ready for Apple Silicon</a> </li> <li> <a href="/collections/list-of-native-windows-arm-apps">Apps native on Windows ARM</a> </li> <li> <a href="/collections/list-of-32-bit-macos-apps">macOS 32-bit apps</a> </li> <li> <a href="/collections/discontinued-macos-ios-apps">Discontinued apps</a> </li> <li> <a href="/app-collection/ios-carplay-apps">iOS CarPlay apps</a> </li> <li> <a href="/app-collections">More collections...</a> </li> </ul> </li> <li> <a href="/mac-app">Download</a> </li> <!--<li> <a href="/blog">Blog</a> </li>--> <li> <a href="/about">About</a> </li> <li> <a href="/app/+">Add App</a> </li> </ul> <ul class="nav navbar-nav navbar-right"> <li> <a href="#" data-toggle="modal" data-target="#modal-search" class="with-icon"> <span class="sr-only">Search applications</span> <svg class="icon fav-icon-outline"> <use xlink:href="/assets/svg/icons.svg#shape-magnifying-glass" /> </svg> </a> </li> <li class="hidden-sm"> <a href="#" data-toggle="modal" data-target="#modal-feedback">Feedback</a> </li> <li class="dropdown account-dropdown" ng-if="user"> <a href="#" class="dropdown-toggle" data-toggle="dropdown">{{user.username}}</a> <ul class="dropdown-menu pull-right" role="menu"> <li> <a href="/account">Account</a> </li> <li> <a href="/account/watching">Notifications</a> </li> <li ng-if="user.role == 'admin'" class="divider"></li> <li ng-if="user.role == 'admin'"> <a href="/admin/dashboard">Admin dashboard</a> </li> <li ng-if="user.role == 'admin'"> <a href="/admin/comments">Comments review</a> </li> <li ng-if="user.role == 'admin'"> <a href="/admin/screenshots">Screenshot review</a> </li> <li ng-if="user.role == 'admin'"> <a href="/admin/tags">Tag manager</a> </li> <li ng-if="user.role == 'admin'"> <a href="/admin/itunes-importer">iTunes Importer</a> </li> <li ng-if="user.role == 'admin'" class="divider"></li> <li> <a href="/logout" ng-click="logout($event)">Log out</a> </li> </ul> </li> <li ng-if="!user"> <a href="#" data-toggle="modal" data-target="#modal-register" class="account-register">Register</a> </li> <li ng-if="!user"> <a href="#" data-toggle="modal" data-target="#modal-signin" class="account-signin">Sign in</a> </li> </ul> </nav> </div> </header> <section id="main" ng-controller="StaticAppCollectionCtrl" ng-class="{'overlay-in': state.overlayIn }"> <div class="container" ng-hide="state.loading"> <div class="row"> <div class="col-xs-12 col-sm-10 col-sm-offset-1 col-md-8 col-md-offset-2"> <!-- <ul class="breadcrumb"> <li>One</li> <li>Two</li> <li>Three</li> </ul> --> <div class="page-header underline transparent pushdown"> <h1>macOS apps built with Catalyst</h1> <!-- <div class="action-items"> <div class="dropdown app-more-dropdown"> <a href="" class="dropdown-toggle" data-toggle="dropdown"> <svg class="icon"> <use xlink:href="/assets/svg/icons.svg#shape-chevron-small-down" /> </svg> </a> <ul class="dropdown-menu pull-right"> <li> <a href="#" ng-click="state.editing = !state.editing">Edit collection</a> </li> </ul> </div> </div> /.action-items --> </div> <div class="app-header-meta"> <div class="meta-right"> <span>Written by <a href="/u/bryce">bryce</a> · 1 September, 2019</span> </div> </div> </div> </div> <!-- Content --> <div class="row"> <div class="col-xs-12 col-md-10 col-md-offset-1 col-lg-8 col-lg-offset-2"> <div class="border-box"> <p><strong>Catalyst</strong> is a development framework from Apple that allows developers to build and release their existing (or new) <a href="https://developer.apple.com/ipad-apps-for-mac/">iOS apps for macOS</a> .</p> <p>Commencing with <a href="https://www.apple.com/macos/catalina-preview/">macOS Catalina</a>, developers can use tools in Xcode 11 to create a Mac version of an iPad app.</p> <p>Apps built with Catalyst will run natively on macOS, using the same frameworks and resources as native Mac apps. They'll be available in the Mac App Store or via direct download, depending on the developer's preference.</p> <p>More reading about Catalyst:</p> <ul> <li> <a href="https://developer.apple.com/ipad-apps-for-mac/">iPads apps for Mac – Apple Developer</a> </li> <li> <a href="https://arstechnica.com/gadgets/2019/07/catalyst-deep-dive-the-future-of-mac-software-according-to-apple-and-devs/">Catalyst deep dive – Ars Technica</a> </li> <li> <a href="https://www.imore.com/ipad-apps-mac-project-catalyst-explained">Project Catalyst explained – iMore</a> </li> </ul> <p>Below is a list of apps known to currently be built with Catalyst. Expect the list to grow over the coming months as thousands of iOS developers become familiar with the Catalyst project and release their iPad apps for macOS.</p> </div> </div> <h5 class="row-header col-xs-12 col-md-10 col-md-offset-1 col-lg-8 col-lg-offset-2"> <span>Catalyst Applications</span> </h5> <div class="col-xs-12 col-md-10 col-md-offset-1 col-lg-8 col-lg-offset-2"> <div class="border-box"> <p ng-if="apps === null">Loading...</p> <p ng-if="apps.$value === null || apps.length == 0">No applications in this collection yet.</p> <div class="static-app-table-container"> <table id="app-collection" class="table table-striped app-collection-table"></table> </div> </div> </div> </div> </div> </section> <!-- Footer --> <footer role="contentinfo"> <div class="container"> <div class="row"> <div class="col-md-6"> <p> <i>⚒</i>by Bryce Cameron since 10.7. <!-- <a class="bmc-button" target="_blank" href="https://www.buymeacoffee.com/roaringapps?ref=rawf" style="align-items: center;"><span>Buy me a coffee</span> <img src="https://cdn.buymeacoffee.com/buttons/bmc-new-btn-logo.svg" alt="Buy me a coffee"></a> --> </p> </div> <div class="col-md-6"> <p class="pull-right"> <a href="/">Home</a> · <a href="/about">About</a> · <a href="/newsletter/join">Newsletter</a> · <a href="/help/contribute-to-roaringapps">Contribute</a> · <a href="/contact">Contact</a> · <a href="/account">Account</a> · <a href="/legal">Legal</a> </p> </div> </div><!-- /.row --> </div> </footer> <script data-name="BMC-Widget" data-cfasync="false" src="https://cdnjs.buymeacoffee.com/1.0.0/widget.prod.min.js" data-id="roaringapps" data-description="Support me on Buy me a coffee!" data-message="" data-color="#FF5F5F" data-position="Right" data-x_margin="18" data-y_margin="18"></script> </div> <!-- Modals --> <section class="the-modals" ng-controller="ModalCtrl"> <!-- Sign In --> <div class="modal fade narrow" id="modal-signin" tabindex="-1" role="dialog" aria-labelledby="modal-label-signin" aria-hidden="true"> <div class="modal-dialog"> <p class="modal-outside-meta modal-msg" ng-if="signinModalMsg">{{signinModalMsg}}</p> <div class="modal-content"> <div class="modal-body"> <form id="form-signin" ng-submit="login.submit()"> <div class="gravatar"></div> <input type="email" name="signin-email" ng-model="form.login.email" placeholder="Email address" /> <input type="password" name="signin-password" ng-model="form.login.password" placeholder="Password" /> <button class="btn btn-action" action="submit" name="signin-submit" ng-hide="login.submitting"> <span>Sign in</span> </button> <div class="btn btn-action modal-button-loader" ng-show="login.submitting"> <div class="spinner spinner-three-dots faster"> <div class="bounce1"></div> <div class="bounce2"></div> <div class="bounce3"></div> </div> </div> </form> </div> </div><!-- /.modal-content --> <p class="modal-outside-meta"> <a href="/account/forgot">Forgot?</a> <a class="pull-right" href="#" data-toggle="modal" data-target="#modal-register"><strong>Create an account</strong> </a> </p> </div> </div> <!-- Register / Create account --> <div class="modal fade narrow" id="modal-register" tabindex="-1" role="dialog" aria-labelledby="modal-label-register" aria-hidden="true"> <div class="modal-dialog"> <div class="modal-content"> <div class="modal-body"> <form id="form-register" ng-submit="register.submit()"> <div class="gravatar"></div> <input type="email" name="register-email" ng-model="form.register.email" placeholder="Email address" /> <input type="text" name="register-username" ng-model="form.register.username" placeholder="Username" /> <input type="password" name="register-password" ng-model="form.register.password" placeholder="Password" /> <button class="btn btn-action" action="submit" name="register-submit" ng-hide="register.submitting"> <span>Create account</span> </button> <div class="btn btn-action modal-button-loader" ng-show="register.submitting"> <div class="spinner spinner-three-dots faster"> <div class="bounce1"></div> <div class="bounce2"></div> <div class="bounce3"></div> </div> </div> </form> </div> </div><!-- /.modal-content --> <p class="modal-outside-meta">{{register.errors.join(' ')}}</p> </div> </div> <!-- Search --> <div class="modal fade search-modal" id="modal-search" tabindex="-1" role="dialog" aria-labelledby="modal-label-search" aria-hidden="true"> <div class="modal-dialog"> <div class="modal-content"> <div class="modal-body"> <form id="form-search"> <input type="search" id="search-input" name="search" ng-model="form.search.query" placeholder="Search applications" autocomplete="off" /> <span class="search-result-count" ng-show="search.results.length > 0">{{search.results.length}} apps</span> </form> <p class="search-msg" ng-show="search.searching">Searching...</p> <p class="search-msg" ng-show="search.empty">No results</p> <ul class="search-results"> <li class="result" ng-repeat="app in search.results | orderBy:'-_searchRank'"> <a href="/app/{{app.slug}}"> <img ng-src="{{app.icon}}" alt="{{app.icon ? app.name + ' icon' : 'No icon'}}" class="{{app.icon ? 'search-result-has-icon' : 'search-result-no-icon'}}" onerror="this.style.display='none'" /> <strong>{{app.name}}</strong> <span class="dev">{{app.developer}}</span> </a> </li> </ul> </div> </div><!-- /.modal-content --> <p class="modal-outside-meta">{{register.errors.join(' ')}}</p> </div> </div> <!-- Moderate --> <div class="modal fade" id="modal-moderate" tabindex="-1" role="dialog" aria-labelledby="modal-label-moderate" aria-hidden="true"> <div class="modal-dialog"> <div class="modal-content"> <div class="modal-header"> <h4>Moderator control panel</h4> </div> <div class="modal-body"> <form id="form-moderate"> <div class="row"> <div class="col-xs-12 col-sm-6"> <div class="form-group"> <label for="moderate-app-name">Application</label> <input type="text" name="moderate-app-name" id="moderate-app-name" ng-model="selectedApp.name" disabled /> </div> </div> <div class="col-xs-12 col-sm-6"> <div class="form-group"> <label for="moderate-app-slug">Slug</label> <input type="text" name="moderate-app-slug" id="moderate-app-slug" ng-model="selectedApp.slug" disabled /> </div> </div> <div class="col-xs-12 col-sm-6"> <div class="form-group"> <label for="moderate-app-developer">Developer</label> <input type="text" name="moderate-app-developer" id="moderate-app-developer" ng-model="selectedApp.developer" disabled /> </div> </div> <div class="col-xs-12 col-sm-6"> <div class="form-group"> <label for="moderate-app-url">URL</label> <input type="text" name="moderate-app-url" id="moderate-app-url" ng-model="selectedApp.url" disabled /> </div> </div> </div> <div class="form-group"> <p ng-if="!selectedApp.statuses">This application has no status reports.</p> </div> <div class="form-group"> <button class="btn btn-outline btn-danger" ng-click="moderate.delete(selectedApp.slug)">Delete app</button> <button class="btn btn-outline" ng-click="moderate.merge.chooseTo(selectedApp.slug)">Merge with...</button> <button class="btn btn-outline" ng-click="moderate.appCollection.add(selectedApp.slug)">Add to collection...</button> <button class="btn btn-outline">Update</button> </div> </form> </div> </div><!-- /.modal-content --> <p class="modal-outside-meta">For use only by approved RoaringApps moderators.</p> </div> </div> <!-- Feedback --> <div class="modal fade" id="modal-feedback" tabindex="-1" role="dialog" aria-labelledby="modal-label-feedback" aria-hidden="true"> <div class="modal-dialog"> <div class="modal-content"> <div class="modal-header"> <h4>Submit Feedback</h4> </div> <div class="modal-body"> <p>I develop RoaringApps in my (rather limited) spare time, so sometimes I miss bugs here and there. If you notice something not quite working properly, or have an idea for the site, I'd love to hear from you.</p> <form id="form-feedback" name="feedbackForm" ng-submit="feedback.submit(feedbackForm.$valid)" novalidate> <!-- novalidate disables HTML5 validation, so we can use the angular validation --> <div class="row"> <div class="col-xs-12 col-sm-6"> <div class="form-group"> <label for="feedback-name">Name</label> <input type="text" name="feedback-name" id="feedback-name" ng-model="form.feedback.name" required /> </div> </div> <div class="col-xs-12 col-sm-6"> <div class="form-group"> <label for="feedback-email">Email (optional)</label> <input type="email" name="feedback-email" id="feedback-email" ng-model="form.feedback.email" /> </div> </div> </div> <div class="form-group"> <label for="feedback-comment">Comment</label> <textarea id="feedback-comment" ng-model="form.feedback.comment" required></textarea> </div> <div class="form-group form-action-area"> <input type="submit" value="Send feedback" class="btn btn-outline" ng-disabled="feedbackForm.$invalid" /> </div> <div class="form-group"> <p class="msg error" ng-if="feedback.errorMsg">{{feedback.errorMsg}}</p> <p class="msg success" ng-if="feedback.successMsg">{{feedback.successMsg}}</p> </div> </form> </div> </div><!-- /.modal-content --> </div> </div> <!-- Report comment --> <div class="modal fade" id="modal-report-comment" tabindex="-1" role="dialog" aria-labelledby="modal-label-report-comment" aria-hidden="true"> <div class="modal-dialog"> <div class="modal-content"> <div class="modal-header"> <h4>Report comment</h4> </div> <div class="modal-body"> <p>Report this comment to help the moderators identify items that require attention.</p> <form id="form-report-comment" name="reportCommentForm" ng-submit="reportComment.submit(reportCommentForm.$valid)" novalidate> <!-- novalidate disables HTML5 validation, so we can use the angular validation --> <div class="row"> <div class="col-xs-12"> <div class="form-group"> <label for="report-comment-reason">Reason</label> <select name="report-comment-reason" id="report-comment-reason" ng-model="form.reportComment.reason" required> <option>Invalid advice</option> <option>Illegal/inappropriate</option> <option>Off-topic</option> <option>Personal attack</option> <option>Spam</option> <option>Other</option> </select> </div> </div> <div class="col-xs-12"> <div class="form-group"> <label for="report-comment-description">Description (optional)</label> <textarea id="report-comment-description" ng-model="form.reportComment.description"></textarea> </div> </div> <div class="col-xs-12"> <div class="form-group form-action-area"> <input type="submit" value="Submit report" class="btn btn-outline" ng-disabled="reportCommentForm.$invalid" /> </div> <div class="form-group"> <p class="msg error" ng-if="reportComment.errorMsg">{{reportComment.errorMsg}}</p> <p class="msg success" ng-if="reportComment.successMsg">{{reportComment.successMsg}}</p> </div> </div> </div><!-- /.row --> </form> </div> </div><!-- /.modal-content --> </div> </div><!-- /.modal (report comment) --> </section> <!-- JS and analytics only. --> <script src="/../assets/js/production-2-7-1.js"></script> <script> if (typeof lucide !== undefined) lucide.createIcons(); </script> </body> </html>