Architecture Overview

Fullstack SSR architecture for Evensiva Technologies — Next.js 16 App Router, PostgreSQL, Prisma, NextAuth.js, MUI v6, @mui/material-nextjs v7.

Overview

Evensiva Technologies (evensiva.com) is a fullstack web application built with Next.js 16 App Router. The project was migrated from a Vite + React SPA to a server-rendered Next.js application for SEO, performance, and the ability to handle backend logic (database, authentication, API routes) within a single codebase.

Branding in the UI: The global header (Banner) and footer (Footer) show SiteLogo (/Logo.png) beside a two-line wordmark — Evensiva on the first line and TECHNOLOGIES in small caps on the second (same pattern in the mobile drawer). Together this reads Evensiva Technologies. The logo image uses alt="Evensiva Technologies". Root metadata and JSON-LD (JsonLd.tsx) use the same public name. The Banner applies a subtle border and shadow when the user scrolls (scroll listener on window).

The application serves as a company website and digital services portal offering IT training courses, web development services, digital marketing, and an internship program. It includes a public-facing marketing site, a blog with rich content rendering, and a full admin panel for content management.

Vite → Next.js Migration

The original application was a client-side React SPA bootstrapped with Vite, using React Router DOM for client routing and static data embedded in components. The migration involved:

Note: Deleted Vite-specific files: vite.config.ts, index.html, src/main.tsx, src/App.tsx, src/App.css, src/vite-env.d.ts, tsconfig.app.json, tsconfig.node.json.

Tech Stack

LayerTechnologyPurpose
FrameworkNext.js 16 (App Router)SSR, SSG, file-system routing, API routes; default production compiler is Turbopack
LanguageTypeScript 5Type safety across frontend and backend
UI LibraryMUI v6 + Emotion + @mui/material-nextjs v7Component library with SSR-compatible styling; Next adapter supplies AppRouterCacheProvider
DatabasePostgreSQL (Neon)Serverless Postgres for posts, courses, contacts, users; project provisioned for Evensiva
ORMPrisma 6Type-safe database access, migrations, seeding
AuthenticationNextAuth.js v5 (Auth.js)JWT sessions, Credentials + optional Google/GitHub OAuth, role-based access; auth.config.ts for Edge middleware, auth.ts for DB-backed providers
FormsReact Hook Form + ZodForm state management and validation
IconsMUI Icons + Lucide ReactIcon sets for UI components
Rich ContentDOMPurify + PrismJS + html-react-parserSanitized HTML rendering with syntax highlighting
DeploymentVercelEdge hosting, serverless functions, CI/CD

Project Structure

