From existing project to digital product: how I built the Energía en Acción web app

How the Energía en Acción project found its digital space: a platform to connect students, mentors and organizations around shared projects.

From existing project to digital product: how I built the Energía en Acción web app

This idea did not start from scratch. Energía en Acción already existed as a project; what it needed was a digital layer that would help better organize its operation.

That's where the web app came in: not as a simple support page, but as a practical tool for everyday use, designed to give more clarity to students, mentors and organizations.

THE STARTING POINT

From the start, I wanted a website that would introduce the project to the public and support the people working within it.

When a student discovers a project and starts taking part, that experience should continue within the same system. The project already existed; it needed a web app to give it an operational structure.

home

WHAT DOES THE APP DO?

The web app is designed to connect students, mentors and organizations. From the beginning it was clear that not everyone should navigate the platform in the same way, because each one arrives with a different need.

Students move from registration to their profile, then on to exploring projects. Once a student applies, the app becomes more than a catalogue: it also provides a place to follow their application.

Mentors have a different journey. They come to support participants, check the projects they are involved in, see who is interested and share updates without relying on external channels.

The platform also considers the role of organizations, although in this first version the main experience is more focused on students and mentors.

catalogue

THE TOOLS I USED

To build the web app I worked with Next.js, React, TypeScript, Prisma and MySQL. Additionally, I used Zod for validations, JWT for session management and Tailwind CSS for the interface.

More than accumulating tools, what I was looking for was a stable technical base to be able to work with roles, data, messaging and different routes within the same application.

HOW I DESIGNED THE ARCHITECTURE

From the start, I wanted to keep the project well organised. I wanted to avoid mixing everything together and making each new feature harder to maintain.

That's why I kept a clear separation between the visual part, the application logic, the API and the data model. That allowed me to move forward with more control and build a small, but well-structured MVP.

AUTHENTICATION, SESSIONS AND ROLES

In an app like this, logging in wasn't the most important thing. The real challenge was deciding well what each person can do and in what context.

The session uses a JWT stored in an httpOnly cookie. The application validates the session and checks the user’s role to control access to routes.

It may seem like a small detail, but on a platform with multiple profiles this type of control is what makes the experience feel truly coherent.

One of the most important parts was to protect the routes well according to the profile. This snippet summarizes how the app checks the session and redirects each user to their correct space.

const PROTECTED = ["/dashboard", "/profile", "/projects/new"];  export async function proxy(req: NextRequest) {   const { pathname } = req.nextUrl;   const needsAuth = PROTECTED.some(     (p) => pathname === p || pathname.startsWith(p + "/")   );   if (!needsAuth) return NextResponse.next();    const session = await readSession(req);   if (!session) {     return NextResponse.redirect(new URL("/auth/login", req.url));   }    if (pathname.startsWith("/dashboard/student") && session.role === "mentor") {     return NextResponse.redirect(new URL("/dashboard/mentor", req.url));   }    return NextResponse.next(); }

It is a small piece of logic, but it helps keep navigation consistent when several roles share the same product.

WHAT MATTERS: REAL USER FLOWS

Beyond the technical part, what interested me was that the app told a clear story of use.

Students move from signing in to their profile, then to the catalogue and dashboard. I wanted to avoid the feeling of “I have applied, but I do not know what happens next.” The dashboard gives them context and helps them follow the next steps.

home

For mentors, the focus is on mentoring. They come in to see projects, detect interest, open conversations and keep track from one place.

Their dashboard is designed as a workspace rather than just an information page.

mentor

At the centre of the platform is the project page, with the description, status, required skills and actions available to each role.

project

MESSAGING AND COMMUNICATION IN THE APP

Another important part was to avoid the collaboration breaking down right after it started. If everything ended up depending on messages outside the platform, the app lost part of its value.

That's why I integrated a system of internal messaging, but connected to the real context of the project and not to a generic logic of contact between users.

For announcements I reused the same messaging system, with an internal flag to distinguish project updates. It was a simple solution that worked well at this stage.

chat

In the messaging part, I opted for a quite pragmatic solution: reuse the messaging infrastructure to send communications linked to a specific project.

const bodyWithFlag = `[BC:P${projectId}] ${parsed.data.message}`;  await prisma.messages.createMany({   data: applications.map((app) => ({     sender_id: BigInt(session.uid),     receiver_id: app.student_id,     body: bodyWithFlag,   })), });  return NextResponse.json({ ok: true, sent: applications.length });

That allowed me to solve a real MVP need without setting up a parallel system just for internal updates.

ONBOARDING IS PART OF THE PRODUCT

In a project with multiple roles, I didn't want people to have to intuitively figure out how to use the platform.

That is why I added guided onboarding tours on key screens such as the dashboards and project catalogue. I saw these as an essential part of the experience.

onboarding

THE REAL PROBLEMS I ENCOUNTERED

As is often the case, the most interesting part was not just building screens, but getting the application to respond well when it started to behave like a real system.

One of the focuses was overall robustness: Authentication, sessions, role protection and response of sensitive endpoints. I wasn't just interested in the app looking good, but also in being reliable when running.

I also addressed specific failure cases, such as the database being unavailable. I wanted the app to handle the failure gracefully and make the cause clear.

Another important adjustment appeared when thinking about the system really working, not just locally with everything perfect. The healthcheck now responds clearly when the database is not available.

export async function GET() {   try {     const [{ now }] =       await prisma.$queryRaw<{ now: Date }[]>`SELECT NOW() AS now`;      return Response.json({ ok: true, database: "up", dbTime: now });   } catch {     return Response.json(       { ok: false, database: "down", error: "Database unavailable" },       { status: 503 },     );   } }

It is not a functionality visible to the end user, but it is one of those decisions that make the difference when it comes to diagnosing, deploying and maintaining an application.

HOW CODEX HELPED ME DURING DEVELOPMENT

Codex was a real help in several phases of the project. It helped me review the structure of the app with more perspective, map routes, components and shared logic, and detect adjustments more clearly.

It also helped me with the more practical part of development, generating implementation snippets and unlocking code approaches that allowed me to move faster.

And it also had an important role in the end: reviewing, validating and transforming part of the technical basis of the project into documentation and explanations that were easier to communicate.

If you would also like to set up your development environment, see this guide to getting the GitHub Student Developer Pack and using Codex in VS Code. 

WHAT I CHECKED BEFORE CALLING IT READY

Before finishing this phase, I reviewed the application as if I were handing it over for validation. I ran lint, and checked the production build and the behaviour of the most important endpoints.

At the application level, the result was encouraging: it compiled, responded and kept its main structure intact. Full end-to-end functionality still required the data environment to be set up correctly.

THE BEST PART OF THE PROJECT

What I like most about the Energía en Acción web app is that it doesn't feel like a sum of disconnected screens.

It has a clear narrative: you enter, discover projects, participate, talk to other people and follow the context from the same place.

CONCLUSION

Building this web app was a way to give digital structure to a project that already had a real base.

More than creating a beautiful website, it was about building a useful tool so that students, mentors and organizations could move with more clarity and less friction.

Energía en Acción app demo

FROM CURIOSITY TO PRACTICE

Your next step starts here.

Put an idea into practice or find people to continue learning with.

Receive new stories in your RSS reader ↗

A story from the Saturdays.AI community. Originally published on March 18, 2026.

← More community stories