s

tudu: Dev Log

Day 14 (Part 2): Turning the Website into a Sales Machine June 22, 2025

With the app itself feeling more polished, I turned my attention back to the landing page. It looked great, but I realized it wasn't *selling* hard enough. It needed to do more than just list features; it needed to build trust and prove the app's intelligence. I focused on three key upgrades.

1. Show, Don't Just Tell: Upgrading the AI Demo

The "You Say... tudu Creates..." demo was good, but it could be better. It needed to showcase the full power of the AI. I updated it to show that the AI doesn't just parse dates and titles, but also infers **Priority**, adds **Tags**, and includes **Notes**. I added colorful, distinct badges for each element, making the output more scannable and visually impressive. It now immediately communicates a much higher level of intelligence.

2. Adding Tangible Proof: The "Smart Tags" Feature

I realized I had this awesome "Auto-Tag" feature in the app but wasn't even mentioning it on the site! I added a new feature card for "Smart Tags" and changed the layout to a more balanced 2x2 grid. This provides another concrete example of the AI in action and makes the whole feature section look more organized and deliberate.

3. Framing the Conversation: The Competitor Comparison

This was a big strategic move. To proactively answer the question, "Why this app over the hundred others?", I added a new "Competitor Comparison" section. It's a clean, modern table that positions tudu's unique strengths (AI parsing, intelligent suggestions, streaks) against "Traditional Apps."

It's a classic marketing technique, but it's effective. It builds confidence by showing I'm not afraid to compare, and it clearly articulates tudu's unique value proposition from the get-go. It frames the app not as just another to-do list, but as a next-generation tool.

These changes make the website feel less like a simple info page and more like a persuasive, high-tech sales tool. It's all about building that initial trust and making a compelling case for why tudu is different.

Marketing & Strategy
Day 14 (Part 1): The AI Gets a PhD in "Actually Helpful" June 22, 2025

Back in the code today with a mission: make the AI feel less like a parser and more like a real assistant. It's one thing to have cool features, but if the workflow is clunky, nobody will use them. I focused on making the entire process of creating and editing tasks smoother and more intelligent.

AI Now Understands Priority

This was a big one. The AI is now fully aware of task priorities. Users can now type things like, "Schedule a meeting for tomorrow, it's urgent" or "Add 'buy milk' low priority," and the app will correctly assign High, Medium, or Low priority. I also added a manual picker, so you have full control, but letting the AI handle it feels magical.

Auto-Tagging That Doesn't Suck

The global "Auto-Assign Tags" feature got a major logic overhaul. The first version was a bit too literal, creating tons of one-off tags. I refined the prompt to instruct the AI to prioritize grouping and reusing existing tags. So now, instead of creating a useless `#hydration` tag, it'll correctly group it under the more reusable `#health` tag. It's now accessible from a new "AI Actions" menu right on the main task list.

A More Polished & Forgiving Editing Workflow

This was a huge quality-of-life update. I completely re-thought the AI editing experience:

  • Conditional Auto-Save: When the AI edits an existing task, it saves instantly. But when it creates a *new* task from your input, the view stays open, letting you review and tweak before manually saving. No more views closing on you unexpectedly!
  • Dynamic Feedback: The generic "AI has updated..." message is gone. Now it tells you *exactly* what changed, like "AI updated: title, due date, 2 tags." Much more transparent.
  • "Save on Dismiss": This is my favorite. If you make a bunch of changes and then just swipe the view away without hitting "Save," the app now saves it for you in the background. No more lost work!
  • Tag Suggestions: A small but mighty feature. As you start typing a tag, a list of your previously used tags appears. Tapping one adds it instantly. It's so much faster and keeps your tags consistent.

These changes make the app feel so much more professional and intuitive. The AI and the UI are finally working together as a team.

Polishing & UX
Day 13: Phase 2 | From Code to Brand - tudu is Born! June 21, 2025

The pivot is real. I've officially switched hats from "coder who hasn't seen the sun in a week" to "marketer who still hasn't seen the sun." Today was a whirlwind of branding, design, and logistics. It's one thing to build an app, but another thing entirely to build a brand around it.

Finding a Name: The .com Struggle is Real

