Case study

Fullstack Developer

Medium-clone

Medium-clone

Medium-clone is a personal fullstack project that reimagines how people create, share, and explore articles online. The project focuses on building a seamless web experience with user authentication, article management, and content categorization, all powered by a modern React and Node.js stack.

Medium-clone is a personal fullstack project that reimagines how people create, share, and explore articles online. The project focuses on building a seamless web experience with user authentication, article management, and content categorization, all powered by a modern React and Node.js stack.

Tech stack

Frontend: React, Tailwind CSS, Axios, Markdown-to-JSX


Backend: Node.js, Express.js, Sequelize ORM, JWT, Bcrypt.js


Database: MySQL

My role

Fullstack Developer

Tools

VS Code

Completed

May, 2023

Why I did it

Why I did it

Medium Clone was my first fullstack project, marking the transition from architecture student to software engineer. This project is not just a showcase of my coding skills, but also a demonstration of my ability to tackle a complex project, research and select the right tools, libraries, and solutions to build a functional and maintainable web application.

Medium Clone was my first fullstack project, marking the transition from architecture student to software engineer. This project is not just a showcase of my coding skills, but also a demonstration of my ability to tackle a complex project, research and select the right tools, libraries, and solutions to build a functional and maintainable web application.

What Medium

Clone shows

What Medium

Clone shows

The project provides a complete CRUD system, enabling users to interact with each other through likes, follows, and comments on articles. Articles are displayed in a paginated list (3 articles per page) and can be filtered by tags, making it easy for users to find content. Each user has a profile page displaying their bio and image, with the ability to edit personal information such as their name.

The project provides a complete CRUD system, enabling users to interact with each other through likes, follows, and comments on articles. Articles are displayed in a paginated list (3 articles per page) and can be filtered by tags, making it easy for users to find content. Each user has a profile page displaying their bio and image, with the ability to edit personal information such as their name.

Development Process

Development Process

I started by choosing React for the frontend to demonstrate my skills in building modern, component-based interfaces. I used Vite as the build tool since it’s lightweight and faster compared to Create React App, which relies on Webpack. For styling, I chose Tailwind CSS because it allows easy customization without cluttering the project with multiple CSS files.


For the backend, I selected Express.js because it’s one of the most popular frameworks for Node.js, with great documentation and a large community—making it ideal for showcasing my full-stack development capabilities. The additional libraries were chosen based on necessary functionalities such as user authentication and system management.


As for the database, I decided to use MySQL because it’s widely used, well-documented, and easy to learn, which made it a solid choice for this project.

I started by choosing React for the frontend to demonstrate my skills in building modern, component-based interfaces. I used Vite as the build tool since it’s lightweight and faster compared to Create React App, which relies on Webpack. For styling, I chose Tailwind CSS because it allows easy customization without cluttering the project with multiple CSS files.


For the backend, I selected Express.js because it’s one of the most popular frameworks for Node.js, with great documentation and a large community—making it ideal for showcasing my full-stack development capabilities. The additional libraries were chosen based on necessary functionalities such as user authentication and system management.


As for the database, I decided to use MySQL because it’s widely used, well-documented, and easy to learn, which made it a solid choice for this project.

Example feature in action

Example feature in action

Feature: Article Creation
- I built a form that allows users to create and publish articles.
This feature connects to the backend using Axios and provides form validation.

Feature: Article Creation
- I built a form that allows users to create and publish articles.
This feature connects to the backend using Axios and provides form validation.

const onFinish = async (e) => {
  e.preventDefault();
  const body = { title, content, tags: tag };
  try {
    await axios.post("http://localhost:8000/articles/", body);
    navigate("/");
    window.location.reload();
  } catch (err) {
    setError("Title should not contain spaces.");
  }
};

This function represents the bridge between the front-end and back-end — showcasing how I handled asynchronous requests, error management, and user navigation in a clean and reactive way.

This function represents the bridge between the front-end and back-end — showcasing how I handled asynchronous requests, error management, and user navigation in a clean and reactive way.

Frontend: Article Input Section

- To allow users to write and edit their own articles, I implemented a Markdown editor using React’s controlled components and styled it with Tailwind CSS.

Frontend: Article Input Section

- To allow users to write and edit their own articles, I implemented a Markdown editor using React’s controlled components and styled it with Tailwind CSS.

<textarea
  name="content"
  value={content}
  onChange={(e) => setContent(e.target.value)}
  placeholder="Write your article (in markdown)"
  required
  rows={8}
  className="w-full rounded-md border-0 py-2 text-gray-900 
             ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 
             px-2.5 focus:ring-2 focus:ring-yellow-600 resize-y"
/>

This snippet demonstrates how I handled state, validation, and styling directly in JSX using Tailwind CSS. It’s a simple but key part of the article creation feature that brings the writing experience to life.

This snippet demonstrates how I handled state, validation, and styling directly in JSX using Tailwind CSS. It’s a simple but key part of the article creation feature that brings the writing experience to life.

Backend Logic: Article Creation & Tag Management
- This part of the project handles how a new article is created and connected to its related tags. It showcases how I handled data validation, database relations, and asynchronous operations using Express.js and Sequelize.

Backend Logic: Article Creation & Tag Management
- This part of the project handles how a new article is created and connected to its related tags. It showcases how I handled data validation, database relations, and asynchronous operations using Express.js and Sequelize.

const addArticle = async (req, res) => {
  const { title, content, tags } = req.body;
  const hashtag = tags.split(",");

  // Validate: title must not contain spaces
  if (title.includes(" ")) {
    return res.status(400).send({ message: "Title should not contain spaces." });
  }

  // Create a new article
  const newArticle = await db.Article.create({
    title,
    content,
    user_id: req.user.id,
  });

  // Manage tags and relationships
  const newTag = await Promise.all(
    hashtag.map(async (tagName) => {
      const [tag] = await db.Tag.findOrCreate({ where: { name: tagName } });
      const foundTag = await db.ArticleTag.findOne({
        where: { article_id: newArticle.id, tag_id: tag.id },
      });

      if (!foundTag) {
        await db.ArticleTag.create({
          article_id: newArticle.id,
          tag_id: tag.id,
        });
      }

      return tag;
    })
  );

  newArticle.setDataValue("tags", newTag);
  res.status(201).send(newArticle);
};

This logic handles article creation and tag management in Express and Sequelize, showcasing how I managed validation, relations, and clean database structure.

This logic handles article creation and tag management in Express and Sequelize, showcasing how I managed validation, relations, and clean database structure.

Want to see more code

Want to see more code

Github

Github

Showcase UI

Showcase UI

Let's make

something

meaningful together

wiriya.oran@gmail.com

Open for freelance & collaboration opportunities.

Oran Wiriya

© 2025 All rights reserved.

Let's make something

meaningful together

wiriya.oran@gmail.com

Open for freelance & collaboration opportunities.

Oran Wiriya

© 2025 All rights reserved.

Create a free website with Framer, the website builder loved by startups, designers and agencies.