<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Destan ÖZGEN</title>
    <description>The latest articles on DEV Community by Destan ÖZGEN (@destan_zgen_3119b2328637).</description>
    <link>https://dev.to/destan_zgen_3119b2328637</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4085101%2Fd0bb73a1-0154-4332-91b3-232ccfb9f9fe.png</url>
      <title>DEV Community: Destan ÖZGEN</title>
      <link>https://dev.to/destan_zgen_3119b2328637</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/destan_zgen_3119b2328637"/>
    <language>en</language>
    <item>
      <title>I completed my internship: how I built Movere AI from scratch</title>
      <dc:creator>Destan ÖZGEN</dc:creator>
      <pubDate>Wed, 19 Aug 2026 13:32:02 +0000</pubDate>
      <link>https://dev.to/destan_zgen_3119b2328637/i-completed-my-internship-how-i-built-movere-ai-from-scratch-23d2</link>
      <guid>https://dev.to/destan_zgen_3119b2328637/i-completed-my-internship-how-i-built-movere-ai-from-scratch-23d2</guid>
      <description>&lt;p&gt;Six weeks ago, when I started my software development internship at Motivolog, I had an empty Flutter project. Today there's a real mobile app, uploaded to App Store Connect and running through TestFlight with its own AI backend: Movere AI.&lt;/p&gt;

&lt;p&gt;This post covers what I actually did over the internship. The technical side — the stack, the real problem the app solves, the Apple permissions process, and the challenges I ran into — is covered in a separate technical post linked below.&lt;/p&gt;

&lt;h2&gt;
  
  
  How it went
&lt;/h2&gt;

&lt;p&gt;I structured the internship into five weekly sprints:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Sprint 1&lt;/strong&gt; — project setup, my own design system ("Move Beyond"), core UI components&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sprint 2&lt;/strong&gt; — Dashboard, Focus Mode, Progress screen&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sprint 3&lt;/strong&gt; — Academy (short lessons) and podcast integration&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sprint 4&lt;/strong&gt; — local persistence with SQLite, real authentication with Firebase&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sprint 5&lt;/strong&gt; — turning the Reality Score into something actually computed live, full English/Turkish support, and the first version of the AI-backed recommendation system&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The final week (Finalization) went entirely into testing, bug fixes, performance work, and getting the app release-ready.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it ended up being
&lt;/h2&gt;

&lt;p&gt;Movere AI, in short: a focus app that tracks real sessions, shows a Reality Score that's computed from real data instead of being static or random, teaches digital-habits lessons in both text and podcast form, and reads your own data to give you short, real AI-backed recommendations — all in English and Turkish, switchable in one tap.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I actually took from the process
&lt;/h2&gt;

&lt;p&gt;This wasn't just "build an app" for me — it was the first time I really learned what committing regularly, running an actual sprint structure, reviewing my own code, and genuinely shipping something (App Store Connect, certificates, TestFlight) actually feels like. The technical problems I hit in the last couple of weeks especially — code signing, missing permission strings, an abandoned native extension silently blocking the build — weren't things I learned from a book. I learned them by chasing down a real bug in a real product.&lt;/p&gt;

&lt;p&gt;Outside the technical side, regularly writing and sharing progress reports was its own kind of new discipline — having to clearly lay out, every couple of days, "what I did, where I am, what's next" actually made my own thinking clearer too. Reporting on something and getting it signed off before calling it "done" turned out to be a genuinely different kind of responsibility than working alone ever was.&lt;/p&gt;

&lt;p&gt;Haydar had also set up a shared "internship" space that all the interns could see — you could watch what everyone else was working on, which made the whole thing feel less like working alone in a room and more like actually being part of a team. At one point he pointed me toward a resource with the note "you can pick up some skills from here while using AI" — a directory of skill files written specifically for Claude Code, Codex, and Cursor for mobile developers. Fitting, given how much of this internship was about learning to work with AI better — even the recommendation itself was teaching that.&lt;/p&gt;

&lt;h2&gt;
  
  
  Demo video
&lt;/h2&gt;

&lt;p&gt;I put together a full walkthrough of the app — you can watch it below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://youtu.be/nljgDGpMwtY" rel="noopener noreferrer"&gt;https://youtu.be/nljgDGpMwtY&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you're curious about the code, what I built it with, the actual problem the app is solving, and what the Apple side of shipping this looked like, that's all in the technical post: &lt;a href="https://dev.to/destan_zgen_3119b2328637/how-i-built-movere-ai-with-flutter-the-problem-the-stack-the-apple-process-and-what-actually-2b0i"&gt;https://dev.to/destan_zgen_3119b2328637/how-i-built-movere-ai-with-flutter-the-problem-the-stack-the-apple-process-and-what-actually-2b0i&lt;/a&gt;&lt;/p&gt;

