Welcome to the Intania Openhouse 2026 frontend repository! This is a modern Next.js project strictly organized using a modular architecture for API calls, UI sections, and type-safety.
This README serves as a guide for all coworkers contributing to this codebase to ensure consistency in coding standards.
- Framework: Next.js (App Router)
- UI & Styling: Material-UI (MUI)
- State & Data Fetching: TanStack React Query
- HTTP Client:
ky(Fetch API wrapper) - Forms & Validation:
react-hook-form+zod - Package Manager:
bun
We follow a strict separation of concerns pattern to keep features cleanly isolated from API layers and shared components.
src/
├── app/ # Next.js App Router (Pages, Layouts, global providers)
├── components/ # Generic, highly reusable UI elements (e.g., CustomButton)
├── contexts/ # Global Context Providers (e.g., ReactQueryProvider)
├── layouts/ # Scoped layout components (Main layout, headers, etc)
├── lib/ # Utilities, Zod schemas, constants, Firebase config
├── sections/ # 🔥 Feature-specific UI components (Views)
├── services/ # 🔥 API fetching logic and hooks
└── types/ # Typescript Definitions aligning with backend JSON models
Instead of putting all UI logic into app/[route]/page.tsx, we extract feature modules into sections/.
For example, the form logic lives entirely inside sections/form/. The main orchestrator is typically view/form-view.tsx. The app/form/page.tsx file purely serves to render this View component.
We use an enterprise-level API layer approach to strictly type and handle API requests over ky using React Query. Every new feature should create a folder here (e.g., services/user/ or services/form/).
Inside a feature service folder, segregate by action type:
Located in services/[feature]/mutation/.
- Define the
fetchexecution function. - Export a React Hook wrapping
useMutation. - Create an
index.tsto export it nicely.
// Example: src/services/form/mutation/use-submit-form.ts
export function useSubmitFormMutation() {
return useMutation({
mutationFn: postSubmitForm,
});
}Located in services/[feature]/query/.
- Must export a
[feature]QueryKeysobject factory. - Must export the raw
fetchfunction. - Can export
queryOptions()objects tailored for globaluseQueryusage.
// Example: src/services/user/query/user-query.ts
const usersQueryKeys = {
all: () => ["users"] as const,
meOptions: (payload) => queryOptions({ ... }),
};When adding a new feature that communicates with the Backend, follow these 4 steps:
-
Define the Types (
src/types/) Look at the OpenAPI spec and create exact TypeScript definitions for the payload requests and responses. (Avoid using genericanytypes). -
Create the API Integration (
src/services/)- If it's a GET request: create
services/[feature]/query/... - If it's a POST/PUT/DELETE: create a hooked
services/[feature]/mutation/use-[name].ts - Note: Use the pre-configured
kyinstance available atsrc/services/ky.ts.
- If it's a GET request: create
-
Build the UI (
src/sections/) Create a new folder for the specific view components. Inject the queries/mutations created in Step 2 directly into the component via React Query hooks. -
Add the Route (
src/app/) Build thepage.tsx/layout.tsxroute, import the component fromsections/and render it.
Install dependencies using bun:
bun installStart the development server:
bun run devOpen http://localhost:3000 with your browser to see the result. The API proxy points to localhost:8000 locally.