A Next.js boilerplate with modular architecture and strict conventions.
yarn devOpen http://localhost:3000 to see the result.
features/: Page-specific componentscomponents/ui/: Reusable components (Button, Icons, etc.)components/layout/: Layout components (Header, Footer)components/shared/: Components shared between features
hooks/: Reusable business logic (performance, scroll, animations, etc.)
layout/: Specific layouts (default.tsx)
providers/: Global contextsperformance.provider.tsx: Performance managementsmooth-scroll.provider.tsx: Smooth scrollroot.tsx: Root provider
- CSS Variables:
styles/tailwind.css - Global Spacing: Variables
--x-default,--y-defaultwith variants (half, double) - Padding/Margin:
padding-x-default,margin-y-double-default, etc. - Colors and fonts: Declared in
:rootand@theme
styles/abstracts/: Mixins and keyframesstyles/base/: Reset, fonts, Lenisstyles/components/: Typography and componentsstyles/main.scss: Main entry point
- Typography: Classes
.h1,.h2,.h3,.p1,.p2,.p3in_typography.scss - Fonts: Font declarations in
_fonts.scss - Global Variables: SCSS for typography, Tailwind for spacing
- Mixins:
_mixins.scss - Animations:
_keyframes.scss
yarn format # Format code
yarn check # Check without fixing
yarn lint # Linter- Automatic formatting with ESLint
- Prettier for CSS property ordering
- Husky for Git hooks
yarn dev # Development with Turbopack
yarn build # Production build
yarn start # Production server
yarn format # Format with ESLint
yarn check # Check code- Next.js 15 with Pages Router
- React 19 + TypeScript
- Sanity v4 for CMS + Visual Editing
- GSAP for animations
- Lenis for smooth scroll
- Tailwind CSS 4 + SCSS
- ESLint + Prettier for code quality
Required environment variables:
NEXT_PUBLIC_SANITY_PROJECT_ID=your-project-id
NEXT_PUBLIC_SANITY_DATASET=production
NEXT_PUBLIC_SANITY_STUDIO_URL=http://localhost:3000/studio
SANITY_VIEWER_TOKEN=your-tokenAccess the studio at http://localhost:3000/studio
-
services/sanity.service.ts: Centralized logic for fetching and Visual EditingfetchSanityData(): Fetches data with draft mode supportcreateDataAttribute(): Generates click-to-edit attributes
-
services/[content].service.ts: Services per content type (e.g.,sample.service.ts)- Contains specific GROQ queries
- Uses
fetchSanityData()under the hood
hooks/useSanityData.ts: Hook to simplify Sanity data usage- Automatically extracts
dataandencodeDataAttribute - To be used in your components
- Automatically extracts
Visual Editing allows you to modify content directly from the preview.
// pages/example.tsx
import { useSanityData } from "@/hooks/useSanityData";
import { fetchSamples } from "@/services/sample.service";
import type { InferGetStaticPropsType } from "next";
export const getStaticProps = async (context: { draftMode?: boolean }) => {
const samples = await fetchSamples(context);
return {
props: {
samples,
draftMode: samples.draftMode // β
Important to enable Visual Editing
}
};
}
export default function Page({ samples }: InferGetStaticPropsType<typeof getStaticProps>) {
const { data, encodeDataAttribute } = useSanityData(samples);
return (
<div>
{data.map((item, index) => (
<h1
key={item._id}
data-sanity={encodeDataAttribute([index, 'name'])} // β
Click-to-edit
>
{item.name}
</h1>
))}
</div>
);
}For a simple field:
data-sanity={encodeDataAttribute('title')}For a field in an array:
data-sanity={encodeDataAttribute([index, 'title'])}For a nested field:
data-sanity={encodeDataAttribute(['author', 'name'])}- Go to the Studio: http://localhost:3000/studio
- Open the Presentation Tool
- Click on an element with
data-sanityto edit it - Changes are visible in real-time
Click "Disable Draft Mode" in the preview, or go to /api/disable-draft