Thomas Ortega - Portfolio

Thomas Ortega - Portfolio

EN ES

Building a Portfolio: Four Iterations of Learning

Building a Portfolio: Four Iterations of Learning

Published on: 10/23/2024

Updated on: 10/24/2024

Without getting into whether having a portfolio is recommended or not, I'd like to share my experience developing my latest one. It's the fourth iteration I've made over three years, and each version has taught me something interesting. Before diving into the details of the current version, I'll review the previous iterations, as they helped me define the requirements that would eventually shape the final version.

The Path to a Functional Portfolio

First Steps: Python and Flask

I built my first website with Python and Flask before starting my vocational training. This version had two fundamental problems that made it impractical in reality:

  1. Flask, being a server technology, presented some drawbacks. It's not that Flask is a problem itself - it's an excellent tool for what it's designed for - but for a portfolio, it's excessive. I could have added plugins to handle content to avoid doing everything manually, and avoid redeploying every time I updated projects, but it still didn't seem like a long-term solution.
  2. The free online deployment options weren't worth it or simply no longer exist. Initially, I used Heroku's free tier, but the page took forever to load, and the server would fail every few days, forcing me to reinstall everything and redeploy. The last straw came when Heroku eliminated its free tier, apparently because some users were abusing the service by chaining multiple accounts instead of paying. The alternative services I tried were even slower. The lesson was clear: nowadays, it's not practical to depend on servers if you don't really need them.

Experimenting with WordPress

WordPress, the CMS that probably needs no introduction, was my next attempt. Many of the websites we visit daily are managed with this technology, and there's a reason for that. However, for my specific needs, it presented several drawbacks:

  1. Again, we ran into server dependency. Deploying the open-source version wasn't practical for a portfolio, and the free version, while it worked in a pinch, left much to be desired in terms of performance.
  2. The styling and layout customization options seemed very limited and had too much boilerplate. And for the use I wanted to give the website, it had too many installed plugins that I wasn't going to use.

However, there was something I loved: having a content manager. It reminded me of the good old Blogger days and solved the problem I had with Flask of having to do everything manually.

Defining Key Requirement

From these initial experiences, I could extract several fundamental requirements:

  • The page had to be static
  • It needed optimal performance
  • It needed a content management system
  • The frontend had to be easy to maintain

With these requirements clear, I embarked on a search for technologies that would fit my needs. It's common sense: it's more efficient to use a tool designed for the type of development you're looking for than to force the tools you know to meet requirements they're not designed for.

The Evolution: Strapi and Next.js

The solution I found was to split the project into two parts: a backend with a minimalist CMS (Strapi) and a frontend that could generate static pages. While researching (though not thoroughly enough, as I would later discover), I found three candidates: Hugo, Next.js, and Astro.

The Strapi Experience

Strapi turned out to be a pleasant surprise. If you've worked with WordPress, Strapi's admin console will feel incredibly intuitive. The process is simple: you create your content types (single or collections), add the necessary elements (text, multimedia, etc.), and can relate them to each other as needed. All this backed by an SQLite or PostgreSQL database, depending on your preference.

Data interaction is managed through user permissions and REST API. Although I'm using Strapi 4, I recommend starting directly with version 5 for new projects, as it includes significant improvements in basic components and improved GraphQL support.

The Next.js Adventure

I initially chose Next.js for its extensive documentation and abundance of tutorials. However, this is where my most significant experience with AI in development began, but I'll talk about that later.

I made two crucial mistakes:

  1. Not making an early prototype that included all my requirements and not testing the functionalities that could cause the most problems at the project's start.
  2. Trusting tutorials and AI too much without thoroughly reading the framework's specification and its limitations.

I lost three weeks implementing a website that, contrary to my intentions, wasn't really static. When I finally understood the problem, I spent another week trying to convert the project into a truly static one.

After I stopped using Next.js, I found something that made me think a lot about how much we need to understand the frameworks we use. In this case, Next.js belongs to Vercel, which, if you don't know, is a hosting platform, to put it very generally. Next.js works better when you use Vercel than when you want to use it on your own. In my case, it's not just that the framework wasn't designed to generate 100% static content, but also that when trying to do so, I kept having to patch different levels of the application and couldn't meet the requirements 100%. I recommend watching this video to understand what I'm talking about.

