🪟 Windows TippsXDA: I replaced my laptop with a Samsung Fold 8(14.09.2026 um 18:11 Uhr)
🎥 Podcasts9to5Google: Upgrade paths: Pixel 9 to Pixel 11...(03.09.2026 um 17:45 Uhr)
🎥 Podcasts9to5Google: Update Your Pixel Watch ASAP!(03.09.2026 um 17:59 Uhr)
🎥 Podcasts9to5Google: All Wallets are Designed Badly(04.09.2026 um 22:44 Uhr)
🪟 Windows TippsXDA: I replaced my laptop with a Samsung Fold 8(14.09.2026 um 18:11 Uhr)
🎥 Podcasts9to5Google: Upgrade paths: Pixel 9 to Pixel 11...(03.09.2026 um 17:45 Uhr)
🎥 Podcasts9to5Google: Update Your Pixel Watch ASAP!(03.09.2026 um 17:59 Uhr)
🎥 Podcasts9to5Google: All Wallets are Designed Badly(04.09.2026 um 22:44 Uhr)

🔧 Programmierung 🕛 vor 2 Monaten 6 Min Lesezeit
0

Luminary: a NextJS migration story.

↗ Quelle (dev.to)
🗣️ Stimme:
📑 Inhaltsübersicht




Introduction



We're back. After our four-week sprint that took Luminary from a blank repository to a fully functional community platform built in vanilla HTML, CSS, and JavaScript, we regrouped to migrate the entire project to a modern framework.




Luminary is a community-powered directory and news platform celebrating women who are driving change across all fields — business, science, arts, activism, sport, technology, agriculture, education, and more. It allows anyone to nominate or self-submit, is searchable by name and field, and surfaces daily and weekly news of women making impact globally.




For this two-week sprint, we moved Luminary off the vanilla stack and onto a proper application architecture. I would be writing about the migration in general, my role in it, and the lessons I picked up along the way.






The Migration



The old Luminary lived as a set of standalone HTML pages, which we had wired up with its own script and stylesheet. It worked fine, but as the project grows, sharing logic, keeping styles consistent, and integrating with the backend cleanly is foreseen to become hectic.



This sprint we restructured the project into a Turborepo monorepo with two apps — a Next.js (App Router) + TypeScript frontend and an Express + Supabase backend. On the frontend we adopted Tailwind for styling,






Technical Implementation Breakdown





  • Shared form primitives: Extended the common form module into FormField, TextField, FormLabel, and a Base UI SelectField so labels and inputs are defined once and reused everywhere instead of being hand-written per form.


  • Data out of components: Moved form constants — initial state, tabs, and field options — into the data layer, keeping the components focused on rendering.


  • Design system consistency: Replaced raw <button> elements across the tabs, link fields, and collapsible sections with the custom Button component, and added a reusable Drawer wrapper around Base UI's drawer.


  • Service layer: Split the logic into a NominationService and a standalone UploadService, with a private toPayload method and a shared error utility for consistent messaging.


  • Submission flow: Swapped manual try/catch handling for TanStack Query's mutation onError, and conformed API errors to a typed response shape.






Challenges & Resolutions





  • Turning imperative code into components: The original form was built with direct DOM manipulation, so I had to rethink it as composable React components and lift the shared pieces — labels, inputs, button, drawer — into reusable primitives rather than porting the markup one-to-one.


  • Acting on review feedback: A good portion of the week was responding to PR reviews from






    Technical Implementation Breakdown





    • Profile route: Created /directory/[id] as an async server component and rebuilt the old profile.html sections — header, about, and related links — as components using next/image and the original decorative photo frame.


    • Shared mapper: Added a single toNomineeProfile mapper feeding both the directory list and a new getProfileById, normalizing inconsistent URL fields coming back from the API.


    • Image configuration: Allow-listed the remote image hosts in the Next.js config so profile and avatar images render through the image pipeline.






    Challenges & Resolutions





    • Profiles returning "not found": The directory cards were keyed on the nominee id while the detail endpoint looks records up by nomination id, so links never resolved. I aligned both on the nomination id through the shared mapper.


    • The backend wouldn't boot locally: It was missing its environment file, and once that was added the Supabase client still threw — Node.js below version 22 has no native WebSocket, which the client requires, so I added a ws fallback to provide one.


    • A request black hole: Even with the server running, requests never reached it. Port 5000 turned out to be reserved at the OS level on my computer, so the kernel was answering instead of the app. Moving local dev to a free port fixed it instantly, interestingly this was an issue I experienced in the original project stack as well, but had to debug and resolve again as I had forgotten, higlighting the importance of documentation in projects, silly me.






    What I Learned This Week



    This week, from migrating the profile pages, I learnt new methods of integrating a typed frontend with a real API across server components, the value of a single mapping layer between API and UI shapes, and the importance of documentation across project sprints.






    Conclusion



    Two weeks in, Luminary has a more solid foundation — a typed, component-driven frontend, the hard part of the move is behind us. For now, at least, onto the next.






    Github Repository





    -Product Lead 2:

    -Lead Maintainer:

    -Engineering Lead:

    Vollständiger Original-Bericht
    Ausführliche Details, Code-Beispiele & Hersteller-Stellungnahme auf dev.to.
    ↗ Original-Artikel auf dev.to lesen
Wie bewertest du diesen Beitrag?
1 Klick Feedback
Teilen mit Netzwerk & Team:

Community-Analysen & Experten-Meinungen 0

Verfasse deine eigene Analyse, teile Workarounds oder diskutiere diesen Vorfall im Blog.
Noch keine Community-Analyse verfasst. Markiere einen Textabschnitt oder klicke oben auf Eigene Analyse verfassen“!
Community Pulse: Relevanz-Einschätzung
1 Klick Experten-Votum
🔴 Akute Relevanz 0%
🟡 In Evaluierung 0%
🟢 Keine Auswirkung 0%
Spannende Innovation 0%
Verwandte Story-Cluster & Quellen (Vektor-KI)
Port 8095 Engine
2 Quellen
ChatGPT Work, now powered by GPT-6 Astra
2 Quellen
Discovering new antibiotics with ChatGPT
1 Quelle
Sam Altman :‘AGI in 2026’, just as Models Start to [Mis]Train Themselves
Ähnliche Beiträge
🔍 Verwandte News

Auch interessante Nachrichten Luminary: a NextJS migration story.

Thematisch verwandte Begriffe: Luminary, NextJS, migration, story · 6 Treffer

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...