Skip to content

Commit

Permalink
Initial commit from Create Next App
Browse files Browse the repository at this point in the history
  • Loading branch information
ccrsxx committed Aug 31, 2022
0 parents commit fd01013
Show file tree
Hide file tree
Showing 31 changed files with 15,901 additions and 0 deletions.
9 changes: 9 additions & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# next config
next.config.js

# tailwind config
tailwind.config.js
postcss.config.js

# jest config
jest.config.js
76 changes: 76 additions & 0 deletions .eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
{
"parser": "@typescript-eslint/parser",
"parserOptions": {
"project": "./tsconfig.json"
},
"plugins": ["@typescript-eslint"],
"extends": [
"eslint:recommended",
"plugin:import/recommended",
"plugin:import/typescript",
"plugin:@typescript-eslint/recommended",
"plugin:@typescript-eslint/recommended-requiring-type-checking",
"next/core-web-vitals"
],
"settings": {
"import/resolver": {
"typescript": true,
"node": true
}
},
"rules": {
"semi": ["warn", "always"],
"curly": ["warn", "multi"],
"quotes": ["error", "single", { "avoidEscape": true }],
"jsx-quotes": ["error", "prefer-single"],
"linebreak-style": ["error", "unix"],
"no-console": "warn",
"comma-dangle": ["error", "never"],
"no-unused-expressions": "error",
"import/order": [
"error",
{
"pathGroups": [
{
"pattern": "*.scss",
"group": "builtin",
"position": "before",
"patternOptions": { "matchBase": true }
},
{
"pattern": "@lib/**",
"group": "external",
"position": "after"
},
{
"pattern": "@components/**",
"group": "external",
"position": "after"
}
],
"warnOnUnassignedImports": true,
"groups": [
"builtin",
"external",
"internal",
"parent",
"sibling",
"index",
"object",
"type"
]
}
],
"@typescript-eslint/no-misused-promises": [
"error",
{
"checksVoidReturn": {
"attributes": false
}
}
],
"@typescript-eslint/consistent-type-imports": "error",
"@typescript-eslint/prefer-nullish-coalescing": "error",
"@typescript-eslint/explicit-function-return-type": "error"
}
}
48 changes: 48 additions & 0 deletions .github/workflows/deployment.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
name: Deploy 🚀

on:
push:
branches: ['main']
pull_request:
branches: ['main']

jobs:
prettier:
name: 🧪 Prettier
runs-on: ubuntu-latest
steps:
- name: ⬇️ Checkout repo
uses: actions/checkout@v3

- name: 📥 Download deps
run: npm ci

- name: 🔍 Format
run: npm run format

eslint:
name: ✅ ESLint
runs-on: ubuntu-latest
steps:
- name: ⬇️ Checkout repo
uses: actions/checkout@v3

- name: 📥 Download deps
run: npm ci

- name: 🪄 Lint
run: npm run lint

jest:
name: 🃏 Jest
runs-on: ubuntu-latest
steps:
- name: ⬇️ Checkout repo
uses: actions/checkout@v3

- name: 📥 Download deps
run: npm ci

# ! uncomment this after you add test
# - name: 🔬 Test
# run: npm run test:ci
36 changes: 36 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.

# dependencies
/node_modules
/.pnp
.pnp.js

# testing
/coverage

# next.js
/.next/
/out/

# production
/build

# misc
.DS_Store
*.pem

# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*
.pnpm-debug.log*

# local env files
.env*.local

# vercel
.vercel

# typescript
*.tsbuildinfo
next-env.d.ts
6 changes: 6 additions & 0 deletions .husky/pre-commit
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"

exec 1> /dev/tty

npx lint-staged
9 changes: 9 additions & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# testing
/coverage

# next.js
/.next/
/out/

# production
/build
5 changes: 5 additions & 0 deletions .prettierrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"singleQuote": true,
"jsxSingleQuote": true,
"trailingComma": "none"
}
29 changes: 29 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# My Next.js App Template