First order of business: FINALLY give this app a name. I landed on **tudu**. It's short, memorable, and plays on the tagline I came up with: "a to-do list, for u." Unfortunately, `tudu.com` and `tudu.ai` were long gone. I debated between `trytudu.com` and `gettudu.com` and ultimately went with **gettudu.com**. It feels more like a confident call-to-action, not just a trial. I registered it through AWS, so we are officially on the map!

Building the Front Door: The Landing Page

With the name sorted, I spent a solid 7 hours locked in, building the official website. I'm not even exaggerating; I completely forgot to eat, but it was so worth it. The site is live right now, and I am SO proud of it. It's exactly what I envisioned and more – sleek, modern, and it feels as high-tech as the AI inside the app. I wanted to sell the *benefit* ("Stop organizing, Start achieving") rather than just listing features, and I think the site nails it.

Check out the Live Website!

The process was intense. It went from a basic concept to a polished final product by focusing on key phases: strategy, content structure, adding high-tech interactive elements (like an aurora background and a spotlight that follows your cursor), and then a final "pixel-perfect" pass to align everything with the new brand colors.

The Logo Saga & Legal Stuff

I tried my hand at logo design. I had this cool idea of combining a chat bubble and a checkmark. My dad took one look and said, "Looks like WhatsApp." I didn't see it at first, but after looking at it on the site... yeah, he was right. It screamed "messaging app." So, for now, the logo is just the name `tudu.` in the brand color. I'm not a graphic designer, but it works! It's clean.

Also knocked out the boring but essential stuff: created the Apple Developer account (in my dad's name, so I can start setting up RevenueCat for the paywall) and drafted the initial Privacy Policy and Contact pages. Every piece of the puzzle is slowly falling into place.

Branding & Marketing
Day 12 (Part 2): Power-User Mode: ON! June 20, 2025

With the app no longer crashing every five seconds (see Part 1!), I could finally get back to building features. I just discovered GitHub Issues, and it's been a game-changer for organizing the chaos in my head into an actual to-do list. Ironic, I know.

Feature Drop #1: Subtasks!

This has been the most requested feature from... well, from me. I needed a way to break down big tasks. Implementing this was a fun challenge in data modeling. A task can now be a parent to other tasks, creating a hierarchy.

The trickiest part was getting them to display correctly in the UI. I had to create a "flattened hierarchy" where the list still looks simple, but child tasks are neatly indented and sorted under their parent. It feels so satisfying to finally be able to organize "Launch App" into subtasks like "Finalize Name," "Design Logo," and "Panic."

Feature Drop #2: AI "BETA" Toggles

The AI is powerful, but some of the more experimental ideas might not be for everyone. So, I added a new "BETA Features" section in Settings.

  • Users can now opt-in to things like "AI Auto-Estimate Duration." If you create a task like "Write college essay" without a duration, the AI will make a reasonable guess.
  • This was done with some slick prompt engineering. I'm literally just adding new instructions to the Gemini prompt if the user has a toggle turned on. It's a super flexible way to test new AI features without forcing them on everyone.

Feature Drop #3: Spying on My AI

How do I know if the AI is actually being helpful? I need data! I built a system to log every user prompt and the AI's raw response to a separate, secure collection in Firestore. This is purely for analytics and debugging. Seeing what works (and what doesn't) will be invaluable for making the AI smarter over time. I used a `defer` block in the code to make sure the logging happens no matter what, which is a pretty robust pattern.

And Finally, The Ghost Bug...

I swear, the "Delete Account" button is haunted. I fixed it, and then it broke again for no apparent reason. Then I'd change something completely unrelated, and it would start working. It's one of those bugs that just makes you laugh so you don't cry. It's stable... for now. *knock on wood*.

Still need to finalize the app's name, branding, logo, colors, tagline... the fun stuff! But having a stable, cloud-synced app with subtasks and smart AI toggles feels like a massive leap forward.

Development Phase
Day 12 (Part 1): The Great Un-Crashing! June 20, 2025

Woke up this morning with one mission: fix the bug that was crashing the app on every single data-related tab. The cliffhanger from last night was that the Settings tab worked, and that was the golden clue.

The "Aha!" Moment

It was a "silly" mistake, but the kind that makes you want to pull your hair out. A classic dependency injection problem. I was passing the Firestore and Auth managers to each view *inside* the TabView, but it turns out SwiftUI's TabView can be picky about how it passes things down its hierarchy. Some of my views were waking up after login and basically shouting "Where's the database?!" into the void, causing an immediate crash.

