
Three JS - Simple Shelf Builder
This project is an experiment with Three.js and React-Three-Fiber. It's a shelf builder. With this project, I want to learn how to rescale models and manipulate them in the scene using external controllers.
2025-03-21
A simple image converter that allows you to convert images to different formats, optimizing them in the process. The project is built with Next.js and uses a server action to process the images.
Resources:
Sharp documentationThis article explains how to build a simple but powerful image converter using Next.js. The application allows users to upload images, convert them to different formats (such as AVIF, WEBP, and PNG), and download the results.
The image converter is a web application where users can:
The main motivation behind this project was to create a fast and easy-to-use tool for optimizing images for the web. As a web developer, I often need to convert images to modern, efficient formats like WebP or AVIF to improve website performance. This tool streamlines that process.
This project is built on a selection of modern web technologies, chosen for their performance and developer experience:
File
objects and FormData
. It helps catch errors early and makes the code more robust and maintainable.The image conversion is handled by a Next.js server action. Here’s a high-level overview of the process:
sharp
library to convert each image to the desired format in memory.Here is a snippet of the server action responsible for the conversion:
// Core conversion logic using sharp
import sharp from "sharp";
const SHARP_FORMAT_MAP = {
JPEG: (instance: sharp.Sharp) => instance.jpeg({ quality: 80 }),
PNG: (instance: sharp.Sharp) => instance.png(),
WebP: (instance: sharp.Sharp) => instance.webp({ quality: 80 }),
AVIF: (instance: sharp.Sharp) => instance.avif({ quality: 80 }),
};
async function convertImage(
buffer: Buffer,
format: keyof typeof SHARP_FORMAT_MAP
) {
const sharpInstance = sharp(buffer);
const transformer = SHARP_FORMAT_MAP[format];
if (!transformer) {
throw new Error(`Unsupported format: ${format}`);
}
return transformer(sharpInstance).toBuffer();
}
This approach uses a map to associate each output format with a specific Sharp transformation. This makes the code clean, extensible, and easy to maintain when adding new formats.
The UI is built with React and Tailwind CSS, focusing on a clean and intuitive user experience. Key components include:
The DropZone
component, built with the react-dropzone
library, provides a simple way for users to select their images. It supports both drag-and-drop and the traditional file explorer.
export const DropZone = ({ setFiles }) => {
const onDrop = useCallback((acceptedFiles: File[]) => {
// Handle file size validation and update state
}, [setFiles]);
const { getRootProps, getInputProps, isDragActive } = useDropzone({ onDrop });
return (
<div {...getRootProps()}>
<input {...getInputProps()} />
<p>
{isDragActive
? "Drop the files here..."
: "Drag and drop your images here or click to select"}
</p>
</div>
);
};
Once files are selected, the FileRow
component is responsible for displaying each file's information, including its name, size, and the controls for conversion. It also shows the conversion status and provides a download button for each successfully converted file.
export const FileRow = ({ file, format, setFormat, onRemove, convertedFile, status }) => {
// ... component logic
return (
<div className="file-row">
<span>{file.name}</span>
{status === "converted" && convertedFile && (
<button onClick={handleDownload}>Download</button>
)}
{/* ... other controls ... */}
</div>
);
};
The Converter
component is the main component that orchestrates the entire process. It manages the state of the files, handles the conversion logic, and renders the other UI components.
export const Converter = ({ files, setFiles }) => {
const [convertions, setConvertions] = useState([]);
const handleConvert = async () => {
// ... logic to call the server action
};
// ... other handlers and effects
return (
<div>
{/* ... UI for global actions ... */}
{convertions.map((convertion, index) => (
<FileRow key={index} {...convertion} />
))}
</div>
);
};
The UI is designed to be responsive and works well on both desktop and mobile devices.
This project is a great example of how to use Next.js server actions to build a full-stack feature. It combines a modern frontend with a powerful backend to create a useful tool for image conversion.
Feel free to try out the image converter and explore the source code to learn more about the implementation.
Want to see more?
Three JS - Simple Shelf Builder
This project is an experiment with Three.js and React-Three-Fiber. It's a shelf builder. With this project, I want to learn how to rescale models and manipulate them in the scene using external controllers.
2025-03-21
Three JS - Basic Character Controller
This project is my first experience with Three.js and React-Three-Fiber. It's a simple basic character controller that I built to learn the basics of 3D rendering and game development. The original code and models were taken from: @WawaSensei tutorial in youtube and modified to fit my needs.
2025-03-14