Reference
Architecture
Deep dive into the folder structure, utilities, hooks, server actions, and conventions that power this boilerplate.
Folder Structure
Each folder has a clear responsibility. Follow these conventions when adding new code.
πapp/Routes, pages, layouts, and API endpoints using the Next.js App Router.
app/Routes, pages, layouts, and API endpoints using the Next.js App Router.
- β’layout.tsx β Root layout with Poppins font and SEO metadata
- β’page.tsx β Home/landing page
- β’error.tsx β Route-level error boundary (client component)
- β’not-found.tsx β Custom 404 page
- β’loading.tsx β Global loading indicator
- β’styles/globals.css β Tailwind imports, design tokens, custom utilities
Convention
Each folder inside app/ becomes a route. Use layout.tsx for shared UI, page.tsx for page content, and error.tsx for error boundaries.
π§©components/Reusable UI components organized by scope.
components/Reusable UI components organized by scope.
- β’layout/ β Structural components (Header, Footer)
- β’shared/ β Components used across multiple features
- β’ui/ β Base/atomic UI components (buttons, inputs, cards)
Convention
Keep components small and focused. One component per file. Use TypeScript interfaces for props. Co-locate related components in sub-folders.
πͺhooks/Custom React hooks for reusable stateful logic.
hooks/Custom React hooks for reusable stateful logic.
- β’useCustomParams.ts β URL query parameter management
- β’index.ts β Re-export barrel file
Convention
Name hooks starting with 'use'. Keep hooks pure (no direct DOM manipulation). Export from index.ts for clean imports.
π§utils/Generic, stateless utility functions with no side effects.
utils/Generic, stateless utility functions with no side effects.
- β’queryExtractor.ts β Build URL query strings for API calls
- β’paramsExtractor.ts β Parse server-side search params (async)
- β’logger.ts β Environment-aware console logger
Convention
Utils must be pure functions. No React imports, no state, no side effects. One function per file preferred.
π€helpers/Pure helper functions for data transformation.
helpers/Pure helper functions for data transformation.
- β’array.ts β sortBy, groupBy, uniqueArray (all type-safe with generics)
Convention
Helpers are for data manipulation (arrays, objects, strings). Keep them generic and type-safe.
βοΈcore/Application infrastructure β server actions, caching, auth.
core/Application infrastructure β server actions, caching, auth.
- β’actions/mutation.ts β Generic CRUD mutation helper with auth + cache revalidation
- β’actions/auth-actions.ts β Cookie-based logout server action
- β’cache/revalidate.ts β Cache revalidation utilities (placeholder)
Convention
Core is for infrastructure that the rest of the app depends on. Server actions go here, not in components or utils.
πtypes/Global TypeScript type definitions and constants.
types/Global TypeScript type definitions and constants.
- β’queryExtractor.type.ts β QueryExtractor type definition
- β’paramsExtractor.type.ts β IPamrasEX constants (SEARCHTERM, PAGE, LIMIT)
Convention
Use 'type' suffix for type files. Export types and interfaces. Use 'as const' for runtime constants.
πconstants/Static configuration values and API URL constants.
constants/Static configuration values and API URL constants.
- β’convention.api.constant.ts β API_BASE_URL, API_V1_BASE_URL, CLIENT_BASE_URL
Convention
Constants never change at runtime. Use UPPER_SNAKE_CASE for naming. Group by domain (api, routes, config).
πΌοΈassets/Static assets like images, icons, and SVGs.
assets/Static assets like images, icons, and SVGs.
- β’index.ts β Re-export barrel file
Convention
Keep assets in public/ for static files or assets/ for importable modules. Use index.ts for clean imports.
Key Utilities
Core utility functions for data handling and API interactions.
queryExtractorsrc/utils/queryExtractor.tsBuilds URL query strings from search, sort, pagination, and filter parameters. Used to construct API request URLs.
Signature
queryExtractor({
searchTerm?: string,
sortBy?: string,
sortOrder?: "asc" | "desc",
page?: number,
limit?: number,
extra?: Record<string, unknown>,
}): stringUsage Example
import { queryExtractor } from "@/src/utils/queryExtractor";
const query = queryExtractor({
searchTerm: "react",
sortBy: "name",
sortOrder: "asc",
page: 1,
limit: 10,
extra: { category: "frontend" },
});
// Result:
// "searchTerm=react&sortBy=name&sortOrder=asc&page=1&limit=10&category=frontend"
const url = `${API_V1_BASE_URL}/users?${query}`;paramsExtractorsrc/utils/paramsExtractor.tsParses server-side search params in Next.js App Router. Returns typed searchTerm, page, limit, and filter values.
Signature
paramsExtractor({
searchParam: Promise<Record<string, string | string[]>> | undefined,
}): Promise<{
searchTerm: string,
page: number,
limit: number,
filter: Record<string, string>,
}>Usage Example
import { paramsExtractor } from "@/src/utils/paramsExtractor";
// In a Server Component
export default async function UsersPage({
searchParams,
}: {
searchParams: Promise<{ [key: string]: string | string[] }>;
}) {
const { searchTerm, page, limit, filter } = await paramsExtractor({
searchParam: searchParams,
});
// Use these values to fetch data
}loggersrc/utils/logger.tsEnvironment-aware console logger. Logs full details in development, sanitized messages in production.
Signature
logger(error: Error | any): voidUsage Example
import { logger } from "@/src/utils/logger";
try {
// risky operation
} catch (error) {
logger(error);
// Development: logs full error
// Production: logs "Internal server error!"
}array helperssrc/helpers/array.tsType-safe array utility functions: sortBy, groupBy, and uniqueArray. All use TypeScript generics.
Signature
sortBy<T>(arr: T[], key: keyof T, order?: "asc" | "desc"): T[]
groupBy<T>(arr: T[], key: keyof T): Record<string, T[]>
uniqueArray<T>(arr: T[], key?: keyof T): T[]Usage Example
import { sortBy, groupBy, uniqueArray } from "@/src/helpers/array";
// Sort users by name ascending
const sorted = sortBy(users, "name", "asc");
// Group orders by status
const grouped = groupBy(orders, "status");
// { pending: [...], completed: [...] }
// Remove duplicates by id
const unique = uniqueArray(items, "id");Server Actions
Pre-built server-side functions for mutations and authentication.
mutationsrc/core/actions/mutation.tsGeneric server action for CRUD operations. Handles authentication (cookie-based Bearer token), optional shop identification, cache revalidation (paths + tags), and error handling.
Parameters
routestringAPI route path (e.g., '/users')method"POST" | "PUT" | "PATCH" | "DELETE"HTTP methoddatastringJSON stringified request bodyidstringResource ID (for DELETE with single item)idsstring[]Resource IDs (for bulk DELETE)requireAuthbooleanRequire authentication (default: true)requireShopIdbooleanRequire shop identifier (default: false)pathToRevalidatestring | string[]Paths to revalidate after mutationtagsToRevalidatestring | string[]Cache tags to revalidate after mutationUsage Example
import { mutation } from "@/src/core/actions/mutation";
// Create a new user
const newUser = await mutation({
route: "/users",
method: "POST",
data: JSON.stringify({ name: "John", email: "john@example.com" }),
pathToRevalidate: "/users",
});
// Update a user
const updated = await mutation({
route: "/users",
method: "PATCH",
id: "123",
data: JSON.stringify({ name: "Jane" }),
pathToRevalidate: "/users",
});
// Delete a user
const deleted = await mutation({
route: "/users",
method: "DELETE",
id: "123",
pathToRevalidate: "/users",
});
// Bulk delete
const bulkDeleted = await mutation({
route: "/users",
method: "DELETE",
ids: ["123", "456", "789"],
pathToRevalidate: "/users",
});logoutServerActionsrc/core/actions/auth-actions.tsServer action that clears the authentication cookie and redirects to /login.
Usage Example
import { logoutServerAction } from "@/src/core/actions/auth-actions";
// In a component or layout
<button onClick={() => logoutServerAction()}>
Logout
</button>Custom Hooks
Reusable stateful logic for client-side data management.
useCustomParamssrc/hooks/useCustomParams.tsClient-side hook for managing URL query parameters. Provides read, write, and clear operations with debounce support and non-blocking transitions.
Returns
setQueryParamSet or update URL query parametersremoveQueryParamRemove specific query parametersclearAllQueryParamRemove all query parametersgetQueryParamRead a single query parameter valuegetArrayQueryParamRead a comma-separated param as arraygetNumberParamRead a param as number with fallbackgetBooleanParamRead a param as boolean with fallbackallParamsObject containing all current query paramsloadingBoolean indicating if a transition is pendingUsage Example
"use client";
import { useCustomParams } from "@/src/hooks/useCustomParams";
export default function Filters() {
const {
setQueryParam,
removeQueryParam,
clearAllQueryParam,
getQueryParam,
loading,
} = useCustomParams({ routeName: "products" });
return (
<div>
{/* Search */}
<input
onChange={(e) =>
setQueryParam({ search: e.target.value }, { debounce: true })
}
defaultValue={getQueryParam("search") ?? ""}
/>
{/* Page */}
<button onClick={() => setQueryParam({ page: "2" })}>
Page 2
</button>
{/* Remove */}
<button onClick={() => removeQueryParam("search")}>
Clear Search
</button>
{/* Clear all */}
<button onClick={clearAllQueryParam}>Reset All</button>
{loading && <p>Updating...</p>}
</div>
);
}Styling System
Tailwind CSS v4 with custom design tokens and utility classes.
Design Tokens
CSS variables defined in :root and mapped to Tailwind via @theme inline.
--main-color#ccfd3fBrand accent (lime green)--brand147 51 234Primary brand (purple, RGB)--brand-259 130 246Secondary brand (blue, RGB)--success#22c55eSuccess state (green)--warning#f59e0bWarning state (amber)--danger#ef4444Danger state (red)Custom Utility Classes
.gradient-bganimatedAnimated gradient from brand to brand-2.glass-cardblurGlassmorphism effect with backdrop blur.grid-overlaypatternSubtle 40px grid pattern overlay.glowshadowAnimated purple glow box-shadowCommit Convention
Standardized commit messages for readable Git history.
Format: <type>: <description>
feat: add hero section call-to-action
fix: resolve mobile navbar overflow
ui: adjust button spacing on mobile
docs: update readme with setup stepsCommit Types
featA new featurefixA bug fixuiUI or styling changesupdateUpdate any code blockrefactorCode refactoring without changing behaviorperfPerformance improvementsdocsDocumentation updatestestAdding or updating testschoreMaintenance tasks (configs, deps, tooling)buildBuild system or bundler changesciCI/CD related changesrevertReverting a previous commitRules
- β’Use present tense ("add", not "added")
- β’Do not capitalize the first letter
- β’Do not end with a period
- β’One logical change per commit