Preskool Banner

Introduction

Preskool is a simple and easy-to-access management dashboard for education, including schools, colleges, and universities.

Requirement

Technologies
  • Next.js 16.3 (App Router + Turbopack)
  • React 19.2
  • TypeScript 5.9
  • Bootstrap 5.3 + SCSS
  • Redux Toolkit 2.11
System Requirements
  • Node.js version >= 18.18 (LTS 20+ recommended)
  • npm version >= 9 (ships with Node.js)
  • Yarn package (Optional)
  • Visual Studio Code
  • Terminal
  • A modern browser — Chrome, Edge, Firefox or Safari

Core Features

– Built with Next.js 16 App Router and React 19
– TypeScript throughout
– File-system based routing with route groups
– Per-page SEO metadata through generateMetadata
– Static export (output: "export") — deploys to any static host
– 390+ ready-made pages grouped by module
– Role based dashboards — Admin, Teacher, Student and Parent
– Academic, HRM, Finance, Attendance, Library, Transport, Hostel, Communication and Settings modules
– Turbopack powered dev server and production build
– Redux Toolkit store with theme settings persisted to localStorage
– Service layer that switches between mock data and a real REST API
– Light / Dark theme and four layout modes — default, mini, boxed and RTL
– Path aliases for clean imports
– Fully responsive design
– Cross browser compatible
– Clean and well commented code
– Easy to customize
– Developer friendly
– And many more...

File Structure

Project Overview

The app/ tree handles routing and metadata only — the actual page UI lives in views/. Template internals sit in core/ and data access in services/.

preskool/
│
└── nextjs/
    │
    ├── public/
    │   ├── assets/                     # images, fonts and static files
    │   └── favicon.png
    │
    ├── src/
    │   ├── app/                        # App Router — routing and metadata only
    │   │   ├── (pages)/                # main layout: header, sidebar, theme
    │   │   │   ├── admin-dashboard/
    │   │   │   │   ├── page.tsx
    │   │   │   │   └── adminDashboardClient.tsx
    │   │   │   └── …                   # 390+ page folders
    │   │   ├── (authentication)/       # bare auth layout: login, errors…
    │   │   ├── providers/              # AppProviders, AuthProvider
    │   │   ├── globals.scss
    │   │   ├── layout.tsx              # root layout: global CSS + providers
    │   │   ├── page.tsx                # "/" entry
    │   │   ├── rootRedirectClient.tsx  # client-side "/" → "/login" hop
    │   │   ├── not-found.tsx
    │   │   └── notFoundClient.tsx
    │   │
    │   ├── components/
    │   │   ├── bootstrap-js/           # loads Bootstrap's JS on the client
    │   │   ├── routing/                # ProtectedRoute, RoleGuard
    │   │   ├── ui/
    │   │   └── workspace/
    │   │
    │   ├── config/                     # env.ts (typed env), metadata.ts
    │   ├── constants/
    │   │
    │   ├── core/
    │   │   ├── common/                 # header, sidebar, modals, theme-settings
    │   │   ├── data/                   # redux store, slices and menu JSON
    │   │   └── modals/
    │   │
    │   ├── features/                   # feature hooks — auth, dashboard, students
    │   ├── hooks/                      # useForm, useQuery, useToasts, …
    │   ├── mocks/                      # static fixtures returned by mock services
    │   ├── routes/
    │   │   └── all_routes.tsx          # single source of route paths
    │   ├── services/                   # api/, auth/, dashboard/, students/
    │   ├── style/
    │   │   ├── css/
    │   │   ├── fonts/
    │   │   ├── icon/
    │   │   └── scss/
    │   ├── types/
    │   ├── utils/
    │   ├── views/                      # every page's UI, grouped by module
    │   └── environment.tsx             # base_path and img_path
    │
    ├── eslint.config.mjs
    ├── next.config.ts
    ├── package.json
    ├── package-lock.json
    └── tsconfig.json
									

Next Structure

Structure Overview

PreSkool Next.js uses the App Router with two route groups. (pages) renders inside the main layout — header, sidebar and theme settings — while (authentication) renders the bare login and error screens. Route groups are wrapped in parentheses, so they organise the folder tree without appearing in the URL.

The app is configured with output: "export", which produces a fully static site. There is no server runtime — no route handlers, no middleware and no server actions.

Configuration — next.config.ts:
import type { NextConfig } from "next";

const nextConfig: NextConfig = {
  output: "export",
  basePath: "/nextjs",
};

export default nextConfig;
Root Layout — src/app/layout.tsx:
import { Metadata } from "next";
import "../../node_modules/bootstrap/dist/css/bootstrap.min.css";
import BootstrapJs from "@/components/bootstrap-js/bootstrapjs";
import "./globals.scss";
import AppProviders from "./providers/AppProviders";

export const metadata: Metadata = {
  title: "Preskool Admin Template",
  icons: { icon: "favicon.png" },
};

