nyxcore-systems
6 min read

A Marathon Dev Session: Taming Todos, Boosting UX, and Squashing Bugs in One Epic Sprint

Dive into a packed development session where we tackled everything from AI persona enhancements and a powerful todo importer to critical bug fixes and UI polish. Learn from our challenges and celebrate the wins!

developmentnextjstypescriptuxaiproduct-developmentlessons-learnedsqlpwa

Ever had one of those development sessions where you just flow? The kind where the clock seems to warp, coffee becomes fuel, and you emerge hours later with a massive list of "done" items? That was my recent sprint, a focused 04:00 UTC session that saw a mountain of features and fixes go from concept to code.

The goal was ambitious: a multi-feature assault encompassing workflow UX improvements, a smart todo-to-action-point importer, a new project reports tab, a dynamic sidebar heartbeat, and a handful of critical console errors. By the time the dust settled, everything was implemented, type-checked, and ready for commit. Let's break down what made this session so productive and what lessons we learned along the way.

What We Built: A Feature Showcase

This session was about pushing the boundaries of usability and functionality across several fronts.

Elevating Our AI Personas

Our AI-powered system relies heavily on well-defined personas. We gave NyxCore a custom visual identity and significantly enhanced the depth of all 9 personas in the system.

  • Custom Persona Portraits: NyxCore, our flagship AI, received a unique profile picture, adding a touch of personality to its interactions.
  • Persona Specializations Backfill: Every persona now boasts 1-3 specific specializations, a category, and distinct traits. Think "Sasha: System Design/Scalability/Clean Architecture" or "Noor: Vulnerability Analysis/OWASP/Threat Modeling." This granular detail allows our AI to provide more contextually relevant and expert-level assistance.
  • Workflow Compare Persona Labels: To leverage these new specializations, our workflow comparison view now displays persona names alongside their top two specializations. This simple UI tweak provides immediate context, helping users quickly identify the most suitable AI for a given task.

Streamlining Project Management

Projects are at the heart of our application, and we introduced features to make managing them even smoother.

  • Workflow Creation Project Selector: When initiating a new workflow, users can now explicitly link it to an existing project via a new dropdown. This crucial step ensures better organization and project-specific tracking from the get-go.
  • Dedicated Project Reports Tab: A brand new "Reports" tab, complete with a BarChart2 icon, now resides within each project view. This tab lists all completed project workflows and their associated statistics. More excitingly, a "Generate Report" button opens a ReportGeneratorModal, hinting at powerful analytics capabilities to come.

The Todo-to-Action Point Revolution

One of the session's biggest wins was tackling the often-manual process of managing development todos.

  • Automated Todo Importer Service: We developed a robust server-side service (src/server/services/todo-importer.ts) that parses structured markdown files from a todo/ directory. It intelligently extracts key information:
    • Headings like ### N. Title become action point titles.
    • Keywords like Type→category map to specific action categories.
    • P0/P1/P2 translate directly to priority levels.
    • "Prompt Essence" becomes a critical piece of context for the action.
  • Action Points Import Mutation: A new tRPC mutation, importFromTodo, allows users to trigger this import. It intelligently de-duplicates entries by title, flags them as isAutoDetected: true, and appends the extracted prompt essence.
  • "Import todo/" Button: An intuitive button now appears in the "Action Points" tab of any project, both in the empty state and the actions bar, making it trivial to pull in a structured backlog. We even tested it with a 15-item todo/backlog-2026-02-26.md file, confirming its efficiency.

UI/UX Polish & System Heartbeat

Sometimes, it's the subtle touches that make a big difference.

  • Sidebar Heartbeat Relayout: The system heartbeat, previously a bit isolated, has been elegantly integrated inline with the NYX CORE logo in the sidebar. It now features animated token flow direction arrows () that subtly animate in and out when background processes are active. This provides a compact, dynamic visual cue: NYX CORE .... ▸ ● ||||| ▸ 2.
  • Foundational PWA & Favicon Support: We ensured our application looks sharp and is PWA-ready by adding favicon.svg, favicon.ico, and icon-192.png/icon-512.png to the public assets, along with the necessary metadata in layout.tsx.

Critical Bug Fixes

No session is complete without tackling some pesky bugs.

  • Middleware Image Path Fix: Resolved a next/image 400 error where our auth middleware was intercepting requests for public images, redirecting them to login.
  • Dashboard SQL Ambiguity: Fixed an ambiguous column reference (output and digest) in a dashboard SQL query by explicitly qualifying them with their table aliases (ws.output, ws.digest).
  • Nested Button Hydration Error: Addressed a React hydration warning by changing an inner <button> to a <span role="button" tabIndex={0}> within an outer button, adhering to HTML semantic rules.

Lessons Learned: Navigating the Technical Minefield

Even in a productive sprint, challenges inevitably arise. These "pain points" are often the most valuable learning opportunities.

1. The Next.js Middleware & next/image Dance

The Problem: We were seeing 400 "not a valid image" errors for persona portraits. It turned out our next/image optimizer, when trying to access public/images/personas/nyx-persona-profile-pic.png, was being intercepted by our authentication middleware. The middleware, designed to protect authenticated routes, was redirecting these internal image requests to /login, causing the optimizer to fail.

The Fix: The solution was to explicitly add images/ to the middleware's matcher exclusion list. This tells the middleware to ignore requests to /_next/image?url=/images/... paths, allowing the image optimizer to do its job unimpeded.

Lesson Learned: When working with Next.js middleware, always consider its impact on internal routes and static asset serving, especially with built-in optimizers like next/image. Any new public/ subdirectories that next/image might serve will need similar matcher exclusions.

2. SQL's Ambiguous Columns: A Classic Tale

The Problem: In a dashboard query involving a JOIN between workflow_steps (ws) and workflows (w), we encountered a 42702: column reference "output" is ambiguous error. Both tables, it turned out, had a column named output (and digest).

The Fix: The resolution was straightforward: qualify all column references with their respective table aliases. So, output became ws.output, and digest became ws.digest.

Lesson Learned: In any SQL query involving JOINs, it's a best practice to always qualify column names with their table aliases, even if you think they're unique. This prevents ambiguity errors, makes your queries more readable, and future-proofs them against schema changes.

3. HTML Semantics & React Hydration Warnings

The Problem: We had an expand/collapse button nested inside another button within our alternatives card UI. This triggered a React hydration warning: "button cannot be descendant of button." Beyond the warning, this is an accessibility and semantic issue, as interactive elements shouldn't be nested this way.

The Fix: We changed the inner expand/collapse <button> to a <span role="button" tabIndex={0}>. The role="button" attribute tells assistive technologies that the span behaves like a button, while tabIndex={0} makes it focusable and interactive via keyboard.

Lesson Learned: Adhere strictly to HTML semantic rules, especially when dealing with interactive elements like buttons. Nesting interactive elements can lead to unpredictable behavior and accessibility issues. When you need button-like behavior without using a <button> tag, span or div with role="button" and tabIndex is a robust alternative.

Looking Ahead

This session delivered a significant leap forward in functionality and user experience. With these features pushed, our immediate next steps involve thorough QA of all new functionalities, especially the todo import process. We'll also be focusing on crucial security aspects like RLS policies for project_notes and an audit of our safeEnqueue mechanisms for SSE endpoints.

It's always rewarding to see a vision come to life, especially when it involves tackling complex problems and refining the user journey. Stay tuned for more updates as we continue to build!