# Grayhat Blog Author: Aniqa Sadaf > Expanded public blog context for posts by Aniqa Sadaf. ## Page - [Aniqa Sadaf Author](https://grayhat-company-blog.grayhatstudio.workers.dev/blog/author/aniqa-sadaf) - [Aniqa Sadaf Author LLM Context](https://grayhat-company-blog.grayhatstudio.workers.dev/blog/author/aniqa-sadaf/llms.txt) - [Root LLM Context](https://grayhat-company-blog.grayhatstudio.workers.dev/blog/llms.txt) - [Root Full LLM Context](https://grayhat-company-blog.grayhatstudio.workers.dev/blog/llms-full.txt) - [Author API](https://grayhat-company-blog.grayhatstudio.workers.dev/blog/api/public/v1/authors/aniqa-sadaf) ## Author Details - Name: Aniqa Sadaf - Location: Rawalpindi, Pakistan - Website: Not provided - Post count in current snapshot: 2 - Bio: Product Designer 1 at Grayhat ## Current Posts - [Our struggles (and minor wins) with Rive for character animation in 2025](https://grayhat-company-blog.grayhatstudio.workers.dev/blog/our-struggles-and-wins-with-rive-2025) - Inspired by Duolingo, we also gave the beta Rive Editor a try to make our AI virtual friends in MindChat come alive. TLDR; It didn't go too well. - [Reflections from executing a Design Sprint](https://grayhat-company-blog.grayhatstudio.workers.dev/blog/reflections-from-executing-a-design-sprint) - How we (partially) applied the Google Design Sprint Kit in a project, and its reflections. ## Child Route Content ### [Our struggles (and minor wins) with Rive for character animation in 2025](https://grayhat-company-blog.grayhatstudio.workers.dev/blog/our-struggles-and-wins-with-rive-2025) - Slug: `our-struggles-and-wins-with-rive-2025` - Published: 2025-11-06T14:00:03.000+05:00 - Updated: 2025-11-19T23:03:41.000+05:00 - Reading time: 5 min - Tags: Animation, Design, AI, Artificial Intelligence, Flutter, Developer Tools, Design Tools - Authors: Saad Bazaz, Abdurrehman Subhani, Aniqa Sadaf, Talal Ahmed Khan, Wasif Sadiq, Muhammad Usama Rashid - Visibility: public Grayhat first met the Rive team at GDC 2024. Early startup energy, cool booth, tons of hype. At the time, we already knew about Rive, but we hadn’t actually battle-tested it in any real production scenario. It looked promising, and we filed it away as a “maybe one day” tool. *Fast forward to this year... We finally decided to give it a real shot. ## **Solly, Our First Rive Experiment** Our first test was simple. We built an animated mascot named **Solly** for MindChat. Just a cute, lively animation. It turned out pretty solid. *An animated Solly, the mascot for MindChat.In our hubris, we decided to go big. Not just animated characters. We wanted **full lip-sync and animated avatars reacting in real-time during video calls**. That’s when our rabbit hole journey began. ## **Research and Learnings** To understand what “good” looks like, we researched teams already doing this at scale. We studied Duolingo’s approach to visemes and character speech, which instantly made them our north star. We also pored over Guido Rosso's breakdown of how Duolingo uses GenAI and Rive for more technical insight. It's an excellent blend of art and tech, I highly recommend watching it: *For character structure and workflow inspiration, we found Tolan’s process incredibly useful, detailed in their post on designing their character. We also dove into the broader concepts of phonemes and visemes, looking at established solutions in the 3D space like Reallusion's iClone for AI-powered lip-sync. Enough theory, let's build. ## **Intersecting art and tech (Rive + Flutter)** To get hands-on, we learned the basics through foundational tutorials like this Rive in Flutter video and this more advanced follow-up. Community tips, like this Reddit thread on a better way to animate, and the official Rive best practices guide were essential reading. Then we got our hands dirty by running our first interactive test. We replaced the Interacting Bear Demo from GitHub with the Monster Mouth (found on the Rive Marketplace), and lipsynced it. *At this point, we were feeling pretty confident. We started exploring Rive's marketplace for rigs, especially mouth rigs and lip-sync templates: - Mouth Movement Rig - Custom Talking Avatar Lip Sync - Karaoke with Zari - Monster Mouth - Wave, Hear and Talk - Mouth Rig We built our own character in a flat, simple style so iteration would be fast. ## **Nested Artboard Hell** Then came the pain. Nested artboards. Calling inputs inside nested rigs from the parent board. This should have been trivial, as most of our designers came from an Adobe After Effects and Sony Vegas background. Instead it became a multi-day excavation. We even built a minimal reproducible Rive file just to understand the problem first, with data binding and nested artboards. We searched everywhere for answers. We scoured Stack Overflow for solutions, read through Reddit threads where users lamented broken nested animations, and followed a critical GitHub issue in the rive-flutter repository that highlighted our exact problem. The Rive community forum had a thread on passing input values that never got a definitive answer. Finally, we found a random deep-internet video that solved it. From Rive, but not on the surface. Not from official docs. Just some obscure YouTube video that succeeded where the actual product failed to explain itself. *And that’s when it hit me. Rive is not designed for professionals yet. Rive is built for early adopters, vibers, Behance-Dribbble motion designers, landing page razzle dazzle, and social media loops. Not structured engineering-grade animation pipelines. Anyone doing real character systems will eventually hit architecture problems. Rive isn’t there yet. But we were too deep in this to give up. ## **Building Our Own Playground** Once we finally got our rig working, we wanted to test it with our custom lip-sync algorithm. We tried using the third-party playground, rive.rip. Cool idea, but feature-limited. Not useful for live algorithmic testing. So we built our own playground in Flutter, specifically for real-time lip-sync with AI voices and Rive characters. You can find the source code for our Rive Playground on GitHub. And here is the deployed version you can play with: * Drag to resize ⤡ Open in new tab (function(){ var box = document.getElementById('rive-resize'); var iframe = box.querySelector('iframe'); var handle = document.getElementById('rive-resize-handle'); var minW = 200, minH = 200; // If Ghost gives width:100% (or if you want it to *look* full-width initially), // set a pixel width equal to the parent's computed width so the element can be resized. function setInitialWidth() { try { var pw = box.parentElement.clientWidth || document.documentElement.clientWidth; // Use parent's width but not less than minW box.style.width = Math.max(minW, Math.min(pw, 700)) + 'px'; } catch(e) { /* ignore */ } } // Initialize setInitialWidth(); // Recompute if window changes (keeps sensible starting width) window.addEventListener('resize', setInitialWidth); var dragging = false; function startDrag(e) { e.preventDefault(); dragging = true; // allow mouse events to reach document while still interacting with iframe iframe.style.pointerEvents = 'none'; window.addEventListener('mousemove', onDrag); window.addEventListener('mouseup', stopDrag); window.addEventListener('touchmove', onDrag, { passive: false }); window.addEventListener('touchend', stopDrag); } function onDrag(e) { if (!dragging) return; e.preventDefault(); var clientX = (e.touches && e.touches[0]) ? e.touches[0].clientX : e.clientX; var clientY = (e.touches && e.touches[0]) ? e.touches[0].clientY : e.clientY; var rect = box.getBoundingClientRect(); var newW = Math.max(minW, clientX - rect.left); var newH = Math.max(minH, clientY - rect.top); box.style.width = newW + 'px'; box.style.height = newH + 'px'; } function stopDrag() { dragging = false; iframe.style.pointerEvents = ''; window.removeEventListener('mousemove', onDrag); window.removeEventListener('mouseup', stopDrag); window.removeEventListener('touchmove', onDrag); window.removeEventListener('touchend', stopDrag); } handle.addEventListener('mousedown', startDrag); handle.addEventListener('touchstart', startDrag, { passive: false }); // optional: double-click handle to snap back to parent's width handle.addEventListener('dblclick', setInitialWidth); })(); ## **Final Result** We managed to make our animation work, with nested artboards and lip-sync. Check it out here: *It's still a work-in-progress, but we continue to learn and improve. ## **The Rive Reality Check** After this entire journey, here’s the honest breakdown. ### **The Cons** - The interface is unintuitive and tries too hard to cosplay as Figma without earning it. - Features like components and preview mode feel half-baked. - Pricing is preposterous, especially when they suddenly made exports paid mid-project. - Performance is unoptimized and multiplayer is buggy. - Browser sync pauses make it feel clunky instead of modern. ### **The Pros** - It works, at least in Beta terms. - Web-based. - Collaborative. - Fun for simple animation use cases. ### **My Verdict** If you already have working pipelines in Blender, After Effects, Spline, or your own tooling, stick with them. Rive is cool, but it is not ready for serious production beyond funky assets, splash animations, and loading screens. I still believe Rive should eventually be acquired by Figma and merged into a full pipeline. But if I see them pull a “we’ll stay independent forever” move like Figma did with Adobe, my remaining hope will evaporate. To anyone from the Rive team: If you're reading this, I'd love to talk and have a feedback session on our team's experience on the Paid plan. Maybe we can find a better way out! Peace ✌️ *Credits to:* - Umayma binte Saleem, our Web, Interactions and Graphics intern, for the first Solly animation - Ayesha Aamir (UI/UX Designer) for her research, character design and animation implementation - AbdurRehman Subhani (Lead Engineer) for building the open source Playground, and developing the lip sync algorithm with AI - Aniqa Sadaf (Product Designer) for world-building ### [Reflections from executing a Design Sprint](https://grayhat-company-blog.grayhatstudio.workers.dev/blog/reflections-from-executing-a-design-sprint) - Slug: `reflections-from-executing-a-design-sprint` - Published: 2025-10-30T14:00:46.000+05:00 - Updated: 2025-10-30T14:00:46.000+05:00 - Reading time: 5 min - Tags: Design, Product Design, UI, UX - Authors: Aniqa Sadaf - Visibility: public We're experimenting hard in Grayhat right now to figure out a design flow that actually *works*. We're throwing everything at the wall, trying out all the best practices, using both physical tools (like, chart papers on walls, stickies, real Kanbans, paper and pens... the works) and digital ones (Figma, obviously 💃), and seeing how far we can push AI to help us out. We're not starting from zero, though. We're taking a lot of inspiration from the Google Sprint Kit and mixing it with solid SDLC/GDLC principles. It's important that we first learn the basics, and don't reinvent the wheel. We started with a startup, called Camply (now it's called Enrichly). We were in the "Planning Phase," just trying to figure out what we were even building, who for, and what problem it was going to solve. Camply is a web app for finding and signing up for camps, and the whole goal was to make it super smooth and hassle-free for customers. Our main focus was on fixing two big pain points for users. To do that, we had to dive into research - checking out competitor websites like Outschool, Allschool, you know, the ones our client used and recommended. The cool part was our client *was* the user, so she knew exactly where all the problems were on these other sites. She was our Onsite Customer. I moodboarded all these competitor sites in Figma. Compared their features, their flows, what worked and what totally didn't. From talking to our client and looking at the pain points, we realized we needed a design that was just… intuitive. Something that guides the user on its own, you know? Easy to understand and just fixes their problems. We had a bunch of features to think about - camp listings, search and filters, authentication, all that. But with the budget and timeline, we had to pick what would have the biggest impact. We narrowed it down to the search mechanism. We really had to put our brains into designing the best search. We even looked at sites like Amazon because, let's be honest, their search is just good, and users are familiar with the patterns in it (especially moms!). Then came the system design phase. The team set milestones and planned out the Camply flow for the POC. We had a ton of collaborations just to make sure the design and the tech architecture were compatible and could actually solve the business problems. We did the usual stuff - daily standups, cross-disciplinary meetings, weekly sprints, design handoffs. During the design phase, I made user personas for the "parent" and the "camp manager." Started with rough sketches, got initial client feedback, and discussed everything with the team. I had to constantly update the system architect on every little design change so we could track compatibility. Every design decision I made, I had to be sure it could actually be built well and on time. After the initial sketches (which we did with the system architect using paper and colored pens, lol), I turned them into wireframes in Figma and got the client's feedback. Once the flows were locked, I moved to high-fidelity prototypes. I used the Material Design library because it's neat, has great guidelines, and makes everything consistent. Client feedback was a constant loop until everything was finalized. Once the functional Figma prototypes were ready, we shipped them to the business team. They did the initial user surveys and interviews to test the designs. That led us into the development phase. When development started and the first version of the app went live, I was deep in design QA. I had to make sure the experience was smooth, the flows were accurate, and all the features worked as designed. We recorded all the issues, prioritized them, and got them fixed by the devs systematically. After version one was out, we planned to test it with real users: usability testing. Usability testing is ideal to: - Validate your hypothesis - Fix issues before the big launch - See how users actually use your product vs. a competitor's You should do it at every step. Depending on the stage, you ask different questions. There are three main times to ask users questions: before the test (to screen them), during the test (to answer your research questions), and after the test (for overall feedback). The most important thing? You gotta have the *correct audience*. Not everyone is your user. So you do a quick screening test first with questions like: - How does your everyday life look? - How often do you use products like this? - What do you identify as? etc. Then, during the test, your questions shouldn't lead the user. Let them think aloud. You just watch them interact, notice their body language, and ask things like: - I noticed you did [this action], why so? - What features do you find the most valuable? - Can you try performing [this specific action]? After the test, you ask more open questions: - How was your overall experience? - How likely are you to use this product? And as a designer, you HAVE to note the "critical incidents." - You expected the user to do one thing, but they did something totally different. - They seemed frustrated, or happy, or confused. - You assess what was a success and what was a failure. Tools like website heatmaps also help a ton. They show you the hottest areas on your site - where people click, scroll, move. It helps you understand where to focus on improving the experience. And lastly, you HAVE to document all the test feedback properly. Spreadsheets, screen recordings, audio notes… everything. You'll be amazed at what you notice when you rewatch it. So what do you do after usability testing? You analyze all that data. Look for patterns and common pain points. You need to look at both the numbers (quantitative data, like task completion rates) and the observations (qualitative data). Then you make informed decisions. But listen, NOT EVERY ISSUE IS IMPORTANT. You have to prioritize. Think about how often a problem happens, how much it messes up the user experience, and the potential ROI for fixing it. Collaboration between design and dev is crucial here. You gotta discuss possible solutions together. And then you make iterative changes. Don't try to fix everything at once. After you've made the initial changes, you go for another round of testing. See how the experience has improved and track the data. **So what could we have improved?** In our case, we did apply the best practices for usability testing. We went through all three stages, but we didn't record the feedback in a systematic way. Which led us to just assume we had to change everything a user didn't like. We really needed to group the common user issues and prioritize them properly. And you can't forget that as you move from a POC to an MVP, the client always has new feature demands. If we had recorded what needed to be worked on *after* the usability testing, and also tracked the new features, in a proper, systematic way… it would have led to a much happier client and way more realistic deadlines. We still have a long way to go... We're trying to incorporate technologies like Dev Mode, AI, scripting and more. Also, our Design offering has expanded beyond just UI/UX: We now also focus on Graphic Design, Character Design, Animation and more (coming soon - 3D is exciting!). I'd love to learn more about what your design process is, and how you think we can improve. ## **Some resources** - https://designsprintkit.withgoogle.com/ - https://designlab.com/blog/guide-to-usability-testing-methods - https://designlab.com/blog/what-is-the-ux-design-process - https://www.lyssna.com/guides/usability-testing-guide/usability-testing-methods/ - https://www.lyssna.com/blog/website-heatmaps/ - https://www.linkedin.com/pulse/next-steps-after-conducting-ux-testing-your/