</description>
      <category>flutter</category>
      <category>internship</category>
      <category>career</category>
      <category>ai</category>
    </item>
    <item>
      <title>How I built Movere AI with Flutter: the problem, the stack, the Apple process, and what actually went wrong</title>
      <dc:creator>Destan ÖZGEN</dc:creator>
      <pubDate>Wed, 19 Aug 2026 13:26:06 +0000</pubDate>
      <link>https://dev.to/destan_zgen_3119b2328637/how-i-built-movere-ai-with-flutter-the-problem-the-stack-the-apple-process-and-what-actually-2b0i</link>
      <guid>https://dev.to/destan_zgen_3119b2328637/how-i-built-movere-ai-with-flutter-the-problem-the-stack-the-apple-process-and-what-actually-2b0i</guid>
      <description>&lt;p&gt;I wrote Movere AI with Flutter. This post covers what my internship-completion post didn't: the actual problem the app solves, the stack I used, the permissions and certificate process I went through on Apple's side, and the real difficulties I ran into along the way.&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem it solves
&lt;/h2&gt;

&lt;p&gt;Most screen-time tools show you a number and stop there — what it means, what to actually do about it, is left to you. What Movere AI is trying to solve is a bit different: building a feedback loop you can actually trust. When you finish a focus session, I wanted you to know it's recorded, that your progress feeds into a real score, and that the score isn't made up. Trust between the user and the app is the thing the whole design sits on.&lt;/p&gt;

&lt;p&gt;That shows up concretely in the Reality Score: not a static or random number, but a weighted average of three real components — how close you are to today's focus goal (50%), your session completion rate over the last 7 days (30%), and your overall reading progress (20%). The weights were set by gut feeling for now; I'm planning to tune them once real usage data comes in.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I built it with
&lt;/h2&gt;

&lt;p&gt;Flutter on the frontend, Riverpod for state management — I picked it over Provider or Bloc mainly for compile-time type safety and being able to handle fairly complex state (like the AI recommendation engine computing across four categories) without much boilerplate. The project is structured feature-first: &lt;code&gt;lib/features/&amp;lt;feature&amp;gt;/{presentation, application, domain}&lt;/code&gt;, with shared components living centrally in &lt;code&gt;lib/core&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Local persistence runs on SQLite (&lt;code&gt;sqflite&lt;/code&gt;). Hive was an option, but I knew early on I'd need relational queries — things like sorting this week's sessions by date — and SQL just fits that better. Five tables hold the data: focus sessions, reading progress, bookmarks, listened episodes, user profile.&lt;/p&gt;

&lt;p&gt;I used Firebase Authentication for identity and session management rather than building another authentication backend. At this stage, that kept the security-sensitive part small and let me spend the internship on the app's core features.&lt;/p&gt;

&lt;p&gt;One problem that ended up needing two completely different solutions was Usage Insights — and the hard part wasn't the code, it was the permission model itself, which turned out to be fundamentally different on each platform.&lt;/p&gt;

&lt;p&gt;On Android, usage stats aren't gated behind a normal runtime permission you can just pop a dialog for. &lt;code&gt;PACKAGE_USAGE_STATS&lt;/code&gt; is a "special" permission — the kind Android deliberately makes awkward to grant, precisely because it's privacy-sensitive. There's no API call that shows a standard allow/deny prompt. Instead, the app has to check whether access is already granted using &lt;code&gt;AppOpsManager&lt;/code&gt; (&lt;code&gt;checkOpNoThrow&lt;/code&gt; with &lt;code&gt;OPSTR_GET_USAGE_STATS&lt;/code&gt;), and if it isn't, the only path forward is firing an Intent that sends the user to a specific system settings screen (Settings &amp;gt; Apps &amp;gt; Special app access &amp;gt; Usage access) where they have to manually find Movere AI in a list and flip the toggle themselves. I built a native &lt;code&gt;MethodChannel&lt;/code&gt; bridge to handle both the check and the settings redirect, plus UI on the Flutter side that explains why the user needs to do this before sending them there.&lt;/p&gt;

&lt;p&gt;iOS turned out to be the harder problem, not because the permission is hard to grant, but because there's no permission to grant at all. Apple simply doesn't expose a live usage-stats API to third-party apps — not behind a special permission, not behind an entitlement, not at any tier. It's a hard privacy boundary, full stop. So "solving" it on iOS wasn't a permissions problem, it was an architecture problem: the only viable path was building a completely separate flow around Apple's own App Privacy Report feature, where the user exports their own usage data from Settings as a file, and the app imports and parses that file (NDJSON format) after the fact. It's not live, and it's not automatic, but it's the only route that actually respects how Apple's platform is designed — and being upfront in the UI about why the two platforms behave differently mattered more than I expected.&lt;/p&gt;