The Final Solution: Astro

Finally, we come to the second component of this portfolio. Astro isn't so different from Next.js if we speak very generally - it's a framework for creating websites or maintaining routing, depending on how you want to look at it. Because really, depending on the dependencies and tools you use, these solutions can be an all-in-one or simply a base module.

For example, Astro is compatible with React, Vue, and other frameworks, but it also implements its own way of creating components. You can replace the routing it offers with another package, and so on. What convinced me was that it was better documented than Hugo and could maintain all the functionalities I needed, including some I hadn't mentioned before, like a native package for implementing internationalization.

This time, learning from my mistakes, from minute zero, I implemented a prototype that included all the functionalities I had in mind. I did a local build and deployed it on a basic HTTP server. Only when I got everything working (because packaging some files also required giving the topic quite a few turns), did I launch into developing the entire website.

For the final implementation, I used:

  • Astro pages and components to generate static content and routing
  • React for the music player, specifically the 'react-h5-audio-player' package and for rendering Strapi's rich text block
  • Prism.js for code's syntax highlighting
  • Other minor dependencies for specific functionalities

The AI Experience: Developing a Critical View

As I mentioned earlier, the quality of search engine results has dropped considerably, making it increasingly tedious to find useful resources beyond official documentation, especially when you're not familiar with the tools you're using.

Using LLMs

During development with Next.js, I decided to bet heavily on AI. I started with ChatGPT, but even with a paid account, the quality of its responses had notably decreased. I switched to Claude, which worked better, but still fell into similar problems:

  • Frequent context loss
  • Repetition of solutions that had already proven not to work
  • Tendency to return to discarded suggestions after a few messages

A Change in Perspective

Until then, I had used LLMs as a "glorified chatbot" for specific tasks such as:

  • Generating test data from database DDL
  • Creating basic XML from XSD
  • Writing boilerplate with reference implementations
  • Translating or compacting documentation

However, not knowing JavaScript in depth, my dependence on LLMs increased considerably. I was no longer in charge - I was subject to the variable quality of the responses I received. In retrospect, the time I thought I was saving wasn't really saved. If I had invested that time in properly learning JavaScript, I probably would have finished the project in the same time, with the benefit of learning some JavaScript.

Lessons About Using AI in Development

It's important to clarify: if what you want to create is a common application, you won't have many problems with AI. But when your requirements become more specific or the project grows - as in this case with internationalization, build-time route generation, API-based components, multimedia packaging - the project is no longer the same monolithic block as before. And this is where we start to brush up against the limits of what an LLM can handle without starting to hallucinate every two or three messages.

Can it be done? Of course. Should you? In my case, I don't think so. Not only have I had to invest a lot of time, but in the end, I haven't learned as much as I expected. Probably, if I hadn't depended so much on AI, I would have noticed the flaws I found in the Next.js version sooner.

Final Reflections

This experience has led me to some important conclusions:

  1. About Development: It doesn't matter what tool you work with and how much you think you know - you need to study well how things work and make small prototypes that implement all possible requirements. This ensures that the time we're going to invest is being put into a tool capable of solving our problem.
  2. About AI: I'm going to limit the use of artificial intelligence, particularly LLMs, as much as possible. Its use will be what I gave it almost two years ago: boilerplate, boilerplate, boilerplate, and always for very concise and specific things.
  3. About the Current State of AI: Significant advances seem to be made more by brute force than by fundamental improvements in the models. If technical improvements are subordinate to training with more and more data, without offering an equally substantial return, then what they're selling us today could be more smoke than reality.

I hope something I've shared here proves useful in your own development journey. Sometimes, the greatest learnings come from our stumbles and from being willing to question our own assumptions about the tools we use.

PS: You can find the song used in the audio player here. As for the shader to visualize the music, I made it using shader-toy using this tutorial as main reference. Maybe I'll talk about shaders and audio visualization once I get more experience on the topic.