evensiva_frontend_app/
├── docs/                          # Project documentation (this folder)
│   ├── features/                  # Feature-specific docs (markdown)
│   ├── setup/                     # Setup and deployment guides (HTML)
│   ├── archive/                   # Historical migration docs
│   └── documentation-index.json   # Manifest for all docs
├── prisma/
│   ├── schema.prisma              # Database schema (User, Post, Course, Contact)
│   └── seed.ts                    # Database seed script
├── public/                        # Static assets (case-sensitive URLs on Linux)
│   ├── Images/                    # slider/, services/, courses/, docs/ (screenshots)
│   ├── PDFs/                      # Downloadable PDFs
│   └── Logo.png                   # Brand + root metadata icon (`/Logo.png`)
├── src/
│   ├── app/                       # Next.js App Router pages
│   │   ├── layout.tsx             # Root layout: flex column body, main flex:1, ThemeRegistry, Banner, Footer, SEO
│   │   ├── page.tsx               # Home route: metadata + HomePageContent
│   │   ├── HomePageContent.tsx    # Home page UI (client; MUI + next/link CTAs)
│   │   ├── globals.css            # Global styles
│   │   ├── about/                 # About Us page
│   │   ├── contact/               # Contact form page
│   │   ├── courses/               # Courses listing
│   │   ├── documentation/         # Marketing documentation hub (/documentation)
│   │   ├── docs/                  # Project docs index + file server for repo `docs/` tree
│   │   ├── help/                  # Help center with FAQ
│   │   ├── internship/            # Internship program page
│   │   ├── posts/                 # Blog listing + [slug] detail
│   │   ├── services/              # Services overview (RoutableTabs) + subpages
│   │   ├── admin/                 # Admin panel (protected)
│   │   │   ├── layout.tsx         # Admin layout with sidebar
│   │   │   ├── page.tsx           # Dashboard with stats
│   │   │   ├── login/             # Admin login
│   │   │   ├── signup/            # Admin signup
│   │   │   ├── posts/             # Posts CRUD
│   │   │   ├── courses/           # Courses CRUD
│   │   │   └── contacts/          # Contact submissions
│   │   ├── api/                   # API routes
│   │   │   ├── auth/[...nextauth] # NextAuth handler
│   │   │   ├── auth/register/     # Admin signup endpoint
│   │   │   ├── contact/           # Contact form API
│   │   │   ├── posts/             # Posts API (CRUD)
│   │   │   └── courses/           # Courses API (CRUD)
│   │   ├── sitemap.ts             # Dynamic sitemap generation
│   │   └── robots.ts              # robots.txt generation
│   ├── components/
│   │   ├── layouts/               # Banner (nav) and Footer — SiteLogo + Evensiva / TECHNOLOGIES wordmark
│   │   ├── features/              # Service feature components
│   │   ├── common/                # Shared components
│   │   │   ├── SiteLogo/          # Brand image from `public/Logo.png`
│   │   │   ├── RichContent/       # HTML renderer with Prism
│   │   │   ├── RoutableTabs/      # URL-synced tabs
│   │   │   ├── ArticleToc/        # Article TOC sidebar
│   │   │   ├── ImageSlider/       # Homepage carousel
│   │   │   ├── CourseCard/        # Course display card
│   │   │   ├── ServicesCards/     # Service display cards
│   │   │   ├── SocialMediaCard/   # Social links
│   │   │   └── GradientBox/       # Styled gradient container
│   │   ├── providers/             # ThemeRegistry, AuthProvider
│   │   ├── admin/                 # Admin-specific components
│   │   ├── ContactForm/           # Contact form with API submission
│   │   └── JsonLd.tsx             # JSON-LD structured data helpers
│   ├── lib/
│   │   ├── prisma.ts              # Prisma client singleton
│   │   ├── auth.config.ts         # Edge-safe NextAuth options (middleware; no Prisma)
│   │   ├── auth.ts                # NextAuth + Credentials (Prisma/bcrypt) for API routes
│   │   └── utils.ts               # Utility functions (slugify, formatDate)
│   └── types/
│       └── index.ts               # Shared TypeScript types
├── middleware.ts                   # Edge auth for /admin/* (uses auth.config only)
├── next.config.ts                 # Next.js configuration
├── package.json                   # Dependencies and scripts
├── tsconfig.json                  # TypeScript configuration
└── .env.local                     # Environment variables (not committed)

Rendering Strategy

The application uses Next.js App Router's default rendering strategy: Server Components by default, with "use client" directives only where client-side interactivity is required.

