<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <id>https://docs.pushmark.app/blog</id>
    <title>Pushmark Docs Blog</title>
    <updated>2026-04-09T00:00:00.000Z</updated>
    <generator>https://github.com/jpmonette/feed</generator>
    <link rel="alternate" href="https://docs.pushmark.app/blog"/>
    <subtitle>Pushmark Docs Blog</subtitle>
    <icon>https://docs.pushmark.app/img/pushmark-icon.svg</icon>
    <entry>
        <title type="html"><![CDATA[Get Push Notifications for GitHub Events on Your iPhone]]></title>
        <id>https://docs.pushmark.app/blog/github-events-push-notifications</id>
        <link href="https://docs.pushmark.app/blog/github-events-push-notifications"/>
        <updated>2026-04-09T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Use GitHub Actions and Pushmark to send yourself real-time iPhone notifications for deploys, build failures, PR merges, and more — no server required.]]></summary>
        <content type="html"><![CDATA[<p>Your deploy just finished. Or failed. You'll find out whenever you next open your laptop and check the Actions tab. There's a better way.</p>
<h2 class="anchor anchorTargetStickyNavbar_yIpS" id="the-idea">The idea<a href="https://docs.pushmark.app/blog/github-events-push-notifications#the-idea" class="hash-link" aria-label="Direct link to The idea" title="Direct link to The idea" translate="no">​</a></h2>
<p>GitHub Actions can run a <code>curl</code> command. Pushmark receives that request and sends a push notification to your iPhone in seconds. No server, no APNs certificates, no notification infrastructure to maintain — just a few lines of YAML and a free Pushmark account.</p>
<h2 class="anchor anchorTargetStickyNavbar_yIpS" id="deploy-notifications">Deploy notifications<a href="https://docs.pushmark.app/blog/github-events-push-notifications#deploy-notifications" class="hash-link" aria-label="Direct link to Deploy notifications" title="Direct link to Deploy notifications" translate="no">​</a></h2>
<p>Get notified the moment a deployment succeeds. Add this workflow to your repository:</p>
<div class="language-yaml codeBlockContainer_huE5 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_oko_"><pre tabindex="0" class="prism-code language-yaml codeBlock_BBgU thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_t9f9"><span class="token-line" style="color:#F8F8F2"><span class="token key atrule">name</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> Notify deploy</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token key atrule">on</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token key atrule">check_run</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token key atrule">types</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token plain">completed</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token key atrule">jobs</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token key atrule">notify</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token key atrule">if</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> github.event.check_run.conclusion == 'success'</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token key atrule">runs-on</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> ubuntu</span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain">latest</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token key atrule">steps</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> </span><span class="token key atrule">name</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> Send Pushmark notification</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token key atrule">run</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">|</span><span class="token scalar string" style="color:rgb(255, 121, 198)"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token scalar string" style="color:rgb(255, 121, 198)">          curl -X POST "https://api.pushmark.app/YOUR_CHANNEL_HASH" \</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token scalar string" style="color:rgb(255, 121, 198)">            -H "Content-Type: application/json" \</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token scalar string" style="color:rgb(255, 121, 198)">            -d '{</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token scalar string" style="color:rgb(255, 121, 198)">              "type": "log",</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token scalar string" style="color:rgb(255, 121, 198)">              "message": {</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token scalar string" style="color:rgb(255, 121, 198)">                "status": "${{ github.event.check_run.conclusion }}",</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token scalar string" style="color:rgb(255, 121, 198)">                "context": "${{ github.event.check_run.name }}",</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token scalar string" style="color:rgb(255, 121, 198)">                "url": "${{ github.event.check_run.html_url }}",</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token scalar string" style="color:rgb(255, 121, 198)">                "commit": "${{ github.event.check_run.head_sha }}",</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token scalar string" style="color:rgb(255, 121, 198)">                "triggered_by": "${{ github.event.sender.login }}"</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token scalar string" style="color:rgb(255, 121, 198)">              }</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token scalar string" style="color:rgb(255, 121, 198)">            }'</span><br></span></code></pre></div></div>
<p>Replace <code>YOUR_CHANNEL_HASH</code> with the hash from your Pushmark channel page.</p>
<h2 class="anchor anchorTargetStickyNavbar_yIpS" id="build-failure-alerts">Build failure alerts<a href="https://docs.pushmark.app/blog/github-events-push-notifications#build-failure-alerts" class="hash-link" aria-label="Direct link to Build failure alerts" title="Direct link to Build failure alerts" translate="no">​</a></h2>
<p>The most valuable notification is the one that wakes you up when something breaks. Use <code>type: "error"</code> to make it stand out:</p>
<div class="language-yaml codeBlockContainer_huE5 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_oko_"><pre tabindex="0" class="prism-code language-yaml codeBlock_BBgU thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_t9f9"><span class="token-line" style="color:#F8F8F2"><span class="token key atrule">name</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> Notify build failure</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token key atrule">on</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token key atrule">check_run</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token key atrule">types</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token plain">completed</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token key atrule">jobs</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token key atrule">notify</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token key atrule">if</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> github.event.check_run.conclusion == 'failure'</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token key atrule">runs-on</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> ubuntu</span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain">latest</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token key atrule">steps</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> </span><span class="token key atrule">name</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> Send Pushmark notification</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token key atrule">run</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">|</span><span class="token scalar string" style="color:rgb(255, 121, 198)"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token scalar string" style="color:rgb(255, 121, 198)">          curl -X POST "https://api.pushmark.app/YOUR_CHANNEL_HASH" \</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token scalar string" style="color:rgb(255, 121, 198)">            -H "Content-Type: application/json" \</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token scalar string" style="color:rgb(255, 121, 198)">            -d '{</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token scalar string" style="color:rgb(255, 121, 198)">              "type": "error",</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token scalar string" style="color:rgb(255, 121, 198)">              "message": {</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token scalar string" style="color:rgb(255, 121, 198)">                "status": "failed",</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token scalar string" style="color:rgb(255, 121, 198)">                "check": "${{ github.event.check_run.name }}",</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token scalar string" style="color:rgb(255, 121, 198)">                "url": "${{ github.event.check_run.html_url }}",</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token scalar string" style="color:rgb(255, 121, 198)">                "commit": "${{ github.event.check_run.head_sha }}",</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token scalar string" style="color:rgb(255, 121, 198)">                "triggered_by": "${{ github.event.sender.login }}"</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token scalar string" style="color:rgb(255, 121, 198)">              }</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token scalar string" style="color:rgb(255, 121, 198)">            }'</span><br></span></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_yIpS" id="pr-merge-notifications">PR merge notifications<a href="https://docs.pushmark.app/blog/github-events-push-notifications#pr-merge-notifications" class="hash-link" aria-label="Direct link to PR merge notifications" title="Direct link to PR merge notifications" translate="no">​</a></h2>
<p>Know when a pull request lands on your main branch without watching the repository:</p>
<div class="language-yaml codeBlockContainer_huE5 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_oko_"><pre tabindex="0" class="prism-code language-yaml codeBlock_BBgU thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_t9f9"><span class="token-line" style="color:#F8F8F2"><span class="token key atrule">name</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> Notify PR merged</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token key atrule">on</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token key atrule">pull_request</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token key atrule">types</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token plain">closed</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token key atrule">branches</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token plain">main</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token key atrule">jobs</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token key atrule">notify</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token key atrule">if</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> github.event.pull_request.merged == true</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token key atrule">runs-on</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> ubuntu</span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain">latest</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token key atrule">steps</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> </span><span class="token key atrule">name</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> Send Pushmark notification</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token key atrule">run</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">|</span><span class="token scalar string" style="color:rgb(255, 121, 198)"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token scalar string" style="color:rgb(255, 121, 198)">          curl -X POST "https://api.pushmark.app/YOUR_CHANNEL_HASH" \</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token scalar string" style="color:rgb(255, 121, 198)">            -H "Content-Type: application/json" \</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token scalar string" style="color:rgb(255, 121, 198)">            -d '{</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token scalar string" style="color:rgb(255, 121, 198)">              "type": "success",</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token scalar string" style="color:rgb(255, 121, 198)">              "message": {</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token scalar string" style="color:rgb(255, 121, 198)">                "pr": "${{ github.event.pull_request.title }}",</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token scalar string" style="color:rgb(255, 121, 198)">                "merged_by": "${{ github.event.pull_request.merged_by.login }}",</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token scalar string" style="color:rgb(255, 121, 198)">                "branch": "${{ github.event.pull_request.head.ref }}",</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token scalar string" style="color:rgb(255, 121, 198)">                "url": "${{ github.event.pull_request.html_url }}"</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token scalar string" style="color:rgb(255, 121, 198)">              }</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token scalar string" style="color:rgb(255, 121, 198)">            }'</span><br></span></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_yIpS" id="setup">Setup<a href="https://docs.pushmark.app/blog/github-events-push-notifications#setup" class="hash-link" aria-label="Direct link to Setup" title="Direct link to Setup" translate="no">​</a></h2>
<ol>
<li class="">Download the Pushmark app and create a channel — give it a name like "GitHub alerts"</li>
<li class="">Copy the channel hash from the channel detail page</li>
<li class="">Add the workflow YAML to <code>.github/workflows/</code> in your repository</li>
<li class="">Replace <code>YOUR_CHANNEL_HASH</code> with your channel hash</li>
</ol>
<p>The next time a deploy finishes or a build breaks, you'll feel your phone buzz before you've switched windows.</p>
<h2 class="anchor anchorTargetStickyNavbar_yIpS" id="why-pushmark">Why Pushmark<a href="https://docs.pushmark.app/blog/github-events-push-notifications#why-pushmark" class="hash-link" aria-label="Direct link to Why Pushmark" title="Direct link to Why Pushmark" translate="no">​</a></h2>
<p>Sending a GitHub notification to your iPhone normally means: configuring email alerts (noisy), setting up Slack (another tool), or building a webhook receiver with APNs credentials (real infrastructure). This pattern skips all of that. Download the app, create a channel, and you're done. Pushmark handles the APNs side. GitHub Actions handles the trigger. You just write a <code>curl</code> command.</p>
<p>See the <a class="" href="https://docs.pushmark.app/">Getting Started guide</a> for the full API reference and payload options.</p>]]></content>
        <category label="github" term="github"/>
        <category label="github-actions" term="github-actions"/>
        <category label="ci-cd" term="ci-cd"/>
        <category label="push-notifications" term="push-notifications"/>
        <category label="devops" term="devops"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Get Notified the Moment Someone Installs Your SwiftUI App]]></title>
        <id>https://docs.pushmark.app/blog/ios-app-install-notifications</id>
        <link href="https://docs.pushmark.app/blog/ios-app-install-notifications"/>
        <updated>2026-04-09T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[A lightweight pattern for sending yourself a real-time push notification on first SwiftUI app launch — no backend, no APNs certificates.]]></summary>
        <content type="html"><![CDATA[<p>Your analytics dashboard will tell you how many installs you got — eventually. You'll check it tomorrow morning, or maybe the day after, and see a number. That number will have no emotional weight.</p>
<p>There's a better way: feel it happen in real time.</p>
<h2 class="anchor anchorTargetStickyNavbar_yIpS" id="the-idea">The idea<a href="https://docs.pushmark.app/blog/ios-app-install-notifications#the-idea" class="hash-link" aria-label="Direct link to The idea" title="Direct link to The idea" translate="no">​</a></h2>
<p>Pushmark is a free iOS app that receives push notifications triggered by a simple HTTP POST. Install it on your phone, create a channel, and anything that can make an HTTP request can notify you — including your own apps. On first launch, your app fires a single POST to that channel, and your phone buzzes instantly. No backend, no APNs certificates, no provisioning headaches.</p>
<h2 class="anchor anchorTargetStickyNavbar_yIpS" id="setup">Setup<a href="https://docs.pushmark.app/blog/ios-app-install-notifications#setup" class="hash-link" aria-label="Direct link to Setup" title="Direct link to Setup" translate="no">​</a></h2>
<ol>
<li class="">Download <a href="https://pushmark.app/" target="_blank" rel="noopener noreferrer" class="">Pushmark</a> on your iPhone</li>
<li class="">Create a channel — give it a name like "MyApp installs"</li>
<li class="">Copy the channel hash from the channel detail page</li>
</ol>
<h2 class="anchor anchorTargetStickyNavbar_yIpS" id="swiftui-implementation">SwiftUI implementation<a href="https://docs.pushmark.app/blog/ios-app-install-notifications#swiftui-implementation" class="hash-link" aria-label="Direct link to SwiftUI implementation" title="Direct link to SwiftUI implementation" translate="no">​</a></h2>
<p>Replace <code>YOUR_CHANNEL_HASH</code> with the hash you just copied, then add a <code>notifyInstall()</code> function and call it from your root view's <code>.onAppear</code> modifier:</p>
<div class="language-swift codeBlockContainer_huE5 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_oko_"><pre tabindex="0" class="prism-code language-swift codeBlock_BBgU thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_t9f9"><span class="token-line" style="color:#F8F8F2"><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> </span><span class="token class-name">SwiftUI</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token attribute atrule">@main</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">struct</span><span class="token plain"> </span><span class="token class-name">MyApp</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token class-name">App</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">var</span><span class="token plain"> body</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">some</span><span class="token plain"> </span><span class="token class-name">Scene</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token class-name">WindowGroup</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token class-name">ContentView</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                </span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">onAppear </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">notifyInstall</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">func</span><span class="token plain"> </span><span class="token function-definition function" style="color:rgb(80, 250, 123)">notifyInstall</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> defaults </span><span class="token operator">=</span><span class="token plain"> </span><span class="token class-name">UserDefaults</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">standard</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> key </span><span class="token operator">=</span><span class="token plain"> </span><span class="token string-literal string" style="color:rgb(255, 121, 198)">"hasLaunchedBefore"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">guard</span><span class="token plain"> </span><span class="token operator">!</span><span class="token plain">defaults</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">bool</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">forKey</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> key</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">else</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token comment" style="color:rgb(98, 114, 164)">// Flag set before the network call (fire-and-forget — no retry on failure)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    defaults</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">set</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token boolean">true</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> forKey</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> key</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> channelHash </span><span class="token operator">=</span><span class="token plain"> </span><span class="token string-literal string" style="color:rgb(255, 121, 198)">"YOUR_CHANNEL_HASH"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> url </span><span class="token operator">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">URL</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">string</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token string-literal string" style="color:rgb(255, 121, 198)">"https://api.pushmark.app/</span><span class="token string-literal interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">\(</span><span class="token string-literal interpolation">channelHash</span><span class="token string-literal interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token string-literal string" style="color:rgb(255, 121, 198)">"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">!</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">var</span><span class="token plain"> request </span><span class="token operator">=</span><span class="token plain"> </span><span class="token class-name">URLRequest</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">url</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> url</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    request</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">httpMethod </span><span class="token operator">=</span><span class="token plain"> </span><span class="token string-literal string" style="color:rgb(255, 121, 198)">"POST"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    request</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">setValue</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string-literal string" style="color:rgb(255, 121, 198)">"application/json"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> forHTTPHeaderField</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token string-literal string" style="color:rgb(255, 121, 198)">"Content-Type"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> locale </span><span class="token operator">=</span><span class="token plain"> </span><span class="token class-name">Locale</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">current</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">identifier</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> version </span><span class="token operator">=</span><span class="token plain"> </span><span class="token class-name">Bundle</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">main</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">infoDictionary</span><span class="token operator">?</span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token string-literal string" style="color:rgb(255, 121, 198)">"CFBundleShortVersionString"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">as</span><span class="token operator">?</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> </span><span class="token operator">??</span><span class="token plain"> </span><span class="token string-literal string" style="color:rgb(255, 121, 198)">"unknown"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> appName </span><span class="token operator">=</span><span class="token plain"> </span><span class="token class-name">Bundle</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">main</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">infoDictionary</span><span class="token operator">?</span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token string-literal string" style="color:rgb(255, 121, 198)">"CFBundleName"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">as</span><span class="token operator">?</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> </span><span class="token operator">??</span><span class="token plain"> </span><span class="token string-literal string" style="color:rgb(255, 121, 198)">"App"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> body</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token class-name">String</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">Any</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token string-literal string" style="color:rgb(255, 121, 198)">"message"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token string-literal string" style="color:rgb(255, 121, 198)">"app"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> appName</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token string-literal string" style="color:rgb(255, 121, 198)">"version"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> version</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token string-literal string" style="color:rgb(255, 121, 198)">"locale"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> locale</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token string-literal string" style="color:rgb(255, 121, 198)">"type"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token string-literal string" style="color:rgb(255, 121, 198)">"success"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    request</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">httpBody </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">try</span><span class="token operator">?</span><span class="token plain"> </span><span class="token class-name">JSONSerialization</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">data</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">withJSONObject</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> body</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token class-name">URLSession</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">shared</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">dataTask</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">with</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> request</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">resume</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></span></code></pre></div></div>
<p>The <code>.onAppear</code> modifier runs once when the root view appears. The <code>UserDefaults</code> flag ensures it only fires on the very first launch.</p>
<p>That's it. The next time someone opens your app for the first time, you'll feel your phone buzz.</p>
<h2 class="anchor anchorTargetStickyNavbar_yIpS" id="richer-notifications">Richer notifications<a href="https://docs.pushmark.app/blog/ios-app-install-notifications#richer-notifications" class="hash-link" aria-label="Direct link to Richer notifications" title="Direct link to Richer notifications" translate="no">​</a></h2>
<p>The <code>message</code> object is freeform. Include whatever context matters to you:</p>
<div class="language-swift codeBlockContainer_huE5 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_oko_"><pre tabindex="0" class="prism-code language-swift codeBlock_BBgU thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_t9f9"><span class="token-line" style="color:#F8F8F2"><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> body</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token class-name">String</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">Any</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token string-literal string" style="color:rgb(255, 121, 198)">"message"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token string-literal string" style="color:rgb(255, 121, 198)">"app"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> appName</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token string-literal string" style="color:rgb(255, 121, 198)">"version"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> version</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token string-literal string" style="color:rgb(255, 121, 198)">"locale"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token class-name">Locale</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">current</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">regionCode </span><span class="token operator">??</span><span class="token plain"> </span><span class="token string-literal string" style="color:rgb(255, 121, 198)">"??"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token string-literal string" style="color:rgb(255, 121, 198)">"timezone"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token class-name">TimeZone</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">current</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">identifier</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token string-literal string" style="color:rgb(255, 121, 198)">"type"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token string-literal string" style="color:rgb(255, 121, 198)">"success"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><br></span></code></pre></div></div>
<p>Common fields to add:</p>
<ul>
<li class=""><code>Locale.current.regionCode</code> — country (e.g. <code>US</code>, <code>DE</code>, <code>JP</code>)</li>
<li class=""><code>Locale.current.identifier</code> — full locale (e.g. <code>en_US</code>)</li>
<li class=""><code>TimeZone.current.identifier</code> — timezone</li>
<li class=""><code>Bundle.main.infoDictionary?["CFBundleShortVersionString"]</code> — app version</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_yIpS" id="why-pushmark">Why Pushmark<a href="https://docs.pushmark.app/blog/ios-app-install-notifications#why-pushmark" class="hash-link" aria-label="Direct link to Why Pushmark" title="Direct link to Why Pushmark" translate="no">​</a></h2>
<p>Getting push notifications <em>to</em> your device from an iOS app normally requires a server with APNs credentials, a provider token or certificate, and a registered push token from the target device. That's the right setup for production apps sending notifications to users.</p>
<p>This pattern is for a different case: you want to notify <em>yourself</em>, and you want zero infrastructure. Pushmark handles the APNs side. Your app just makes an HTTP POST.</p>
<p>See the <a class="" href="https://docs.pushmark.app/">Getting Started guide</a> for the full API reference.</p>]]></content>
        <category label="ios" term="ios"/>
        <category label="swiftui" term="swiftui"/>
        <category label="push-notifications" term="push-notifications"/>
        <category label="indie-dev" term="indie-dev"/>
    </entry>
</feed>