The fix? I moved the .environmentObject() modifiers to the `TabView` itself. One change. I built the app, ran it, held my breath... and it worked. Every tab opened. No crash. The feeling of relief was *immense*.


Cleaning Up the Authentication Mess

With the main crash fixed, I found more subtle bugs in the sign-in/sign-out flow. It felt like cleaning up after a party.

  • The Onboarding Amnesia Loop: Signing out and then signing back in would trigger the "Welcome!" onboarding survey again, even for an existing user. The app was giving my users amnesia! The root cause was a race condition where the local "onboarding complete" setting was being overwritten in the cloud. The solution was to check the isNewUser flag from Firebase. Now, we only create a user profile if they are *genuinely* new.
  • The Ghost of User's Past: I also realized that signing out left all the previous user's tasks and settings in the local database. The next person to sign in on the same phone would see everything! I created a "hard reset" function called resetAllSettingsToDefaults() that now gets called on sign-out. It completely wipes the local database and resets all settings, ensuring a clean slate.
  • The App That Wouldn't Say Goodbye: After deleting an account, the app would just... get stuck. It wouldn't return to the login screen. I had to implement a more robust event-driven system using Combine's PassthroughSubject. Now, when a user is deleted, it broadcasts a "didSignOut" event that the root view listens for, reliably forcing it back to the login screen.

With these fixes, the cloud foundation finally feels solid and stable. The app is no longer a house of cards. Now, the *real* fun begins: building cool stuff on top of it.

Day 11: Icarus Flew Too Close to the Auth... June 19, 2025

Riding high off yesterday's success with real-time sync, I thought, "How hard can adding Google Sign-In be?" Famous last words.

The goal was to replace my simple "mock user ID" with proper user authentication. This would be the final piece of the puzzle to make the cloud sync truly user-specific. I followed the Firebase docs, integrated the authentication library, and added the sign-in button. It looked great.

And Then... Everything Broke.

I signed in successfully, and the app immediately crashed. Reloaded. Tapped the "Tasks" tab. Crash. Tapped the "Dashboard" tab. Crash. Tapped the "Completed" tab. Crash.

Weirdly enough, the "Settings" tab worked perfectly fine. What on earth?

This is one of those bugs that makes you question everything. My cloud sync logic was solid yesterday. The authentication *seems* to work because I can see my user account in the Firebase console. But navigating to any view that actually needs the user's data just nukes the app.

The Clue

The fact that the Settings tab works is the key. It's the only one that isn't trying to fetch tasks or projects from Firestore. This means the problem isn't the login itself, but how the "logged-in state" and the connection to the database are being passed around the app *after* the login happens. My Task List, Dashboard, and other views are trying to ask Firestore "Hey, get me this user's data!" but it seems like they have no idea who the user is or how to even talk to the database anymore.

It's a classic dependency injection problem, I'm pretty sure. The managers that handle authentication and Firestore are not being passed down correctly through the main TabView to all its children. I'm injecting them, but something about the way SwiftUI handles TabView hierarchies is tripping me up.

It's now 4 AM. I've been staring at this for hours, but at least I think I know *what* the problem is, even if I don't know the exact line of code to fix it yet. I'm going to hit the sheets. I'll pick this up tomorrow with fresh eyes. The bug can't win if I'm asleep.

Day 10: We Go to the Cloud! (Mostly) June 18, 2025

It's time. We need to grow beyond just a single-device app, it needs a brain in the cloud. The goal: real-time data sync across devices. This is the foundation for everything – multi-device support, web versions, the works!

Choosing a Side: Firebase vs. CloudKit

First big decision: where to host this brain? The two main contenders were Apple's CloudKit and Google's Firebase.

  • CloudKit: Super easy to integrate with an iOS app. It's the native, "Apple-approved" way.
  • Firebase: A bit more setup, but it's platform-agnostic. If I ever want to build an Android or web version of Synaptask, Firebase makes that a *million* times easier. Plus, its free tier is incredibly generous, which is crucial since this app is entirely bootstrapped and free to run for now.

Foresight won out. **I went with Firebase.** A little more work now for a lot more flexibility later.

The "Is This Thing On?" Problem