This is my next.js app template. It is a simple starter template that includes Next.js, TypeScript, Tailwind CSS, ESLint, and Jest.

## Installation

1. Clone this template using create-next-app:

```bash
npx create-next-app -e https://github.com/ccrsxx/next-template app-name
```

2. Change the directory name to your own app name:

```bash
cd app-name
```

3. Install dependencies:

```bash
npm i
```

4. Run the development server:

```bash
npm run dev
```
3 changes: 3 additions & 0 deletions components/common/footer.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export function Footer(): JSX.Element {
return <footer></footer>;
}
3 changes: 3 additions & 0 deletions components/common/header.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export function Header(): JSX.Element {
return <header></header>;
}
9 changes: 9 additions & 0 deletions components/common/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import type { ReactNode } from 'react';

type LayoutProps = {
children: ReactNode;
};

export function Layout({ children }: LayoutProps): JSX.Element {
return <>{children}</>;
}
39 changes: 39 additions & 0 deletions components/common/seo.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { useRouter } from 'next/router';
import Head from 'next/head';

type MainLayoutProps = {
title?: string;
image?: string;
product?: boolean;
className?: string;
description?: string;
};

// ! This is a site placeholder, replace with your own url
const siteUrl = 'https://github.com/ccrsxx/next-template';

export function SEO({
title,
image,
description
}: MainLayoutProps): JSX.Element {
const { asPath } = useRouter();

const siteTitle = title;
const siteDescription = description;
const siteImage = image;

return (
<Head>
<title>{siteTitle}</title>
<meta name='og:title' content={siteTitle} />
<meta name='description' content={siteDescription} />
<meta name='og:description' content={siteDescription} />
<meta property='og:image' content={siteImage} />
<meta
name='og:url'
content={`${siteUrl}${asPath === '/' ? '' : asPath}`}
/>
</Head>
);
}
32 changes: 32 additions & 0 deletions components/ui/button.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import cn from 'clsx';
import { VscLoading } from 'react-icons/vsc';

type ButtonProps = {
isLoading?: boolean;
} & React.ComponentPropsWithRef<'button'>;

export function Button({
className,
isLoading,
disabled,
children,
...rest
}: ButtonProps): JSX.Element {
const isDisabled = isLoading ?? disabled;

return (
<button
className={cn(className)}
type='button'
disabled={isDisabled}
{...rest}
>
{isLoading && (
<div className='absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2'>
<VscLoading className='animate-spin' />
</div>
)}
{children}
</button>
);
}
59 changes: 59 additions & 0 deletions components/ui/next-image.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import { useState } from 'react';
import Image from 'next/image';
import cn from 'clsx';
import type { ImageProps } from 'next/image';

type NextImageProps = {
useSkeleton?: boolean;
imgClassName?: string;
blurClassName?: string;
alt: string;
width: string | number;
} & (
| { width: string | number; height: string | number }
| { layout: 'fill'; width?: string | number; height?: string | number }
) &
ImageProps;

/**
*
* @description Must set width using `w-` className
* @param useSkeleton add background with pulse animation, don't use it if image is transparent
*/
export default function NextImage({
useSkeleton,
src,
width,
height,
alt,
className,
imgClassName,
blurClassName,
...rest
}: NextImageProps): JSX.Element {
const [status, setStatus] = useState(useSkeleton ? 'loading' : 'complete');
const widthIsSet = className?.includes('w-') ?? false;

const handleLoad = (): void => setStatus('complete');

return (
<figure
style={!widthIsSet ? { width: `${width}px` } : undefined}
className={className}
>
<Image
className={cn(
imgClassName,
status === 'loading' && cn('animate-pulse', blurClassName)
)}
src={src}
width={width}
height={height}
alt={alt}
onLoadingComplete={handleLoad}
layout='responsive'
{...rest}
/>
</figure>
);
}
Loading

0 comments on commit fd01013

Please sign in to comment.