A modern fullstack Next.js + Supabase application for managing Notes, Blog Posts, and User Profiles with Tags and Media Uploads.
# Install dependencies
pnpm install
# Create .env file
cp .env.example .env
# Configure environment variables inside .env
# Run development server
pnpm dev
Supabase CLI is required to run the database locally. You can install it using the following .
# Install Supabase CLI
brew install supabase/tap/supabase
# Upgrade (if already installed)
brew upgrade supabase
# Login
supabase login
# Press enter to open the browser and login to your Supabase account
# paste the OTP code into the terminal
# Try to run the command
pnpm gen:types
- Next.js 14
- HeroUI
- Tailwind CSS
- Tailwind Variants
- TypeScript
- Framer Motion
- next-themes
- Supabase
- MDXEditor
- ZOD
- 🔥 Authentication (Supabase OAuth / Email)
- 📝 Create and manage Notes
- 📰 Create, edit, delete Blog Posts
- 🏷️ Tags management
- 📂 Upload and manage images
- 👤 User Profile update
- 🎨 TailwindCSS UI
- ⚡ Fast and typed APIs (TypeScript + Zod)
- 🧹 Linting (ESLint, Prettier, Husky hooks)
- Framework: Next.js (App Router)
- Styling: TailwindCSS
- Authentication: Supabase
- Database: Supabase Postgres
- Language: TypeScript
- Validation: Zod
- Code Quality: ESLint, Prettier, Husky
.
├── app (API routes, pages and layouts)
├── components (components grouped by purpose: form, ui, etc.)
├── config (configuration files, constants etc.)
├── hooks (custom react hooks)
├── lib (utility functions: next, api, supabase, zod, etc.)
├── public (public assets)
├── server (server-side logic: actions, services, etc.)
├── styles (global styles, tailwind config)
├── types (typescript types grouped by entity or purpose)
└── validators (entity validators using zod)
Use this route group as a way to group routes that are only accessible to authenticated users.
- login
- /blog
- /create
- /edit/[id]
- /notes
- profile
- tags
[GET]
/api/auth/callback
– callback route for the OAuth providers;[GET]
/api/auth/confirm
– confirm the email OTP and redirect the user to the next page;[DELETE]
/api/posts
– delete a blog post by id;[DELETE]
/api/notes
– delete a note by id;[POST]
/upload
– upload an image to the supabase storage;
- /blog/[slug] – view a blog post by slug;
- /blog – view all blog posts;
In the application, interaction with the server-side can be managed through two primary methods: server-actions and browser requests to API
endpoints. Each method leverages the entityService
as an entry point, ensuring consistency in how data is managed and operations are
performed.
Server-actions are methods defined on the server that directly handle the lifecycle of requests—from parsing data to calling service methods and formatting responses. This approach is considered the default and recommended for its ability to tightly integrate with server logic and services.
Example Usage:
import { postCreate, postUpdate } from '@/server/actions/post';
const DummyExample = () => {
const [response, formAction] = useFormState(action, { statusText: '', status: 0, data: null });
return (
<Form action={formAction}>
<Submit />
</Form>
);
};
- Direct access to server resources and services.
- Efficient handling of data validation and transformation.
- Consolidated error handling and response formatting.
Browser requests are a simpler and more straightforward method where the frontend sends HTTP requests directly to defined API endpoints. These endpoints parse the requests, perform operations via the entity services, and send back the responses.
Example Usage:
import { useApi } from '@/hooks/useApi';
export const DeletePostButton = ({ id }: TPostId) => {
const [deletePost, pending] = useApi<TPostId>('delete', 'posts');
return (
<Button isLoading={pending} onClick={() => deletePost({ id })}>
<Trash />
</Button>
);
};
- Less code, ideal for simple CRUD operations.
- Supports all HTTP methods.
- Manages request states using React's useTransition for smooth user experiences.
- Automatically refreshes components or pages upon request completion.
Both methods, server-actions and browser requests, are effective for interacting with the server-side but cater to different needs and complexities in application architecture. Server-actions offer more robust handling at the cost of tighter coupling, while browser requests provide flexibility and simplicity, ideal for scenarios where rapid development and deployment are prioritized.
Made with ❤️ by [floatrx].