npx create-next-app <project-name>
Would you like to use TypeScript with this project? … No / Yes
Would you like to use Eslint with this project? … No / Yes
Go to current directory
npm run dev
create-next-app
allows you to create a new Next.js app within seconds. It is officially maintained by the creators of Next.js, and includes a number of benefits:
-
Interactive Experience: Running npx create-next-app@latest (with no arguments) launches an interactive experience that guides you through setting up a project.
-
Zero Dependencies: Initializing a project is as quick as one second. Create Next App has zero dependencies.
-
Offline Support: Create Next App will automatically detect if you're offline and bootstrap your project using your local package cache.
-
Support for Examples: Create Next App can bootstrap your application using an example from the Next.js examples collection (e.g. npx create-next-app --example api-routes).
-
Tested: The package is part of the Next.js monorepo and tested using the same integration test suite as Next.js itself, ensuring it works as expected with every release.
my-app
├── .next
├── components
├── node_modules
├── pages
│ ├── api
│ ├── _app.tsx
│ ├── _document.tsx
│ ├── index.tsx
│ ├── 404.tsx
│ ├── login.tsx
│ └── signup.tsx
├── public
│ ├── icons
│ ├── images
│ ├── favicon.ico
│ ├── next.svg
│ ├── thirteen.svg
│ └── vercel.svg
├── redux
│ ├── actions
│ ├── reducers
│ └── store.ts
├── styles
│ └── globals.css
├── utils
├── .env.example
├── .env.local
├── .eslintrc.json
├── .gitignore
├── App.config.js
├── next.config.js
├── next-env.d.ts
├── next.config.js
├── package-lock.json
├── package.json
├── README.md
└── tsconfig.json
NEXT_PUBLIC_AUTH_URL='AUTH_URL'
NEXT_PUBLIC_BASE_URL='BASE_URL'
NEXT_PUBLIC_MAP_API_ACCESS_TOKEN='MAP_API_ACCESS_TOKEN'
export const AUTH_URL = process.env.NEXT_PUBLIC_AUTH_URL;
export const MAP_API_ACCESS_TOKEN = process.env.NEXT_PUBLIC_MAP_API_ACCESS_TOKEN;
// Staging
export const BASE_URL = process.env.NEXT_PUBLIC_BASE_URL;
// Auth Configs
export const AUTH = {
LOGIN: `${AUTH_URL}/admin/login`,
GET_USER: `${AUTH_URL}/auth/user`,
REGISTER: `${AUTH_URL}/auth/register`,
};
// API Configs
export const API = {}
import Head from "next/head";
import type { AppProps } from 'next/app'
import { useRouter } from 'next/router'
import { Provider } from 'react-redux'
import store from '../redux/store'
// Import Components
import MenuLayout from '../components/MenuLayout'
// Import Styles
import '../styles/globals.css'
const App = ({ Component, pageProps }: AppProps) => {
// States
const router = useRouter()
return (
<>
<Provider store={ store }>
<div style={containerStyles}>
{ (router?.asPath === '/login' || router?.asPath === '/signup' || router?.asPath === '/') ?
(
<Component { ...pageProps } />
)
:
(
<MenuLayout>
<Component { ...pageProps } />
</MenuLayout>
)
}
</div>
</Provider>
</>
)
}
// Styles
const containerStyles = {
boxSizing: 'border-box' as 'border-box',
width: '100%',
height: '100vh',
overflow: 'hidden'
}
export default App
import type { DocumentContext, DocumentInitialProps } from 'next/document'
import Document, { Html, Head, Main, NextScript } from 'next/document'
import { createCache, extractStyle, StyleProvider } from '@ant-design/cssinjs'
import Script from 'next/script'
class MyDocument extends Document {
static async getInitialProps(
ctx: DocumentContext
): Promise<DocumentInitialProps> {
const cache = createCache()
const originalRenderPage = ctx.renderPage
// Run the React rendering logic synchronously
ctx.renderPage = () =>
originalRenderPage({
// Wrapping The Whole React Tree
enhanceApp: (App) => (props) =>
(
<StyleProvider cache={cache}>
<App {...props} />
</StyleProvider>
),
})
const initialProps = await Document.getInitialProps(ctx)
return {
...initialProps,
styles: (
<>
{initialProps.styles}
<script
dangerouslySetInnerHTML={{
__html: `</script>${extractStyle(cache)}<script>`,
}}
/>
</>
),
}
}
render() {
return (
<Html>
<Head>
<link rel="stylesheet" href="https://cdn.barikoi.com/bkoi-gl-js/dist/bkoi-gl.css"/>
<Script src="https://cdn.barikoi.com/bkoi-gl-js/dist/bkoi-gl.js" strategy="beforeInteractive" />
</Head>
<body>
<Main />
<NextScript />
</body>
</Html>
)
}
}
export default MyDocument
import { useRouter } from 'next/router'
import { useEffect } from 'react'
// Import Components
import { Spin } from 'antd'
// Import Actions & Methods
import { useAppSelector, useAppDispatch } from '../redux/store'
import { validateUser } from '../redux/actions/authActions'
export default function Home() {
// States
const router = useRouter()
const dispatch = useAppDispatch()
// Get Data from Redux Store
const isAuthenticated = useAppSelector(state => state?.auth?.isAuthenticated ?? false)
const isValidating = useAppSelector(state => state?.auth?.isValidating ?? true)
// On Load Validate User by Token
useEffect(() => {
const token = localStorage.getItem('token')
dispatch( validateUser(token) )
}, [])
// On Load Redirect User
useEffect(() => {
if(isAuthenticated && !isValidating) {
console.log("dashboard")
router.push('/dashboard')
} else if(!isAuthenticated && !isValidating) {
console.log("login")
router.push('/login')
}
}, [ isAuthenticated, isValidating ])
return (
<div style={ containerStyles }>
<Spin size='large' />
</div>
)
}
// Styles
const containerStyles = {
width: '100%',
height: '100%',
display: 'flex',
justifyContent: 'center',
alignItems: 'center'
}
import { configureStore } from "@reduxjs/toolkit";
import type { TypedUseSelectorHook } from 'react-redux'
import { useDispatch, useSelector } from 'react-redux'
// Import Reducers
import authReducer from "./reducers/authReducer";
import navReducer from "./reducers/navReducer";
const store = configureStore({
reducer: {
auth: authReducer,
nav: navReducer,
},
});
// Declare Typed Definitions
type RootState = ReturnType<typeof store.getState>
type AppDispatch = typeof store.dispatch
export const useAppDispatch: () => AppDispatch = useDispatch
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector
export default store;
import React from 'react';
// Import Components
import { Layout } from 'antd';
import LeftNav from './LeftNav/LeftNav'
import TopNav from './TopNav/TopNav'
// Import Methods
import { useAppSelector } from '../redux/store';
// Import Constants
const { Header, Sider, Content } = Layout
// Interface
interface Props {
children: React.ReactNode
}
const MenuLayout = ({ children }: Props) => {
// Get Data from Redux
const isLeftNavOpen = useAppSelector(state => state?.nav?.isLeftNavOpen ?? true)
const leftNavWidth = useAppSelector(state => state?.nav?.leftNavWidth ?? 340)
const selectedLeftNavMenuKeys = useAppSelector(state => state?.nav?.selectedLeftNavMenuKeys ?? [ 'dashboard' ])
return (
<div style={ containerStyles }>
<Layout>
<Header style={{width: "100%"}}>
<TopNav/>
</Header>
<Layout hasSider={true}>
<Sider
className='left-nav-container'
theme='light'
trigger={ null }
collapsed={ !isLeftNavOpen }
collapsedWidth={ 100 }
collapsible={ true }
width={ leftNavWidth }
>
<LeftNav selectedLeftNavMenuKeys={ selectedLeftNavMenuKeys }/>
</Sider>
<Content>{ children }</Content>
</Layout>
</Layout>
</div>
);
};
// Styles
const containerStyles = {
width: '100%',
height: '100%',
overflow: 'hidden'
}
export default MenuLayout;