&lt;p&gt;On the AI side there are two layers: a fully local, fully auditable rule engine (in Dart) that decides what to recommend, and an OpenAI call on top of it (through a Firebase Cloud Function) that turns the facts that engine produces into natural language. The phone talks to that function, not to OpenAI directly, so the API key never lives inside the app — only in Secret Manager. The reasoning is simple: an API key embedded in a mobile app isn't really secret anymore, since anyone can pull it out of the binary. Routing through the function removes that risk entirely.&lt;/p&gt;

&lt;p&gt;Localization runs on &lt;code&gt;flutter_localizations&lt;/code&gt; and &lt;code&gt;.arb&lt;/code&gt; files — over 70 text keys, in two languages, switchable live. Altogether, the project sits at 50+ signed commits, with a codebase standardized to English throughout.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the Apple side actually looked like
&lt;/h2&gt;

&lt;p&gt;Getting the app onto TestFlight took longer than writing some of its features, so it deserves a section of its own.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;Apple Developer account&lt;/strong&gt; was already open from earlier Screen Time API experiments. But registering the app in App Store Connect and getting it into TestFlight turned out to be a completely different process. The first package I built with &lt;code&gt;flutter build ipa --release&lt;/code&gt; got rejected on three separate uploads, all with &lt;code&gt;Invalid Signature&lt;/code&gt; — the actual cause being that the machine only had a &lt;strong&gt;Development certificate&lt;/strong&gt;, and no &lt;strong&gt;Distribution certificate&lt;/strong&gt; had ever been created. Fixing it meant generating a CSR by hand, requesting a real Apple Distribution certificate through the developer portal, installing it — private key included — into the Keychain, generating a matching provisioning profile, and re-signing the archive with that specific identity.&lt;/p&gt;

&lt;p&gt;Getting signing right wasn't the end of it either — Apple's own automated validation then rejected the next upload for three separate &lt;strong&gt;missing permission strings&lt;/strong&gt;, for camera, microphone, and photo library. The app doesn't use any of them; a couple of bundled plugin dependencies reference the underlying APIs regardless, and iOS doesn't care whether your own code actually calls them. Three lines added to &lt;code&gt;Info.plist&lt;/code&gt;, problem solved.&lt;/p&gt;

&lt;p&gt;Finally, actually sending the app to a friend through TestFlight meant creating an External Testing group — which requires a build to have successfully finished processing first. So none of that was even reachable until the certificate and permission issues were sorted.&lt;/p&gt;

&lt;h2&gt;
  
  
  The general difficulties along the way
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;An abandoned native extension silently blocked the build&lt;/strong&gt; — During the final week, right after moving the project folder to a different location on my desktop, &lt;code&gt;flutter build&lt;/code&gt; suddenly started failing with a Swift compile error: &lt;code&gt;Type 'TotalActivityReport' does not conform to protocol 'AppExtensionScene'&lt;/code&gt;. This wasn't code I'd written recently — it was a leftover, never-finished Screen Time API extension (a &lt;code&gt;DeviceActivityReport&lt;/code&gt;, meant for usage reporting) that had been added to the Xcode project at some earlier point but never committed to Git. Checking the Git history confirmed the extension had &lt;strong&gt;never actually been committed&lt;/strong&gt;, which gave me a safe fix: revert &lt;code&gt;project.pbxproj&lt;/code&gt; to its last clean, committed state, without touching anything through Xcode's UI. The Swift files stayed on disk but stopped being referenced anywhere, and the build was clean again.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A silent data bug — saved correctly, never displayed&lt;/strong&gt; — During a full testing pass, I noticed podcast episodes' "listened" status wasn't showing up in the UI at all, which I initially assumed meant the data wasn't being saved. Inspecting the SQLite table directly showed otherwise — &lt;code&gt;listened_episodes&lt;/code&gt; was populating exactly as expected; the data was genuinely there. The actual bug was that no screen was ever reading it back — the lesson detail screen simply never watched &lt;code&gt;listenedProvider&lt;/code&gt;. A classic "data layer correct, UI layer missing" bug: trivial to fix once found (one &lt;code&gt;ref.watch&lt;/code&gt; call), but finding it took a code review, not just using the app.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where it's at now
&lt;/h2&gt;

&lt;p&gt;The MVP is signed, uploaded to App Store Connect, running standalone through TestFlight, and has already gone out to a real external tester. Next up: going back through the Reality Score's weights (currently 50/30/20, set by gut feeling) against real usage data instead of my own test sessions.&lt;/p&gt;

&lt;p&gt;If you want the full story of the internship this came out of — the sprints, what the app actually became, and how the whole thing went — I wrote that up too: &lt;a href="https://dev.to/destan_zgen_3119b2328637/i-completed-my-internship-how-i-built-movere-ai-from-scratch-23d2"&gt;https://dev.to/destan_zgen_3119b2328637/i-completed-my-internship-how-i-built-movere-ai-from-scratch-23d2&lt;/a&gt;&lt;/p&gt;

</description>
      <category>flutter</category>
      <category>mobiledev</category>
      <category>ai</category>
      <category>ios</category>
    </item>
  </channel>
</rss>