export default function RootLayout({
  children,
}: Readonly<{ children: React.ReactNode }>) {
  return (
    <html lang="en">
      <body>
        <AppProviders>{children}</AppProviders>
        <BootstrapJs />
      </body>
    </html>
  );
}
Route Groups
Group What it renders
src/app/(pages)/ Every application page, wrapped in the main layout — header, sidebar, theme settings panel
src/app/(authentication)/ Login, register, forgot password, lock screen, error and maintenance pages in a bare layout
src/app/providers/ Redux store and auth context composition
Note

Images are rendered through <ImageWithBasePath> (src/core/common/imageWithBasePath). It prefixes img_path from src/environment.tsx so assets resolve correctly under the basePath in a static export.

Next Scripts

Scripts Overview

Both the dev server and the production build run on Turbopack. Because the project is configured for static export, npm run build already writes the exported site — there is no separate export step.

You can find the scripts in the package.json file. Here are the available commands:

Command Description
npm run dev Starts the development server with Turbopack on http://localhost:3000/nextjs
npm run build Builds the application and static-exports every page to out/
npm run start Serves a previous build
npm run lint Runs ESLint using the flat config in eslint.config.mjs
Package.json Scripts Section:
"scripts": {
  "dev": "next dev --turbopack",
  "build": "next build --turbopack",
  "start": "next start",
  "lint": "eslint"
}

Installation Guide

After unzipping the template files, you will find our product Preskool -> nextjs (Source code)
Node.js (18.18 or above) and npm are required to run the Next.js project

Open a terminal in the nextjs folder and install the dependencies:

npm install (or) npm install --legacy-peer-deps

To run the project in development mode, run the command:

npm run dev

The application starts on http://localhost:3000/nextjs. The /nextjs prefix comes from the basePath option in next.config.ts — change it there if you deploy to a different path.

If you want to make a build in production mode, run the following command in the root directory, otherwise the project will continue to run in the development mode.

npm run build

To install any plugins in your application, you have to run the following command

npm install plugin_name --save (or) npm install plugin_name --legacy-peer-deps
Deployment Note

Because output: "export" is set, the build writes a fully static site to out/. Upload that folder to any static host under the /nextjs path. Note that redirects() has no effect in a static export — the //login hop is done client-side by src/app/rootRedirectClient.tsx.

Adding a Page

The Three File Pattern

Every page in the template follows the same shape — a server page.tsx, a client wrapper and the view itself. Copy it exactly when you add a page of your own.

1. src/app/(pages)/my-page/page.tsx — server component, metadata only:
import { getPageMetadata } from "@/config/metadata";
import MyPageClient from "./myPageClient";

// This runs on the server
export const generateMetadata = () => {
  return getPageMetadata("My Page");
};

export default function MyPagePage() {
  return <MyPageClient />;
}
2. src/app/(pages)/my-page/myPageClient.tsx — the client boundary:
"use client";

import dynamic from "next/dynamic";

const MyPageComponent = dynamic(() => import("@views/module/my-page"), {
  ssr: false,
  loading: () => <p></p>,
});

export default function MyPageClient() {
  return <MyPageComponent />;
}
3. src/views/module/my-page/index.tsx — the UI itself.

Why the split : a file marked "use client" cannot export generateMetadata, and dynamic(..., { ssr: false }) is illegal in a server component. Keeping page.tsx on the server buys per-page SEO titles; the Client file exists only to hold the directive and the dynamic import. Never put "use client" in a page.tsx.

4. Register the path in src/routes/all_routes.tsx:
export const all_routes = {
  // …existing paths
  myPage: "/my-page",
};
5. Link to it — never hard-code a URL string:
import Link from "next/link";
import { all_routes } from "@/routes/all_routes";

<Link href={all_routes.myPage}>My Page</Link>

Path Aliases

Declared Once

Aliases are declared in compilerOptions.paths of tsconfig.json. Next.js reads that file and resolves the same aliases for the bundler, so there is nothing else to keep in sync.

