Install packages
yarn install
Config .env for next-auth
NEXTAUTH_URL="leave it as your nextjs url or custom server"
Config .env for authentication: the information get from our exported API project
NEXT_APP_CLIENT_ID=''
NEXT_APP_CLIENT_SECRET=''
Run on your local
npm run dev
# or
yarn dev
Buil production
// Please turn off ignoreBuildErrors and ignoreDuringBuilds when build project at next.config.js
typescript: {
// !! WARN !!
// Dangerously allow production builds to successfully complete even if
// your project has type errors.
// !! WARN !!
ignoreBuildErrors: false,
}
eslint: {
// Warning: This allows production builds to successfully complete even if
// your project has ESLint errors.
ignoreDuringBuilds: false,
},
yarn build
src
→ assets (not sure but the bridge to get assets ⇒ import { assets } from ‘@asses/index’ ⇒ assets(’name of asset’)
→ pages
→ components
→ atoms
→ molecules
→ AppButton
→ AppButton
→ AppButton.style
→ organisms
→ pages
→ Home
→ Home
→ Home.style (generate style code here)
→ constants
→ models
→ states
→ services
→ utils
For client side, supported navigation function over services/navigate
import { useNavigateService } from '@services/navigate'
const navigation = useNavigateService()
navigation.push()
navigation.replace()
navigation.goBack()
navigation.reload()
For server side
// nextjs navigation in server side
import { NextPageContext } from 'next'
export async function getServerSideProps(context: NextPageContext) {
const { locale = "en", query } = context;
const options: {
props?: Record<string, unknown>;
redirect?: {
destination: string;
permanent: boolean;
};
} = {
props: {
locale,
query,
},
};
// Redirect to login page if user is not authenticated
if (!context.req.headers.cookie) {
options.redirect = {
destination: "/login",
permanent: false,
};
}
return options;
}
Service support function based on business model
How to use service for fetch data from client side
// Define state for query params
const [filterPostParams, setFilterPostParams] = useState<Partial<FilterPostRequestBody>>({
pagination_page: props.query?.page_number,
pagination_limit: props.query?.page_limit
})
// Define query service and pass params to it.
const filterPostQuery = useFilterPostQuery(filterPostParams)
// State of Query can be get over "filterPostQuery"
// filterPostQuery.loading
// filterPostQuery.error
// filterPostQuery.data
// Define action for queries change to trigger refetch data if needed
const handleQueryChange = (newQuery: Partial<FilterPostRequestBody>) => {
setFilterPostParams(newQuery)
}
How to use service for fetch data from server side
// pages/post/index.tsx
// Import server side service
import { fetchFilterPost } from '@services/post'
// Define getServerSideProps to get data from server side
export async function getServerSideProps(context: NextPageContext) {
const { locale = "en", query } = context;
const options: {
props?: Record<string, unknown>;
redirect?: Record<string, unknown>;
} = {};
const { session, queryClient } = await initServerInfo(context);
try {
await fetchFilterPost(queryClient, { pagination_page: query?.page_number, pagination_limit: query?.page_limit});
} catch (err) {
return {
redirect: { destination: `/500`, permanent: false }
}
}
How to use service for mutation data
// Define mutation service
const createPostMutation = useCreatePostMutation();
// Call mutation
const handleCreatePost = async (data: PostData) => {
try {
const response = await createPostMutation.mutateAsync(data);
} catch (e: unknown) {}
};
// State of mutation can be get over "createPostMutation"
// createPostMutation.loading
// createPostMutation.error
// createPostMutation.data
Define a hook with yup schema and react-hook-form outside component
import { useForm } from 'react-hook-form'
import { yupResolver } from '@hookform/resolvers/yup'
import * as yup from 'yup'
const useLoginForm = () => {
const validationScheme = useMemo(
() =>
yup.object().shape({
email: yup.string().email().required(),
password: yup.string().required()
}),
[]
)
return useForm<Form1FormData>({
resolver: yupResolver(validationScheme),
shouldFocusError: true,
mode: 'onChange',
reValidateMode: 'onChange'
})
}
Use hook inside component
const { register, handleSubmit, errors, control } = useLoginForm()
For server side error handling
export async function getServerSideProps(context: NextPageContext) {
const { locale = "en", query } = context;
const options: {
props?: Record<string, unknown>;
redirect?: Record<string, unknown>;
} = {};
const { session, queryClient } = await initServerInfo(context);
try {
if (session) {
await fetchFilterPost(queryClient, { pagination_page: query?.page_number, pagination_limit: query?.page_limit});
}
} catch (err) {
return {
redirect: { destination: `/500`, permanent: false }
}
}
}
For client side error handling
const { data, error } = useFilterPostQuery(filterPostParams)
if (error) {
return <ErrorPage statusCode={500} />
}
- To register for reCAPTCHA v3, go to https://www.google.com/recaptcha/about/, then select
v3 Admin Console
. Login with your Google account - There should be a Plus sign button for you to click on, then enter label, select v3 type. Also add the domains of your website that reCAPTCHA is applied (localhost for local testing). Then Submit
- You will see
Site key
, it needs to be set to NEXT_PUBLIC_RECAPTCHA_SITE_KEY environment variable - For
Secret key
, it is used in your backend to verify with reCAPTCHA server - There is a GoogleReCaptchaProvider in _app.tsx to provide reCAPTCHA context
- Then reCAPTCHA token is fetched by invoking the function retuned from provided hook:
const { executeRecaptcha } = useGoogleReCaptcha()
- You can specify the action as an argument to the function like this
executeRecaptcha('login')
- The token should be specified in
recaptcha
field of the body of the requet toapi/send_otp_codes
Key | Data Type | Example Value | Description |
---|---|---|---|
NEXT_PUBLIC_ACCESS_TOKEN_THRESHOLD | number | 120000 | How long access token will be expired in milliseconds. |
NEXT_APP_CLIENT_ID | string | randomstring | Obtained from backend configuration. |
NEXT_APP_CLIENT_SECRET | string | randomstring | Obtained from backend configuration. |
NEXT_PUBLIC_API_URL | string | https://api-68.review.staging.jitera.app | API URL |
NEXTAUTH_URL | string | https://frontend-68.review.staging.jitera.app | Canonical URL of the site. |
NEXTAUTH_SECRET | string | secret | Used to encrypt the NextAuth.js JWT, and to hash email verification tokens. |