Boilerplate Code Repository for Next.js frontend
Explore the docs »
View Demo
·
Report Bug
·
Request Feature
- Usage
- Commit messages
- Commit Examples
- Tailwind Config and CSS
- Folder Structure
- Types and Interfaces
- Integration
- Cookies
All frontend projects under csivitu must be a fork of this repository, changes can be made as per the project specific requirements but the overall rules and regulations must be followed as mentioned under this repository.
-
Commits must be made not for every minor changes but a group of changes must be clubbed together and committed to the repo at once, same goes for sending a PR to the main upstream repository or the main branch from any other branch.
-
Commit messages must follow standard practices as specified by Conventional Commits and always include the appropriate prefixes such as
feat
,fix
&chore
.
These describe the type of change made to the codebase:
- feat: A new feature or functionality.
- Example:
feat: add user login functionality
- Example:
- fix: A bug fix.
- Example:
fix: resolve login redirect issue
- Example:
- chore: Maintenance tasks or changes that do not affect the codebase logic (e.g., updates to configuration files, dependency updates).
- Example:
chore: update dependencies
- Example:
- refactor: Code changes that neither fix a bug nor add a feature but improve the internal structure.
- Example:
refactor: simplify user data handling logic
- Example:
- style: Code formatting changes (e.g., spacing, indentation, commas), unrelated to functionality.
- Example:
style: fix indentation in index.ts
- Example:
- test: Adding or updating tests.
- Example:
test: add unit tests for login feature
- Example:
- docs: Documentation updates.
- Example:
docs: update README with installation instructions
- Example:
- build: Changes related to build system configuration or external dependencies.
- Example:
build: configure Webpack for production
- Example:
- ci: Changes related to Continuous Integration (CI) configuration.
- Example:
ci: update GitHub Actions for test pipeline
- Example:
- perf: Performance improvements.
- Example:
perf: improve data loading speed
- Example:
- revert: Reverting a previous commit.
- Example:
revert: revert previous login bug fix
- Example:
These specify the area of the project being affected (optional but helpful):
- feat(auth): If the feature is related to authentication.
- Example:
feat(auth): add OAuth2.0 authentication
- Example:
- fix(api): If the fix applies to API-related code.
- Example:
fix(api): handle missing parameters in request
- Example:
- docs(ui): If the documentation is for UI components.
- Example:
docs(ui): update button component usage
- Example:
The Conventional Commits specification standardizes commit messages with prefixes and is often used with tools like semantic-release
to automate versioning:
- BREAKING CHANGE: This prefix indicates that the commit introduces a breaking API change.
- Example:
feat!: change authentication method to token-based (BREAKING CHANGE)
- Example:
- build(deps): If you update or install new dependencies.
- Example:
build(deps): upgrade React to version 18
- Example:
feat(cart): add item quantity update functionality
fix(auth): resolve token expiration issue
chore: remove deprecated package
The tailwind.config.ts
is a TypeScript configuration file used in TailwindCSS projects to customize various aspects of Tailwind's default configuration. It allows you to define custom themes, extend or override existing styles, and configure plugins, among other things.
Things to consider:
-
For errors like CSS not being applied to some pages but working on other pages, make sure to check the content object inside the tailwind.config.ts property accordingly.
-
Adhere to the same breakpoints for the entirety of the project to ensure that responsivity bugs do not arise.
-
For using custom fonts, make sure there is a font-face directive defined in the globals.css file and correctly defined in the tailwind.config.ts file.
Sample:
globals.css
@font-face {
font-family: 'Alegreya';
src: url('/fonts/AveriaSansLibre-Bold.ttf') format('truetype');
font-weight: normal;
font-style: normal;
}
tailwind.config.ts
extend: {
fontFamily: {
"Alegreya": ["Alegreya", "monospace"],
},
},
},
- Adhere to the folder structure defined in the boilerplate, segregate similar files / assets into same directory for better readablity of code.
- All filenames must begin with lowercase letters, especially the
route/
pages. - In react, every component name must begin with an Uppercase letter to avoid errors.
- Unimportant and unnecessary folders/files (locally required files) must be mentioned appropriately in the
.gitignore
file. - Ensure tailwind.config.ts is updated at all times for any folder structure changes.
All custom user types that are non-primitive must be defined in a separate folder in the src, called types, which contains necessary files for all the user defined types used in the project.
Example:
interface User {
name: string;
age: number;
login(): void;
}
type User = {
name: string;
age: number;
login: () => void;
};
- All the response data must be stored as in variables of their respective types / interfaces, all the network requests must be handled for runtime-errors using try / catch / finally blocks.
- The state of each network request must be stored in a state and that state must be updated depending on the response.status received from the API.
- Loading states and error message states must be used to handle loading phases and error messages respectively (if any, after the request is completed successfully).
- For polling-based requests, a maximum upper limit must be set after which the polling must cease, and an appropriate error message must then be set.
There are different ways to fetch data:
- getServerSideProps:
- Server-Side Data Fetching: Use getServerSideProps when you need to fetch data on the server side before rendering the page.
- Real-Time Data: Use it when the data should be fetched on every request (e.g., real-time data, personalized content, or ensuring data is always fresh).
- SEO Considerations: When you need the data to be available for search engines (since the data is pre-rendered).
- Sensitive Data: If you're fetching sensitive data (e.g., authentication tokens, database queries), which should not be exposed to the client.
export const getServerSideProps = async () => {
const res = await fetch('https://api.example.com/data');
const data = await res.json();
return { props: { data } };
};
- useEffect:
- Client-Side Data Fetching: Use useEffect when the data can be fetched after the page has been rendered on the client side.
- Static or Non-Critical Data: If the data doesn’t need to be fetched before the page renders (e.g., less critical or optional data like paginated comments, client-specific data).
- Dynamic or User-Driven Events: When data should be fetched based on user interactions, such as button clicks or scroll events.
- Lighter Initial Load: When you want the page to load quickly and fetch data later.
import { useState, useEffect } from 'react';
const Page = () => {
const [data, setData] = useState(null);
const [error, setError] = useState(null); // State for tracking errors
useEffect(() => {
async function fetchData() {
try {
const res = await fetch('https://api.example.com/data');
// Check if the response is OK
if (!res.ok) {
throw new Error(`HTTP error! Status: ${res.status}`);
}
const result = await res.json();
setData(result); // Set the fetched data to state
} catch (err) {
setError(err.message); // Capture and set error message
}
}
fetchData();
}, []);
if (error) return <div>Error: {error}</div>; // Display error message
if (!data) return <div>Loading...</div>; // Display loading state if data isn't fetched yet
return <div>{data.title}</div>; // Render the fetched data
};
export default Page;
Use Secure and SameSite: Always use the secure option (only for HTTPS sites) and set SameSite to strict or lax to mitigate CSRF attacks.
Consider HttpOnly for Server-Side Cookies: If you're setting cookies on the server (via HTTP headers), use the HttpOnly flag to make them inaccessible to JavaScript, protecting against XSS.
expires
: Defines how long the cookie will be valid. In this case, it's set to 7 days.secure
: Ensures the cookie is only sent over HTTPS, improving security on production environments.sameSite
: Restricts the cookie from being sent with cross-origin requests, protecting against CSRF attacks. Possible values are strict, lax, or none.path
: Defines the URL path the cookie is valid for. Setting it to / makes the cookie accessible across the entire site.
First, install the js-cookie package:
npm install js-cookie
Example:
import Cookies from 'js-cookie';
Cookies.set('jwt_token', 'your-jwt-token', {
expires: 1, // expires in 1 day, set this is per the backend
secure: true, // only over HTTPS
sameSite: 'Strict', // protect against CSRF
});
const token = Cookies.get('jwt_token');
Cookies.remove('jwt_token');
Distributed under the MIT License. See LICENSE
for more information.