Alias Target
@/*src/*
@app/*src/app/*
@views/*src/views/*
@components/*src/components/*
@core/*src/core/*
@layouts/*src/layouts/*
@features/*src/features/*
@mocks/*src/mocks/*
@hooks, @hooks/*src/hooks/*
@services, @services/*src/services/*
@config, @config/*src/config/*
@constants, @constants/*src/constants/*
@utils, @utils/*src/utils/*
@routes, @routes/*src/routes/*
Usage:
import { getPageMetadata } from "@/config/metadata";
import { all_routes } from "@/routes/all_routes";
import ProtectedRoute from "@components/routing/ProtectedRoute";
import { studentsService } from "@services/students";

API & Mock Data

Runs Without a Backend

The template ships with mock data enabled and authentication disabled, so it runs correctly with no .env.local file and no server.

Each domain folder in src/services/ follows the same four-file shape:

File Responsibility
<domain>.types.ts TypeScript types shared by both implementations
<domain>.mock.ts Resolves data from the fixtures in src/mocks/
<domain>.http.ts Real REST calls through the shared client
<domain>.service.ts Picks mock or HTTP via createService

createService (src/services/api/create-service.ts) chooses the implementation from env.useMockApi, so call sites never change. All HTTP traffic goes through the single client in src/services/api/client.ts.

Connecting a Real Backend

Create a .env.local file in the nextjs folder:

NEXT_PUBLIC_API_BASE_URL=https://api.example.com/v1
NEXT_PUBLIC_USE_MOCK_API=false
NEXT_PUBLIC_AUTH_ENABLED=true
Variable Default Description
NEXT_PUBLIC_APP_ENV development Environment label — development, staging or production
NEXT_PUBLIC_API_BASE_URL empty Base URL of the REST API
NEXT_PUBLIC_USE_MOCK_API true Resolve data from static mocks instead of HTTP
NEXT_PUBLIC_AUTH_ENABLED false Enforce authentication on protected routes

src/config/env.ts is the only module that reads process.env. While NEXT_PUBLIC_AUTH_ENABLED is false, ProtectedRoute and RoleGuard render their children unconditionally, so every route stays reachable. Flip it to true once a real auth API is connected and the same components start enforcing the session.

Important Note : Every NEXT_PUBLIC_* value is inlined into the client bundle and is therefore public. Never put a secret or a private key in one.

Theme Settings

Theme state lives in Redux (src/core/data/redux/themeSettingSlice.tsx) and is persisted to localStorage. src/app/(pages)/layout.tsx mirrors that state onto the <html> element as data attributes, and the SCSS keys off them.

Attribute Values
data-theme light, dark
data-layout default, mini, boxed, rtl
data-sidebar light, dark, primary, darkblack, darkblue
data-sidebarbg default, sidebarbg1sidebarbg6
data-color primary, violet, pink, orange, green, red
data-topbar white, dark, primary, grey

All of these are switched at runtime from the gear panel in the header, which is implemented in src/core/common/theme-settings. Because the values are written to localStorage, the choice survives a page reload.

How can I switch to the Dark Mode?

Open the Theme Settings panel from the gear icon in the header and choose Dark under Mode. The selection is stored in localStorage, so it is remembered on the next visit.

dark-image

To make dark mode the default for every new visitor instead, change the initial value in src/core/data/redux/themeSettingSlice.tsx:

const initialState = {
  // …
  dataTheme: localStorage.getItem("dataTheme") || "dark_data_theme",
  // …
};

src/app/(pages)/layout.tsx maps dark_data_theme to data-theme="dark" on the <html> element, which is what the SCSS reads.

How can I switch to the RTL?

Open the Theme Settings panel and pick the RTL layout. src/app/(pages)/layout.tsx then sets data-layout="rtl" on the <html> element and the template stylesheet flips the layout direction.

rtl

If you want the Bootstrap grid and utilities themselves mirrored as well, swap the Bootstrap stylesheet import in src/app/layout.tsx for the RTL build:

// Replace this line
import "../../node_modules/bootstrap/dist/css/bootstrap.min.css";

// with this one
import "../../node_modules/bootstrap/dist/css/bootstrap.rtl.min.css";

RTL-specific overrides used by the template live under the .layout-mode-rtl selector in src/app/globals.scss.

How can I change the Font?

The template uses Inter. Changing it takes two edits.

1. Swap the import in src/style/scss/components/_font.scss:
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap');
2. Update the family stack in src/style/scss/utils/_variables.scss:
// Font Family
$font-family-primary: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;

The base size and weight scale are declared in the same file ($font-size-base, $font-weight-medium and friends), so you can adjust typography globally from one place.

How can I change the Color?

Six preset accent colors ship with the template and can be switched at runtime from the Theme Settings panel — primary, violet, pink, orange, green and red.

To change the brand color itself, edit the theme variables in src/style/scss/utils/_variables.scss:

// Theme Colors Variables
$primary: #3D5EE1;
$secondary: #6FCCD8;
$success: #1ABE17;
$info: #0F65CD;
$warning: #EAB300;
$danger: #E82646;
$dark: #202C4B;
$light: #E9EDF4;

Hover shades are derived from these with color.adjust, so changing $primary updates $primary-hover automatically. The dev server recompiles the SCSS as soon as you save.

Support

Need Support?

If this documentation does not address your questions, please feel free to contact us via email at support@dreamstechnologies.com

Reach the team at GMT+5:30. Typical reply within 12–24 hours on weekdays — rarely up to 48 hrs during holidays. Support is available to verified buyers for template-related issues.

Contact Support

Important Note : We strive to offer top-notch support, but it's only available to verified buyers and for template-related issues such as bugs and errors. Custom changes and third-party module setups are not covered.

Custom Work

Do you need a customized application for your business?

If you need a customized application for your business depends on your specific requirements and goals, Please contact us. Customization can be the key to success, ensuring your project perfectly aligns with your unique goals and requirements.

Don't Miss Out on the Benefits of Customization!

Unlock the potential of your project. It's time to ensure your project isn't another cookie-cutter solution but truly unique and effective one.

Discover how customization can make a difference in your project's success. Let's create a solution that's as unique as your vision!

We'll tailor the application to meet your specific needs and preferences.

We will upload your website to the server and ensure it is live.

thanks

Thank You

Thank you once again for downloading Preskool.
We hope you're enjoying your experience, and we kindly request that you take a moment to share your valuable review and rating with us.

Review Link