Maxim Mikhailov

Web Developer / AI Enthusiast

Main page of the portfolio project


This portfolio website


Last year I've created my first personal portfolio website powered by Next.js and Sanity. Even though it had a lot of cool features, I felt like it was really boring...

Old design of the websiteOne of the projects in old design

Yeah... The main page was almost empty (especially on desktop), the UX was quite bad, the user had to click several times to get to the desired project. It had several issues (e.g. it supported only dark theme), it was unnecessary complex and outdated. Generally I liked it, but it definitely needed an update. When I moved to Åland and bought a new domain, I realized: the time has come. So I've decided to reinvent my personal portfolio website.


As you may have noticed, there's a chatbot on the top of the page. The idea to create it came to my mind while reading the recent OpenAI Dev Day keynotes. OpenAI introduced several new models including a super-cheap version of the GPT-3.5-turbo and, more importantly, GPT-4. I've tried GPT-4 before and was inspired by capabilities of this model, but the price was too high to use in production. But now it's possible!

At the same day, I've started prototyping. The first prototype was done in 2 hours using the amazing Vercel AI SDK. I've already used OpenAI APIs in my projects before (e.g. in forum), but it was pretty complex to implement the right frontend and backend logic to make things work. With this AI SDK, things can be done in minutes and you can concentrate on prompt engineering and design.

The biggest challenge I faced while implementing the chatbot was choosing the right model for the task and defining good internal functions. I wanted the model to be able to contact me when necessary, so I've provided it a command `contact_maxim`, that sends me an email. I thought that GPT-3.5 is capable enough for that. Well, it was a mistake...

First few messages of the botMore messages, messages called after user's "Hi"

I got tons of meaningless messages from the bot about completely irrelevant conversations. Moreover, it started hallucinating and giving the feedback that never existed (like this question about freelance projects). This was happening even after providing more detailed instructions to the model.

First I've fixed the problem by switching to GPT-4. This solution is easy, but not the best. Even turbo version of GPT-4 is too slow and expensive to be used for all requests. It's about 10-20 times more expensive than the new GPT-3.5.

As a better solution I've implemented a two-step algorithm of processing user requests. First, user's request is processed by GPT-3.5. This model is extremely fast and good enough for simple tasks, such as answering user's questions about me. But when trying to use it for something more complex, it's not reliable enough. E.g. it often forgets to ask for contact details or check if the request is meaningful.

When the model wants to contact me, it calls the `contact_request` function, which escalates the conversation to the GPT-4. This model is much smarter, so it can find mistakes that were missed by GPT-3.5. If everything is correct, it sends an email to me using the SendGrid API.

This approach significantly decreased costs, keeping the quality of the responses on the same level.


The frontend is powered by Next.js, Sanity. TailwindCSS.

After almost a year since the initial release, several features of the project were already outdated. E.g. the CMS was deployed as a separate server, which was adding unnecessary complexity to the app. I also had to use pnpm monorepo to share logic between CMS and the actual app. The rendering of Portable Text (Markdown-like solution from Sanity) on the server side was implemented using the pages router with getStaticProps and passing static HTML to props as string (and then inserting it using dangerouslySetInnerHTML. This just did not feel right.

In the update I've migrated from pages router to app router, rewriting my components to be compatible with React Server Components. I've also embedded CMS right into app, so there's no need in monorepo anymore and added daisyUI to support light themes and make centralized theming. And yeah, now there's a preview mode, which is well integrated with Next.js, so it's possible to see the changes in real-time without publishing the post.


The project is still ongoing, I'm adding more features every week, so feel free to provide the feedback. The chatbot is just a few weeks old, so please, don't be too hard on him.

You can ask chatbot to send me a feedback message, or contact me directly using [email protected]