/jest.setup.js'],
13 | testEnvironment: 'jest-environment-jsdom',
14 | preset: 'ts-jest',
15 | }
16 |
17 | // createJestConfig is exported this way to ensure that next/jest can load the Next.js config which is async
18 | module.exports = createJestConfig(config)
--------------------------------------------------------------------------------
/jest.setup.js:
--------------------------------------------------------------------------------
1 | import '@testing-library/jest-dom/extend-expect'
2 |
--------------------------------------------------------------------------------
/next.config.js:
--------------------------------------------------------------------------------
1 | /** @type {import('next').NextConfig} */
2 | const nextConfig = {}
3 |
4 | module.exports = nextConfig
5 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "nextjs13-reactjs-typescript-tailwindcss-jest-starter-frontend",
3 | "version": "0.1.0",
4 | "author": {
5 | "name": "zied-snoussi",
6 | "email": "ziedsnoussi.tn@gmail.com",
7 | "url": "https://www.zied-snoussi.me"
8 | },
9 | "private": true,
10 | "scripts": {
11 | "dev": "next dev",
12 | "build": "next build",
13 | "start": "next start",
14 | "lint": "next lint",
15 | "test": "jest",
16 | "test-watch": "jest --watchAll"
17 | },
18 | "dependencies": {
19 | "@types/node": "20.6.3",
20 | "@types/react": "18.2.22",
21 | "@types/react-dom": "18.2.7",
22 | "autoprefixer": "10.4.15",
23 | "eslint": "8.49.0",
24 | "eslint-config-next": "13.5.1",
25 | "next": "13.5.1",
26 | "postcss": "8.4.30",
27 | "react": "18.2.0",
28 | "react-dom": "18.2.0",
29 | "tailwindcss": "3.3.3",
30 | "typescript": "5.2.2"
31 | },
32 | "devDependencies": {
33 | "@testing-library/jest-dom": "^5.16.5",
34 | "@testing-library/react": "^14.0.0",
35 | "@testing-library/user-event": "^14.5.1",
36 | "eslint-plugin-testing-library": "^6.0.1",
37 | "jest": "^29.7.0",
38 | "jest-environment-jsdom": "^29.7.0",
39 | "ts-jest": "^29.1.1"
40 | }
41 | }
--------------------------------------------------------------------------------
/postcss.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | plugins: {
3 | tailwindcss: {},
4 | autoprefixer: {},
5 | },
6 | }
7 |
--------------------------------------------------------------------------------
/public/next.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/public/vercel.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/app/about/error.tsx:
--------------------------------------------------------------------------------
1 | 'use client' // Error components must be Client Components
2 |
3 | import { useEffect } from 'react';
4 |
5 | const Error = ({
6 | error,
7 | reset,
8 | }: {
9 | error: Error & { digest?: string };
10 | reset: () => void;
11 | }) => {
12 | useEffect(() => {
13 | // Log the error to an error reporting service
14 | console.error(error);
15 | }, [error]);
16 |
17 | return (
18 |
19 |
Something went wrong!
20 | {
22 | // Attempt to recover by trying to re-render the segment
23 | reset();
24 | }}
25 | >
26 | Try again
27 |
28 |
29 | );
30 | };
31 |
32 | export default Error;
33 |
--------------------------------------------------------------------------------
/src/app/about/loading.tsx:
--------------------------------------------------------------------------------
1 | import { Spinner } from '@/components'
2 | import React from 'react'
3 |
4 | const loading = () => {
5 | return (
6 | <>
7 |
8 | >
9 | )
10 | }
11 |
12 | export default loading
--------------------------------------------------------------------------------
/src/app/about/not-found.tsx:
--------------------------------------------------------------------------------
1 | import Link from 'next/link'
2 | import React from 'react'
3 |
4 | const NotFound = () => {
5 | return (
6 |
7 |
Not Found
8 |
Could not find requested resource
9 |
Return Home
10 |
11 | )
12 | }
13 |
14 | export default NotFound
--------------------------------------------------------------------------------
/src/app/about/page.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | const About = () => {
4 | return (
5 |
6 |
7 |
About Us
8 |
9 | Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam
10 | fringilla pulvinar libero, id vulputate neque sollicitudin a.
11 | Vestibulum ante ipsum primis in faucibus orci luctus et ultrices
12 | posuere cubilia Curae; Cras consectetur feugiat malesuada.
13 |
14 |
15 |
16 | );
17 | };
18 |
19 | export default About;
20 |
--------------------------------------------------------------------------------
/src/app/contact/error.tsx:
--------------------------------------------------------------------------------
1 | 'use client' // Error components must be Client Components
2 |
3 | import { useEffect } from 'react';
4 |
5 | const Error = ({
6 | error,
7 | reset,
8 | }: {
9 | error: Error & { digest?: string };
10 | reset: () => void;
11 | }) => {
12 | useEffect(() => {
13 | // Log the error to an error reporting service
14 | console.error(error);
15 | }, [error]);
16 |
17 | return (
18 |
19 |
Something went wrong!
20 | {
22 | // Attempt to recover by trying to re-render the segment
23 | reset();
24 | }}
25 | >
26 | Try again
27 |
28 |
29 | );
30 | };
31 |
32 | export default Error;
33 |
--------------------------------------------------------------------------------
/src/app/contact/loading.tsx:
--------------------------------------------------------------------------------
1 | import { Spinner } from '@/components'
2 | import React from 'react'
3 |
4 | const loading = () => {
5 | return (
6 | <>
7 |
8 | >
9 | )
10 | }
11 |
12 | export default loading
--------------------------------------------------------------------------------
/src/app/contact/not-found.tsx:
--------------------------------------------------------------------------------
1 | import Link from 'next/link'
2 | import React from 'react'
3 |
4 | const NotFound = () => {
5 | return (
6 |
7 |
Not Found
8 |
Could not find requested resource
9 |
Return Home
10 |
11 | )
12 | }
13 |
14 | export default NotFound
--------------------------------------------------------------------------------
/src/app/contact/page.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | const Contact = () => {
4 | return (
5 |
6 |
7 |
Contact Us
8 |
9 | If you have any questions or inquiries, feel free to get in touch with
10 | us using the contact information below.
11 |
12 |
13 |
Email: example@example.com
14 |
Phone: +1 (123) 456-7890
15 |
Address: 1234 Elm Street, City, Country
16 |
17 |
18 |
19 | );
20 | };
21 |
22 | export default Contact;
23 |
--------------------------------------------------------------------------------
/src/app/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zied-snoussi/nextjs13-reactjs-typescript-tailwindcss-jest-starter-frontend/feb988463968bd9cf2df5d6aba0dcc10f1adce87/src/app/favicon.ico
--------------------------------------------------------------------------------
/src/app/globals.css:
--------------------------------------------------------------------------------
1 | @tailwind base;
2 | @tailwind components;
3 | @tailwind utilities;
4 |
5 | :root {
6 | --foreground-rgb: 0, 0, 0;
7 | --background-start-rgb: 214, 219, 220;
8 | --background-end-rgb: 255, 255, 255;
9 | }
10 |
11 | @media (prefers-color-scheme: dark) {
12 | :root {
13 | --foreground-rgb: 255, 255, 255;
14 | --background-start-rgb: 0, 0, 0;
15 | --background-end-rgb: 0, 0, 0;
16 | }
17 | }
18 |
19 | body {
20 | color: rgb(var(--foreground-rgb));
21 | background: linear-gradient(
22 | to bottom,
23 | transparent,
24 | rgb(var(--background-end-rgb))
25 | )
26 | rgb(var(--background-start-rgb));
27 | }
28 |
--------------------------------------------------------------------------------
/src/app/layout.tsx:
--------------------------------------------------------------------------------
1 | import { Footer, Navbar } from '@/components'
2 | import './globals.css'
3 | import type { Metadata } from 'next'
4 | import { Inter } from 'next/font/google'
5 |
6 | const inter = Inter({ subsets: ['latin'] })
7 |
8 | export const metadata: Metadata = {
9 | title: 'Starter Next App',
10 | description: 'Generated by create next app',
11 | }
12 |
13 | export default function RootLayout({
14 | children,
15 | }: {
16 | children: React.ReactNode
17 | }) {
18 | return (
19 |
20 |
21 |
22 | {children}
23 |
24 |
25 |
26 | )
27 | }
28 |
--------------------------------------------------------------------------------
/src/app/login/error.tsx:
--------------------------------------------------------------------------------
1 | 'use client' // Error components must be Client Components
2 |
3 | import { useEffect } from 'react';
4 |
5 | const Error = ({
6 | error,
7 | reset,
8 | }: {
9 | error: Error & { digest?: string };
10 | reset: () => void;
11 | }) => {
12 | useEffect(() => {
13 | // Log the error to an error reporting service
14 | console.error(error);
15 | }, [error]);
16 |
17 | return (
18 |
19 |
Something went wrong!
20 | {
22 | // Attempt to recover by trying to re-render the segment
23 | reset();
24 | }}
25 | >
26 | Try again
27 |
28 |
29 | );
30 | };
31 |
32 | export default Error;
33 |
--------------------------------------------------------------------------------
/src/app/login/loading.tsx:
--------------------------------------------------------------------------------
1 | import { Spinner } from '@/components'
2 | import React from 'react'
3 |
4 | const loading = () => {
5 | return (
6 | <>
7 |
8 | >
9 | )
10 | }
11 |
12 | export default loading
--------------------------------------------------------------------------------
/src/app/login/not-found.tsx:
--------------------------------------------------------------------------------
1 | import Link from 'next/link'
2 | import React from 'react'
3 |
4 | const NotFound = () => {
5 | return (
6 |
7 |
Not Found
8 |
Could not find requested resource
9 |
Return Home
10 |
11 | )
12 | }
13 |
14 | export default NotFound
--------------------------------------------------------------------------------
/src/app/login/page.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | const Login = () => {
4 | return (
5 |
46 | );
47 | };
48 |
49 | export default Login;
50 |
--------------------------------------------------------------------------------
/src/app/page.tsx:
--------------------------------------------------------------------------------
1 | export default function Home() {
2 | // Example content data
3 | const features = [
4 | {
5 | icon: '🚀',
6 | title: 'Fast Performance',
7 | description: 'Next.js provides fast server rendering and optimized production builds.',
8 | },
9 | {
10 | icon: '🛠️',
11 | title: 'Easy Development',
12 | description: 'Develop with ease using Next.js and Tailwind CSS for styling.',
13 | },
14 | {
15 | icon: '📚',
16 | title: 'Interactive Learning',
17 | description: 'Learn and practice Next.js with interactive quizzes.',
18 | },
19 | ];
20 |
21 | return (
22 |
23 |
24 |
Welcome to My Next.js Starter Template
25 |
This is the home page of your starter template.
26 |
27 |
28 | {features.map((feature, index) => (
29 |
30 |
{feature.icon}
31 |
32 |
{feature.title}
33 |
{feature.description}
34 |
35 |
36 | ))}
37 |
38 |
39 |
40 | );
41 | }
--------------------------------------------------------------------------------
/src/app/services/error.tsx:
--------------------------------------------------------------------------------
1 | 'use client' // Error components must be Client Components
2 |
3 | import { useEffect } from 'react';
4 |
5 | const Error = ({
6 | error,
7 | reset,
8 | }: {
9 | error: Error & { digest?: string };
10 | reset: () => void;
11 | }) => {
12 | useEffect(() => {
13 | // Log the error to an error reporting service
14 | console.error(error);
15 | }, [error]);
16 |
17 | return (
18 |
19 |
Something went wrong!
20 | {
22 | // Attempt to recover by trying to re-render the segment
23 | reset();
24 | }}
25 | >
26 | Try again
27 |
28 |
29 | );
30 | };
31 |
32 | export default Error;
33 |
--------------------------------------------------------------------------------
/src/app/services/loading.tsx:
--------------------------------------------------------------------------------
1 | import { Spinner } from '@/components'
2 | import React from 'react'
3 |
4 | const loading = () => {
5 | return (
6 | <>
7 |
8 | >
9 | )
10 | }
11 |
12 | export default loading
--------------------------------------------------------------------------------
/src/app/services/not-found.tsx:
--------------------------------------------------------------------------------
1 | import Link from 'next/link'
2 | import React from 'react'
3 |
4 | const NotFound = () => {
5 | return (
6 |
7 |
Not Found
8 |
Could not find requested resource
9 |
Return Home
10 |
11 | )
12 | }
13 |
14 | export default NotFound
--------------------------------------------------------------------------------
/src/app/services/page.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | const Services = () => {
4 | return (
5 |
6 |
7 |
Our Services
8 |
9 | Service 1: Description of Service 1.
10 | Service 2: Description of Service 2.
11 | Service 3: Description of Service 3.
12 | Service 4: Description of Service 4.
13 |
14 |
15 |
16 | );
17 | };
18 |
19 | export default Services;
20 |
--------------------------------------------------------------------------------
/src/components/Footer/Footer.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | const Footer = () => {
4 | return (
5 |
10 | );
11 | };
12 |
13 | export default Footer;
14 |
--------------------------------------------------------------------------------
/src/components/Navbar/Navbar.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import Link from 'next/link';
3 |
4 | const Navbar = () => {
5 | return (
6 |
7 |
8 |
My App
9 |
10 |
11 |
12 |
13 | Home
14 |
15 |
16 |
17 |
18 | About
19 |
20 |
21 |
22 |
23 | Services
24 |
25 |
26 |
27 |
28 | Contact
29 |
30 |
31 |
32 |
33 |
34 | );
35 | };
36 |
37 | export default Navbar;
38 |
--------------------------------------------------------------------------------
/src/components/Spinner/Spinner.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | const Spinner = () => {
4 | return (
5 |
8 | );
9 | };
10 |
11 | export default Spinner;
12 |
--------------------------------------------------------------------------------
/src/components/index.tsx:
--------------------------------------------------------------------------------
1 | export { default as Footer } from './Footer/Footer'
2 | export { default as Navbar } from './Navbar/Navbar'
3 | export { default as Spinner } from './Spinner/Spinner'
--------------------------------------------------------------------------------
/tailwind.config.ts:
--------------------------------------------------------------------------------
1 | import type { Config } from 'tailwindcss'
2 |
3 | const config: Config = {
4 | content: [
5 | './src/pages/**/*.{js,ts,jsx,tsx,mdx}',
6 | './src/components/**/*.{js,ts,jsx,tsx,mdx}',
7 | './src/app/**/*.{js,ts,jsx,tsx,mdx}',
8 | ],
9 | theme: {
10 | extend: {
11 | backgroundImage: {
12 | 'gradient-radial': 'radial-gradient(var(--tw-gradient-stops))',
13 | 'gradient-conic':
14 | 'conic-gradient(from 180deg at 50% 50%, var(--tw-gradient-stops))',
15 | },
16 | },
17 | },
18 | plugins: [],
19 | }
20 | export default config
21 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es5",
4 | "lib": ["dom", "dom.iterable", "esnext"],
5 | "allowJs": true,
6 | "skipLibCheck": true,
7 | "strict": true,
8 | "noEmit": true,
9 | "esModuleInterop": true,
10 | "module": "esnext",
11 | "moduleResolution": "bundler",
12 | "resolveJsonModule": true,
13 | "isolatedModules": true,
14 | "jsx": "preserve",
15 | "incremental": true,
16 | "plugins": [
17 | {
18 | "name": "next"
19 | }
20 | ],
21 | "paths": {
22 | "@/*": ["./src/*"]
23 | }
24 | },
25 | "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
26 | "exclude": ["node_modules"]
27 | }
28 |
--------------------------------------------------------------------------------