I set up my Firebase project, configured the SDKs, added the `GoogleService-Info.plist`... and tried to save a task. Nothing. No crash, no error, just... silence. My data was not appearing in the Firebase console. I spent a good hour double-checking my app's Bundle ID, convinced I had a typo somewhere. Nope.

Turns out, Firestore's default security rules are basically a brick wall that says "NOBODY GETS IN!" You have to explicitly give it permission to accept data. A quick change to the rules for development mode (`allow read, write: if true;`), and boom! The door was unlocked.

The Race Condition Nightmare

Okay, door's unlocked, let's try again. Save task... still nothing. But this time, I caught a fleeting error in the Xcode console: `Unavailable: Network connectivity changed.` My Wi-Fi was fine, so what gives?

Aha! A classic race condition. My code was telling Firebase "Hey, start saving this data!" and then immediately telling the view "Okay, you're done, close yourself now!" The view was being destroyed before the asynchronous save request could finish, so iOS was just killing the connection. The solution was surprisingly simple: move the `dismiss()` call so it only happens *after* the Firebase operation confirms it's done.

The Magic Moment

With those hurdles cleared, I implemented the sync for Tasks and then extended it to Projects. I created a mock user ID for now, so I didn't have to tackle full Google Sign-In just yet. I had the app running on my phone and the Firebase Firestore console open on my laptop. I added a new task on my phone...

...and watched it appear on my laptop screen in real-time. It felt like absolute magic. That "single source of truth" pattern where the app only writes to the cloud, and a listener updates the local database, is working flawlessly. It's robust, clean, and so satisfying to see in action. Big, big win for today.

Day 9 (Part 2): First Impressions Matter - Onboarding Flow! June 17, 2025

After a busy morning and afternoon on core features (see Part 1!), I switched gears to something equally important: the new user experience. First impressions are everything, right? So, I built out a multi-screen onboarding flow for Synaptask.

The idea is to make users feel welcomed and also to subtly gather some info that might help personalize their experience down the line (and maybe even train the AI better eventually, who knows!).

Here’s what the onboarding journey looks like now:

  • Warm Welcome: Starts with a friendly welcome screen. Standard stuff, but gotta have it.
  • Understanding Intent: Asks users what they primarily plan to use a to-do app for – work, school, personal projects, etc.
  • Experience Level: Gathers a bit about their past experience with task management tools and if they've used AI-assisted productivity apps before. No judgment, just curiosity!
  • Valued Features: Users can pick up to three key features they look for most in a to-do app. This is gold for future development priorities.
  • Primary Goal (Optional): A prompt for them to define one main goal they want to achieve with Synaptask. Thinking this could be a powerful motivator if I can tie it back into the app later.
  • Feature Showcase: Briefly highlights Synaptask's core strengths – AI input, projects/tags, and the streak system. A little "here's what makes us cool" moment.
  • Notification Opt-In: A clear chance to enable notifications, explaining why they're helpful.

All these preferences get saved to AppSettings. For now, it's mostly for me to understand user needs, but the dream is to use this data to tailor the app or even fine-tune AI behavior for individuals in the future. Imagine the AI knowing you primarily use the app for "school" and adjusting its suggestions accordingly!

Spent a decent amount of time on the styling, trying to make it look polished with some custom touches and subtle animations. It's presented only on the very first app launch. Hopefully, it sets a good tone and helps with user retention – that initial investment of time by the user can be surprisingly sticky. My dad hasn't seen this part yet, so fingers crossed he approves of *this* UI!

Day 9 (Part 1): Reminders Get a Brain & Projects Arrive! June 17, 2025

Okay, today felt like one of those days where the coffee kicks in and you just *code*. Managed to knock out two pretty significant feature sets. First up, reminders got a serious upgrade, and then I laid the foundation for project-based organization.

Supercharged Custom Reminders (with AI help!)

