Frameworks and libraries I use for practical frontend, animation, and full-stack development.
In practical React development, applications are rarely built with React alone. Instead, React is often combined with tools such as Next.js, Tailwind CSS, TypeScript, and purpose-specific libraries depending on the features and goals of the project. Next.js extends React into more practical web application development by making it easier to handle routing, server-side rendering, static generation, API integration, and server-side logic. Tailwind CSS is useful for quickly adjusting designs, making it well-suited for UI prototyping and fine-grained responsive styling. TypeScript improves maintainability by making data structures and value passing between components clearer through static types, while also helping reduce mistakes during development. In addition, libraries such as Framer Motion for animations, React Three Fiber for 3D rendering, React Hook Form for forms, and TanStack Query for data fetching and state management can greatly expand both the expressive power and development efficiency of React applications. Rather than building everything from scratch, using the right tools in the right places makes it easier to maintain development speed while implementing high-quality UI and features. Especially in professional development or serious personal projects, it is important to consider not only visual design, but also performance, maintainability, scalability, and user experience. For that reason, I believe that properly combining frameworks, styling tools, type safety, and UI libraries is not just a matter of convenience. It is an important architectural decision for building web applications that can be maintained and improved over the long term.
Framer Motion, which is now also developed under the name Motion, is a very useful library for implementing UI animations in React. It can handle not only simple fade-ins and slide animations, but also element visibility changes, page transitions, hover interactions, and smooth interpolation when layouts change. These kinds of small movements are closely connected to the overall user experience, and Framer Motion makes them relatively simple to implement. In React applications, the UI often changes in response to state updates. Instead of switching elements instantly, connecting those changes with animation helps users understand what is happening on the screen more naturally. For example, opening and closing modals, displaying cards, showing loading states during page transitions, and reordering list items are all areas where Framer Motion is especially effective. On the other hand, React Three Fiber is a powerful option for handling 3D rendering in the browser. When working directly with Three.js, developers usually need to manage scenes, cameras, lights, meshes, materials, animation loops, and other elements in a more procedural way. React Three Fiber allows these 3D scenes to be organized as React components and built in a more declarative style. However, React Three Fiber requires a slightly different mindset from ordinary UI components. Although it can be written with React JSX, it is actually controlling Three.js scenes and objects behind the scenes. This means that knowledge of 3D-specific concepts such as useFrame, refs, geometry, materials, camera control, and performance optimization is also important. For that reason, it is necessary to think not only in terms of React, but also in terms of Three.js and real-time rendering. For form development, the combination of Zod and React Hook Form is also very practical. React Hook Form is a library for efficiently managing form input state and validation errors, while Zod allows validation rules to be defined as schemas. By combining these two libraries, rules such as “this field is required,” “the value must be a valid email address,” “the text must be at least a certain length,” or “multiple fields must satisfy a specific relationship” can be managed separately from the form’s display logic. Zod also works very well with TypeScript, and one of its major advantages is that types can be inferred directly from schemas. Because form values, validation rules, and submitted data types can be managed close to each other, it becomes easier to reduce implementation mistakes. This is especially useful for features that receive user input, such as contact forms, login forms, post creation forms, and admin dashboard forms, where both safety and maintainability are important. In this way, each library has its own area of strength: Framer Motion is useful for UI motion, React Three Fiber is powerful for 3D rendering, and Zod with React Hook Form is effective for building safer and more maintainable forms. In React development, it is important not to try to solve everything with React alone, but to choose the right libraries for each purpose and design the application with clear separation of responsibilities. Choosing the right libraries not only improves development efficiency, but also leads to better UI quality, more maintainable code, and a better user experience.
Even when implementing full-stack features, it is not necessary to build everything from scratch. In practical React and Next.js development, combining services such as Supabase, Resend, and Stripe makes it possible to build important workflows such as databases, email delivery, and payments with a relatively simple architecture. Supabase is a practical backend platform built on PostgreSQL. It provides features such as a database, authentication, storage, realtime functionality, and Edge Functions, making it suitable for both small personal projects and more serious web applications. When used with Next.js, Supabase makes it easy to manage data such as blog posts, user data, contact form submissions, product information, and application settings in PostgreSQL, while still handling sensitive operations securely on the server side. Supabase also supports Row Level Security, or RLS, which allows access control rules to be designed directly at the database level. For example, it is possible to allow anyone to read only published articles while preventing external access to drafts or admin-only data. This approach does not rely only on conditional logic in the frontend. Instead, it places security rules in the database itself. As a result, it becomes easier to build a relatively safe architecture when separating a public website from an admin dashboard. Resend is a useful email delivery service for implementing contact forms, notification emails, registration confirmation emails, and admin alerts. Running your own SMTP server can introduce many unexpected concerns, such as deliverability, spam filtering, domain authentication, sending limits, and error handling. By using Resend, email sending can be triggered securely from Next.js Server Actions or Route Handlers when needed. However, it is important never to expose the email API key on the client side. The Resend API key should always be handled on the server side, and any content submitted from a form should be validated before processing. In addition, when sending emails from a custom domain, DNS settings such as SPF and DKIM need to be configured so that receiving mail servers can verify that the email comes from a legitimate sender. Stripe is a very powerful service for introducing payment functionality. It can handle complex payment-related workflows such as credit card payments, subscriptions, billing, receipts, refunds, and payment completion notifications through webhooks. Building a complete payment system from scratch would involve significant risks around security, card data handling, legal requirements, and operations. For that reason, it is more realistic to delegate the payment layer to a specialized service like Stripe, while the application focuses on what data should be updated after a payment is completed. Especially for an initial implementation, using a hosted or prebuilt payment UI such as Stripe Checkout makes it possible to introduce a payment flow without building a custom payment screen from the ground up. If more detailed UI control is needed, Payment Intents and Elements are also available options. However, at the MVP or personal project stage, it is usually more important to start with a safe and simple architecture. Stripe provides PaymentIntent as a way to track the lifecycle of a payment, including authentication and payment status management when needed. In this way, Supabase, Resend, and Stripe each take responsibility for heavy parts of full-stack development: Supabase for the database and backend foundation, Resend for email delivery, and Stripe for payments. What matters is not simply adding these services to a project, but deciding carefully which operations should run on the client side and which should run on the server side. API keys, payment processing, email sending, and admin write operations should generally be handled securely on the server. In full-stack development, the architecture can easily become complex as more features are added. However, by combining services like Supabase, Resend, and Stripe appropriately, practical features such as data storage, notifications, and payments can be implemented without making the system heavier than necessary. For personal projects and MVPs, I believe it is more realistic to start small, use reliable external services where appropriate, and design the system so that it can be expanded safely over time, rather than trying to build a large backend from the beginning.