RouteRenderingReason
/, /about, /contactStatic (SSG)Content doesn't change often; generated at build time
/posts, /coursesStatic with revalidationFetches from DB at build, revalidates on deploy
/posts/[slug]Dynamic (SSR)Dynamic route; generates metadata per post
/admin/*Dynamic (SSR)Auth-gated; always fresh data
/api/*Serverless functionsAPI endpoints for CRUD operations
/sitemap.xml, /robots.txtDynamicGenerated from DB content

Client vs Server Components

Components are Server Components by default. The "use client" directive is added only when a component uses:

Client components in this project

ComponentReason for "use client"
Banner, FooterEvent handlers (drawer, menu), useMediaQuery, useState; Banner also useEffect scroll listener for elevated app bar; global brand lockup (SiteLogo + two-line wordmark)
ThemeRegistryThemeProvider, AppRouterCacheProvider (@mui/material-nextjs/v16-appRouter)
HomePageContentMUI buttons with component={NextLink}; keeps page.tsx as a Server Component for metadata
Internship, ITTraining, DigitalMarketing, WebDevelopmentSame next/link + MUI pattern; marked "use client"
ImageSlideruseState + useEffect for carousel timer
ContactFormForm state, API submission, useState
PostsClientCategory filtering with useState
AboutContentMUI styled component
RichContentDOMPurify, Prism, copy buttons, DOM manipulation
RoutableTabsuseSearchParams, useRouter for URL sync
ArticleTocSidebaruseTheme for dynamic styling
AdminSidebarusePathname, useSession, sign-out action
PostForm, CourseFormFull form state management
LoginForm, SignupFormuseSearchParams, form validation, NextAuth signIn, optional OAuth actions

Routing

Next.js App Router uses file-system routing. Each page.tsx under src/app/ becomes a route.

Public routes (selected)

/                          → Home page
/about                     → About Us
/contact                   → Contact form
/courses                   → Course listing
/documentation             → Marketing documentation hub (links to services, /docs, help)
/docs                      → Project documentation index (technical HTML guides)
/docs/*                    → Served files from repo `docs/` (e.g. setup/*.html)
/help                      → Help center (FAQ)
/internship                → Internship program
/posts                     → Blog listing
/posts/[slug]              → Individual blog post (dynamic)
/services                  → Services overview (RoutableTabs)
/services/training         → IT Training
/services/digital          → Digital Marketing
/services/webdevelopment   → Web Development
/admin                     → Admin dashboard
/admin/login               → Admin login
/admin/signup              → Admin signup
/admin/posts               → Manage posts
/admin/posts/new           → Create post
/admin/posts/[id]/edit     → Edit post
/admin/courses             → Manage courses
/admin/courses/new         → Create course
/admin/courses/[id]/edit   → Edit course
/admin/contacts            → View contact submissions
/api/auth/[...nextauth]    → NextAuth handler
/api/auth/register         → Signup API (create user)
/api/contact               → Contact API
/api/posts                 → Posts API
/api/posts/[id]            → Single post API
/api/courses               → Courses API
/api/courses/[id]          → Single course API
/sitemap.xml               → Dynamic sitemap
/robots.txt                → Robots file

Data Flow

The application follows a clean data flow pattern:

Data flow diagram
Browser → Server Component → Prisma → PostgreSQL   (public pages)
Browser → Client Component → fetch() → API Route → Prisma → PostgreSQL   (admin CRUD)
Browser → Server Component → Static fallback data   (no DB available)

UI shell, layout, and spacing

Page shell: src/app/layout.tsx gives <body> an inline flex column with minHeight: 100vh and wraps route children in <Box component="main" sx={{ flex: 1 }}> (MUI Box) so the footer stays at the bottom when content is shorter than the viewport.

Spacing and UX: Marketing pages use consistent MUI sx spacing (section py, chip-to-heading gaps, card padding). Cards and buttons use shared motion patterns (e.g. cubic-bezier(0.4,0,0.2,1) transitions, hover lift). The services overview page (/services) uses top padding only on the outer container so vertical padding does not stack with the tab panels’ feature sections (each feature component already sets its own py). The contact route renders <ContactForm /> directly (no extra wrapper div).

Styling

The application uses MUI v6 with Emotion for component styling, integrated with Next.js SSR via @mui/material-nextjs v7 (import AppRouterCacheProvider from @mui/material-nextjs/v16-appRouter for Next.js 16).

Build & Output

The project builds with next build (Next.js 16 uses Turbopack for production builds unless you pass --webpack). Output includes:

npm run build    # Runs: next build (Turbopack by default in v16)
npm run dev      # Runs: next dev (development server)
npm run start    # Runs: next start (production server)
npm run lint     # Runs: next lint

Note: On some Windows environments, next lint may fail with an invalid project directory; run ESLint from the project root (for example npx eslint .) or use your editor integration.