I've been wanting to make the reminders in Synaptask (still workshopping that name, ha!) more than just a single ping. Now, users can add multiple, specific reminders to any task. Think: "Remind me to start on this 2 hours before it's due" AND "Nudge me again 30 mins before."

  • Data Model Magic: Each TaskItem can now hold an array of custom Reminder objects (date, note, enabled/disabled). SwiftData is handling the storage like a champ.
  • Slick UI for Manual Entry: Built out a new section in the task editor for adding/deleting these. The little modal sheet for adding a new reminder feels pretty clean.
  • Notifications on Point: The adinaNotificationManager now juggles all these individual reminders, scheduling and canceling them as tasks get completed or un-completed. Each one gets its own unique ID to avoid any mix-ups.
  • AI Joins the Reminder Party: This is where it gets fun. The AI (Gemini 1.5 Flash, my trusty free-tier sidekick) can now understand when you type "remind me at 5 pm" in the quick-add or even in general commands. It'll suggest structured reminders that the app then sets up. Pretty cool to see it parse that out!

Honestly, getting the AI to reliably suggest reminders and then making sure the app actually *saves* and *schedules* them correctly was a bit of a head-scratcher. State management with SwiftUI and asynchronous AI calls... let's just say there was some "spirited debugging."


Introducing: Project Organization!

The other big piece today was adding a way to group tasks into projects. This has been on my mind since the start, as I personally juggle a bunch of different "hats" – school, this app, other side hustles.

  • Create & Color-Code: Users can now create projects, name them, and pick a color from a palette. Makes it easy to see what's what at a glance.
  • Link Tasks to Projects: Simple toggle in the task editor.
  • Filter by Project: The main task list can now be filtered to show only tasks for a specific project. Essential for focus!
  • Manage Projects Area: Tucked into an options sheet on the task list, users can now view all projects, see active task counts for each, add new ones, edit existing ones (name/color), and delete them. If a project is deleted, tasks just become "unassigned" – no data loss for the tasks themselves.

No AI smarts for projects yet, like "Hey Synaptask, add this to my 'App Dev' project." That's definitely a v2 thing, probably when I can justify upgrading the Gemini model. For now, manual project assignment is a solid first step for better organization.

Whew! A lot packed into one day. Time to push this and then maybe, just maybe, touch some grass.

Day 8: Notifications Galore & Polish June 16, 2025

Today was a marathon of notification work! Finally got the re-engagement notifications ("We miss you!") and streak danger reminders implemented. The goal is to make these helpful, not annoying – like Duolingo, but hopefully a bit more chill.

  • Implemented re-engagement notifications if the app isn't opened for a while.
  • Added streak danger reminders for the evening if no task was completed. The message even adapts if you *did* complete something.
  • Refined the grouping for completed tasks. Untested, fingers crossed it works as expected when I build tomorrow.
  • Also pulled out the email helper into its own file for better organization.
  • The "Clear All Completed Tasks" button is now in both the completed view and settings.
  • Added a theme toggle directly in the app's settings, plus an option to reset streak data. Good for testing!
  • Made the dashboard task items clickable to jump straight to editing.

Feeling pretty good about the notification system's depth. It's these little touches that I hope will make the app feel more alive and supportive.

Day 7: Streaks, Recurring Tasks & More Notifs! June 15, 2025

Big day for core logic! Finally tackled streaks – current streak, longest streak, alerts for losing one or hitting a new record. This is heavily inspired by Duolingo's retention magic, so I'm excited to see how it plays out.

  • Implemented the full streak logic: incrementing, resetting, and alerts. Had a "semi-working" version earlier, but today was about making it robust.
  • Got basic recurring tasks working! Daily, weekly, etc. Still need to integrate them fully with the completed tasks view and counters.
  • Fixed a bug in the next due date calculator for recurring tasks – end dates and month boundaries are tricky!
  • Added task duration-based reminders (e.g., remind X% of duration before due).
  • Also implemented generic motivational notifications that users can schedule.
  • Cleaned up how completed tasks are organized in their view.
  • Compound tag filtering (e.g., show tasks with tag A OR tag B) is now live.
  • Improved the "clickable" dashboard stats – "Overdue" now *only* shows overdue, etc.

The app's starting to feel really feature-rich. Balancing new features with stability is key now.

Day 6: Data & Dashboard Enhancements June 14, 2025

Focused on data management and making the dashboard more interactive today.

  • Added the "Delete All Tasks" button in settings (with a confirmation, of course!). Crucial for users who want a fresh start.
  • Got the completed task counter on the dashboard working accurately.
  • Laid down the basic infrastructure for notifications. This is going to be a big one for engagement.

Thinking about how notifications will actually work. Should they be tied directly to task objects, or a separate system? Leaning towards integrating them closely with tasks for reminders, but having a separate manager for the motivational/streak ones.

Day 5: SwiftData Persistence! No More RAM Store! June 13, 2025

HUGE milestone today: tasks are now saved locally on the device using SwiftData! No more losing everything when the app closes. This feels like a proper app now.

This took a bit to get right, refactoring how data is accessed and managed. But so worth it. Now I can actually start building features that rely on persistent data, like streaks and proper completed task history.

Day 4: UI Overhaul & Settings Foundation June 12, 2025

My dad gave some... direct feedback on the UI. Said it sucked (lol, he was right in hindsight). So, spent a good chunk of today doing a full UI overhaul with a fresh color scheme. It looks SO much better now, much cleaner and more modern.

  • Implemented a completely new color palette and refined UI elements across the app.
  • Settings are now functional for changing the time format (12/24 hour).
  • Added task filtering by tags (single tag for now).
  • Basic task sorting options are in (by due date, creation date, title).
  • Implemented tagging and notes for tasks. The AI can also parse and add these now!

Debating whether cloud sync and user accounts are MVP or post-launch. For now, local storage is king for speed, but cloud sync is essential for multi-device users. Probably post-validation. Need to monetize ASAP, and cloud adds costs (Firebase is free up to a point, but still...).

Day 3: AI Gets Smarter, Dashboard & Completed Tasks June 11, 2025

Big AI day! The general AI command feature is now live. Users can type things like "Mark 'Buy milk' as done" or "What are my tasks for today?". The AI gets the current task list as context, which is pretty neat. I'm using two separate Gemini models now: `generativeModel` for general chat and `taskParsingModel` specifically for dissecting task input. Gemini 1.5 Flash is surprisingly capable for the free tier!

  • Rolled out general AI commands for interacting with the task list.
  • Split AI models for better-specialized responses.
  • Fixed an issue with AI updating time components correctly.
  • Added a "safety date" check: if AI provides a time for an "all-day" task, it correctly converts it.
  • Built out the initial Dashboard view and a separate view for Completed Tasks. You can even undo a completion!
  • Task completion from the dashboard is working, along with a "Completed Today" counter and a dynamic greeting (Good morning/afternoon/evening).
  • AI can now understand task context for editing and updating progress.

The AI interaction feels like the app's superpower. Still considering if Whisper API for voice input is worth the cost down the line. For now, text input with smart parsing is the focus.

Day 2: Core AI & UI Wrestling June 10, 2025

MVP for AI task creation is WORKING! Using Gemini 2.5 Flash. It's surprisingly good at parsing natural language like "Team meeting tomorrow 2pm for 1 hour #work note:bring slides" and populating the fields. This is the magic I was hoping for. But honestly, if app makes profit, then I think swapping to pro is the move, or atleast try out Anthropic or OpenAI models.

  • Core AI "add task" functionality implemented.
  • Fixed task progress continuity when editing.
  • Spent way too long on list row separators. SwiftUI can be finicky! Got them looking clean now.
  • Added the ability to set progress when manually creating a task.
  • Overhauled the Task Input menu UI – still needs color work, but the layout is much better.
  • "Date Only" tasks (tasks without a specific time) are now functional.

Funny story: My provisional certificate for Xcode decided to expire because I was messing with my iPhone's system time for testing date-related features. Spent a solid 3 hours debugging why Xcode wouldn't build, thinking it was some complex code issue. Turns out, Apple's time-sensitive authentication just said "nope!" Lesson learned: don't mess with system time during active development builds!

Still need a name for this app! And branding. And a logo. And a motto... a lot of "ands".

Day 1: And So It Begins! (AI To-Do List) June 9, 2025

Alright, kicking off a new iOS app project! The idea: an AI-Powered To-Do list. Less manual data entry, more smarts. Spent today setting up the initial Xcode project, Git repo, and watching a Swift/SwiftUI tutorial to refresh the basics (it's been a minute!).

Wrote up a requirements document and a feature list. The core concept is making task management more interactive and less tedious. Think voice commands, automatic task creation from natural language, smart reminders, etc. But for MVP, the focus is on AI-powered task input and solid to-do list fundamentals.

Thinking about monetization from day one. What features would users actually pay for? Maybe advanced AI insights, super-customizable reminders, or team collaboration down the line. For now, getting a solid free version out is priority.