@devkitlab/create-nextjs 0.2.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +69 -0
- package/bin/create-nextjs.mjs +100 -0
- package/package.json +35 -0
- package/template/.eslintrc.json +10 -0
- package/template/.husky/pre-commit +5 -0
- package/template/.prettierrc +11 -0
- package/template/.vscode/settings.json +11 -0
- package/template/README.md +70 -0
- package/template/app/(home)/page.tsx +14 -0
- package/template/app/(home)/sub-components/another-section.tsx +12 -0
- package/template/app/(home)/sub-components/hero-section.tsx +29 -0
- package/template/app/_layout/footer.tsx +12 -0
- package/template/app/_layout/header.tsx +41 -0
- package/template/app/favicon.ico +0 -0
- package/template/app/layout.tsx +31 -0
- package/template/app/provider.tsx +15 -0
- package/template/app/styles.css +72 -0
- package/template/next.config.ts +9 -0
- package/template/package.json +50 -0
- package/template/postcss.config.mjs +8 -0
- package/template/public/next.svg +1 -0
- package/template/public/vercel.svg +1 -0
- package/template/src/components/button/index.tsx +42 -0
- package/template/src/components/button/interface.ts +6 -0
- package/template/src/components/container/index.tsx +13 -0
- package/template/src/components/container/interface.ts +6 -0
- package/template/src/components/icon-store/arrow-icons.tsx +19 -0
- package/template/src/components/icon-store/index.tsx +26 -0
- package/template/src/components/icon-store/interface.ts +10 -0
- package/template/src/components/icon-store/weather-icons.tsx +45 -0
- package/template/src/components/loader/index.tsx +20 -0
- package/template/src/components/loader/interface.ts +3 -0
- package/template/src/components/typography/index.tsx +10 -0
- package/template/src/components/typography/interface.ts +13 -0
- package/template/src/utils/class-merge.ts +4 -0
- package/template/tailwind.config.ts +52 -0
- package/template/tsconfig.json +23 -0
- package/template/yarn.lock +4312 -0
package/README.md
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# @devkitlab/create-nextjs
|
|
2
|
+
|
|
3
|
+
Scaffold a DevkitLab Next.js starter with TypeScript, Tailwind CSS, and a ready-to-extend project structure.
|
|
4
|
+
|
|
5
|
+
## Why Use It
|
|
6
|
+
|
|
7
|
+
- Start faster with an opinionated Next.js setup
|
|
8
|
+
- Skip repetitive project bootstrapping
|
|
9
|
+
- Get a clean base for content-driven or product-focused apps
|
|
10
|
+
- Use a starter that already includes common developer tooling
|
|
11
|
+
|
|
12
|
+
## What You Get
|
|
13
|
+
|
|
14
|
+
- Next.js App Router
|
|
15
|
+
- TypeScript
|
|
16
|
+
- Tailwind CSS
|
|
17
|
+
- Sanity starter wiring
|
|
18
|
+
- ESLint and Prettier
|
|
19
|
+
- Husky and lint-staged
|
|
20
|
+
- Reusable starter structure for components and app sections
|
|
21
|
+
|
|
22
|
+
## Installation
|
|
23
|
+
|
|
24
|
+
Create a new app with:
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
npx @devkitlab/create-nextjs@latest my-app
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Then move into the project and install dependencies:
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
cd my-app
|
|
34
|
+
npm install
|
|
35
|
+
npm run dev
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
You can also use `pnpm` or `yarn` instead of `npm`.
|
|
39
|
+
|
|
40
|
+
## Getting Started
|
|
41
|
+
|
|
42
|
+
After installation:
|
|
43
|
+
|
|
44
|
+
1. Create a `.env.local` file if you need environment variables.
|
|
45
|
+
2. Start the development server with `npm run dev`.
|
|
46
|
+
3. Open `http://localhost:3000`.
|
|
47
|
+
4. Begin editing the generated app.
|
|
48
|
+
|
|
49
|
+
## Generated Project Highlights
|
|
50
|
+
|
|
51
|
+
- App code lives in `app/`
|
|
52
|
+
- Shared UI and utilities live in `src/`
|
|
53
|
+
- Static assets live in `public/`
|
|
54
|
+
- Tailwind is preconfigured
|
|
55
|
+
- Linting and formatting are already set up
|
|
56
|
+
|
|
57
|
+
## Who It’s For
|
|
58
|
+
|
|
59
|
+
This starter is useful if you want:
|
|
60
|
+
|
|
61
|
+
- a modern Next.js + TypeScript base
|
|
62
|
+
- Tailwind configured out of the box
|
|
63
|
+
- a starter that can grow into a CMS-backed app
|
|
64
|
+
- a reusable foundation for client projects or internal tools
|
|
65
|
+
|
|
66
|
+
## Package
|
|
67
|
+
|
|
68
|
+
- npm: `@devkitlab/create-nextjs`
|
|
69
|
+
- repository: `shahadat-robin/devkitlab-nextjs`
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { cp, mkdir, readFile, readdir, rename, writeFile } from 'node:fs/promises';
|
|
4
|
+
import path from 'node:path';
|
|
5
|
+
import process from 'node:process';
|
|
6
|
+
import { fileURLToPath } from 'node:url';
|
|
7
|
+
|
|
8
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
9
|
+
const __dirname = path.dirname(__filename);
|
|
10
|
+
const templateDir = path.resolve(__dirname, '..', 'template');
|
|
11
|
+
|
|
12
|
+
const rawProjectName = process.argv[2] || 'my-devkitlab-app';
|
|
13
|
+
const projectName = rawProjectName.trim();
|
|
14
|
+
|
|
15
|
+
if (!projectName) {
|
|
16
|
+
console.error('Project name cannot be empty.');
|
|
17
|
+
process.exit(1);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const targetDir = path.resolve(process.cwd(), projectName);
|
|
21
|
+
|
|
22
|
+
try {
|
|
23
|
+
await mkdir(targetDir, { recursive: true });
|
|
24
|
+
const existingEntries = await readdir(targetDir);
|
|
25
|
+
|
|
26
|
+
if (existingEntries.length > 0) {
|
|
27
|
+
console.error(`Target directory is not empty: ${targetDir}`);
|
|
28
|
+
process.exit(1);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
await cp(templateDir, targetDir, {
|
|
32
|
+
recursive: true,
|
|
33
|
+
filter: source => {
|
|
34
|
+
const relativePath = path.relative(templateDir, source);
|
|
35
|
+
|
|
36
|
+
return relativePath !== '.DS_Store';
|
|
37
|
+
},
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
await renameIfExists(path.join(targetDir, 'gitignore'), path.join(targetDir, '.gitignore'));
|
|
41
|
+
await renameIfExists(path.join(targetDir, 'env.example'), path.join(targetDir, '.env.example'));
|
|
42
|
+
|
|
43
|
+
const packageJsonPath = path.join(targetDir, 'package.json');
|
|
44
|
+
const packageJson = JSON.parse(await readFile(packageJsonPath, 'utf8'));
|
|
45
|
+
|
|
46
|
+
packageJson.name = toPackageName(projectName);
|
|
47
|
+
|
|
48
|
+
await writeFile(packageJsonPath, `${JSON.stringify(packageJson, null, 2)}\n`);
|
|
49
|
+
|
|
50
|
+
const packageManager = detectPackageManager();
|
|
51
|
+
|
|
52
|
+
console.log('');
|
|
53
|
+
console.log('DevkitLab Next.js starter created successfully.');
|
|
54
|
+
console.log('');
|
|
55
|
+
console.log('Next steps:');
|
|
56
|
+
console.log(` cd ${projectName}`);
|
|
57
|
+
console.log(` ${packageManager} install`);
|
|
58
|
+
console.log(` ${packageManager} run dev`);
|
|
59
|
+
console.log('');
|
|
60
|
+
} catch (error) {
|
|
61
|
+
console.error('Failed to create project.');
|
|
62
|
+
console.error(error instanceof Error ? error.message : error);
|
|
63
|
+
process.exit(1);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function toPackageName(value) {
|
|
67
|
+
return (
|
|
68
|
+
value
|
|
69
|
+
.toLowerCase()
|
|
70
|
+
.trim()
|
|
71
|
+
.replace(/[^a-z0-9-_]+/g, '-')
|
|
72
|
+
.replace(/^-+|-+$/g, '') || 'my-devkitlab-app'
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function detectPackageManager() {
|
|
77
|
+
const userAgent = process.env.npm_config_user_agent || '';
|
|
78
|
+
|
|
79
|
+
if (userAgent.startsWith('yarn')) {
|
|
80
|
+
return 'yarn';
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
if (userAgent.startsWith('pnpm')) {
|
|
84
|
+
return 'pnpm';
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
return 'npm';
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
async function renameIfExists(fromPath, toPath) {
|
|
91
|
+
try {
|
|
92
|
+
await rename(fromPath, toPath);
|
|
93
|
+
} catch (error) {
|
|
94
|
+
if (error && typeof error === 'object' && 'code' in error && error.code === 'ENOENT') {
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
throw error;
|
|
99
|
+
}
|
|
100
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@devkitlab/create-nextjs",
|
|
3
|
+
"version": "0.2.9",
|
|
4
|
+
"description": "Create a DevkitLab Next.js starter app with TypeScript and Tailwind CSS.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"create-nextjs": "./bin/create-nextjs.mjs"
|
|
8
|
+
},
|
|
9
|
+
"files": [
|
|
10
|
+
"bin",
|
|
11
|
+
"template"
|
|
12
|
+
],
|
|
13
|
+
"keywords": [
|
|
14
|
+
"create-next-app",
|
|
15
|
+
"nextjs",
|
|
16
|
+
"typescript",
|
|
17
|
+
"tailwindcss",
|
|
18
|
+
"starter",
|
|
19
|
+
"scaffold"
|
|
20
|
+
],
|
|
21
|
+
"repository": {
|
|
22
|
+
"type": "git",
|
|
23
|
+
"url": "git+https://github.com/shahadat-robin/devkitlab-nextjs.git"
|
|
24
|
+
},
|
|
25
|
+
"bugs": {
|
|
26
|
+
"url": "https://github.com/shahadat-robin/devkitlab-nextjs/issues"
|
|
27
|
+
},
|
|
28
|
+
"license": "MIT",
|
|
29
|
+
"engines": {
|
|
30
|
+
"node": ">=18.17.0"
|
|
31
|
+
},
|
|
32
|
+
"publishConfig": {
|
|
33
|
+
"access": "public"
|
|
34
|
+
}
|
|
35
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
{
|
|
2
|
+
"editor.fontLigatures": true,
|
|
3
|
+
"editor.cursorBlinking": "expand",
|
|
4
|
+
"editor.cursorSmoothCaretAnimation": "explicit",
|
|
5
|
+
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
|
6
|
+
"editor.formatOnPaste": true,
|
|
7
|
+
"editor.formatOnSave": true,
|
|
8
|
+
"editor.codeActionsOnSave": {
|
|
9
|
+
"source.organizeImports": "always"
|
|
10
|
+
}
|
|
11
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# NextJS-Starter
|
|
2
|
+
|
|
3
|
+
This is a [Next.js](https://nextjs.org/) project starter kit bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app).
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Next.js 14:** The latest version of Next.js with all its powerful features.
|
|
8
|
+
- **TypeScript:** TypeScript support for type safety and better developer experience.
|
|
9
|
+
- **Tailwind CSS:** Utility-first CSS framework for rapid UI development.
|
|
10
|
+
- **Theaming:** Dark and Light theme enhanched.
|
|
11
|
+
- **ESLint and Prettier:** Code quality tools to maintain a consistent codebase.
|
|
12
|
+
- **Husky:** Automatically lint commit messages and code upon committing.
|
|
13
|
+
- **Environment Variables:** Easy management of environment variables.
|
|
14
|
+
- **Customizable Layout:** Flexible layouting components.
|
|
15
|
+
|
|
16
|
+
This project uses [`next/font`](https://nextjs.org/docs/basic-features/font-optimization) to automatically optimize and load Inter, a custom Google Font.
|
|
17
|
+
|
|
18
|
+
## Getting Start
|
|
19
|
+
|
|
20
|
+
### Prerequisites
|
|
21
|
+
|
|
22
|
+
- Node.js (>= 18.17)
|
|
23
|
+
- yarn
|
|
24
|
+
|
|
25
|
+
### Installation
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
|
|
29
|
+
# Clone the repository:
|
|
30
|
+
git clone https://github.com/yourusername/NextJS-Starter.git
|
|
31
|
+
|
|
32
|
+
# Go to project directory
|
|
33
|
+
cd NextJS-Starter
|
|
34
|
+
|
|
35
|
+
# Install dependencies:
|
|
36
|
+
yarn
|
|
37
|
+
|
|
38
|
+
# Start the development server:
|
|
39
|
+
yarn dev
|
|
40
|
+
# or
|
|
41
|
+
npm run dev
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Open [http://localhost:3000](http://localhost:3000) into your browser to see the result.
|
|
45
|
+
|
|
46
|
+
## Project Structure
|
|
47
|
+
|
|
48
|
+
```plaintext
|
|
49
|
+
NextJS-Starter/
|
|
50
|
+
├── public/ # Static assets
|
|
51
|
+
│ app/ # Next.js pages
|
|
52
|
+
│ ├── _layout/ # Layout components
|
|
53
|
+
│ └── (home)/ # Home page grouping
|
|
54
|
+
├── src/
|
|
55
|
+
│ ├── components/ # Reusable components
|
|
56
|
+
│ ├── utils/ # Utility functions
|
|
57
|
+
│ ├── hooks/ # Custom React hooks
|
|
58
|
+
│ └── services/ # API services
|
|
59
|
+
├── .eslintrc.json # ESLint configuration
|
|
60
|
+
├── .prettierrc # Prettier configuration
|
|
61
|
+
├── next.config.js # Next.js configuration
|
|
62
|
+
├── tsconfig.json # TypeScript configuration
|
|
63
|
+
└── package.json # Project metadata and scripts
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## Learn More
|
|
67
|
+
|
|
68
|
+
To learn more about Next.js, take a look at the following resources:
|
|
69
|
+
|
|
70
|
+
- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { NextPage } from 'next';
|
|
2
|
+
import AnotherSection from './sub-components/another-section';
|
|
3
|
+
import HeroSection from './sub-components/hero-section';
|
|
4
|
+
|
|
5
|
+
const HomePage: NextPage = () => (
|
|
6
|
+
<>
|
|
7
|
+
<HeroSection />
|
|
8
|
+
<AnotherSection />
|
|
9
|
+
<AnotherSection />
|
|
10
|
+
<AnotherSection />
|
|
11
|
+
</>
|
|
12
|
+
);
|
|
13
|
+
|
|
14
|
+
export default HomePage;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import Container from '@/components/container';
|
|
2
|
+
import Typography from '@/components/typography';
|
|
3
|
+
|
|
4
|
+
export default function AnotherSection() {
|
|
5
|
+
return (
|
|
6
|
+
<section className="min-h-screen shadow section-padding">
|
|
7
|
+
<Container className="text-center">
|
|
8
|
+
<Typography variant="h2">This is another section</Typography>
|
|
9
|
+
</Container>
|
|
10
|
+
</section>
|
|
11
|
+
);
|
|
12
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import Button from '@/components/button';
|
|
2
|
+
import Container from '@/components/container';
|
|
3
|
+
import IconStore from '@/components/icon-store';
|
|
4
|
+
import Typography from '@/components/typography';
|
|
5
|
+
import { cn } from '@/utils/class-merge';
|
|
6
|
+
|
|
7
|
+
export default function HeroSection() {
|
|
8
|
+
return (
|
|
9
|
+
<section className={cn(`flex section-padding min-h-screen`)}>
|
|
10
|
+
<Container className="flex items-center justify-center">
|
|
11
|
+
<div className="text-center space-y-5">
|
|
12
|
+
<Typography variant="h1">This is Hero Section</Typography>
|
|
13
|
+
<Typography className="lg:w-3/5 mx-auto">
|
|
14
|
+
Lorem ipsum dolor sit amet consectetur adipisicing elit. Eius fuga culpa ea velit
|
|
15
|
+
tempore libero ullam natus ipsa architecto iusto porro inventore unde deleniti quibusdam
|
|
16
|
+
accusantium, ad error, beatae adipisci?
|
|
17
|
+
</Typography>
|
|
18
|
+
|
|
19
|
+
<Button
|
|
20
|
+
variant="secondary"
|
|
21
|
+
className="border border-primary text-primary dark:text-white"
|
|
22
|
+
>
|
|
23
|
+
Explore <IconStore name="arrow-right-long" className="text-xl" />
|
|
24
|
+
</Button>
|
|
25
|
+
</div>
|
|
26
|
+
</Container>
|
|
27
|
+
</section>
|
|
28
|
+
);
|
|
29
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import Container from '@/components/container';
|
|
2
|
+
import Typography from '@/components/typography';
|
|
3
|
+
|
|
4
|
+
export default function Footer() {
|
|
5
|
+
return (
|
|
6
|
+
<footer className="bg-primary dark:bg-dark-light">
|
|
7
|
+
<Container className="py-5 text-center">
|
|
8
|
+
<Typography>This is Footer</Typography>
|
|
9
|
+
</Container>
|
|
10
|
+
</footer>
|
|
11
|
+
);
|
|
12
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import Container from '@/components/container';
|
|
4
|
+
import IconStore from '@/components/icon-store';
|
|
5
|
+
import { useTheme } from 'next-themes';
|
|
6
|
+
import Image from 'next/image';
|
|
7
|
+
|
|
8
|
+
export default function AppHeader() {
|
|
9
|
+
const { theme, setTheme } = useTheme();
|
|
10
|
+
|
|
11
|
+
return (
|
|
12
|
+
<header className="py-5 sticky top-0 bg-primary dark:bg-dark-light z-50">
|
|
13
|
+
<Container className="flex items-center justify-between">
|
|
14
|
+
<Image
|
|
15
|
+
src="/next.svg"
|
|
16
|
+
alt="Brand logo"
|
|
17
|
+
width={100}
|
|
18
|
+
height={50}
|
|
19
|
+
className="h-auto w-[6.25rem] cursor-pointer"
|
|
20
|
+
priority
|
|
21
|
+
/>
|
|
22
|
+
|
|
23
|
+
<label htmlFor="theme-toggle" className="flex items-center cursor-pointer">
|
|
24
|
+
<div className="relative min-h-[30px] w-[55px] rounded-full bg-white">
|
|
25
|
+
<input
|
|
26
|
+
type="checkbox"
|
|
27
|
+
name="theme-mode"
|
|
28
|
+
id="theme-toggle"
|
|
29
|
+
className="checkbox hidden"
|
|
30
|
+
onChange={() => setTheme(theme === 'light' ? 'dark' : 'light')}
|
|
31
|
+
/>
|
|
32
|
+
<div className="absolute right-1 top-1/2 -translate-y-1/2 bg-dark-light p-1 rounded-full transition-transform duration-200 dark:transform dark:-translate-x-full">
|
|
33
|
+
<IconStore name="moon" className="hidden dark:block text-white" />
|
|
34
|
+
<IconStore name="sun" className="block dark:hidden text-yellow-500" />
|
|
35
|
+
</div>
|
|
36
|
+
</div>
|
|
37
|
+
</label>
|
|
38
|
+
</Container>
|
|
39
|
+
</header>
|
|
40
|
+
);
|
|
41
|
+
}
|
|
Binary file
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { Metadata } from 'next';
|
|
2
|
+
import type { PropsWithChildren } from 'react';
|
|
3
|
+
import Footer from './_layout/footer';
|
|
4
|
+
import AppHeader from './_layout/header';
|
|
5
|
+
import RootProvider from './provider';
|
|
6
|
+
import './styles.css';
|
|
7
|
+
|
|
8
|
+
// const inter = Inter({
|
|
9
|
+
// subsets: ['latin'],
|
|
10
|
+
// style: 'normal',
|
|
11
|
+
// weight: ['400', '500', '600', '700'],
|
|
12
|
+
// });
|
|
13
|
+
|
|
14
|
+
export const metadata: Metadata = {
|
|
15
|
+
title: 'NextJS Project Starter',
|
|
16
|
+
description: 'Generated by create-next-app and tailwind',
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export default function RootLayout({ children }: Readonly<PropsWithChildren>) {
|
|
20
|
+
return (
|
|
21
|
+
<html lang="en" suppressHydrationWarning>
|
|
22
|
+
<body cz-shortcut-listen="true">
|
|
23
|
+
<RootProvider>
|
|
24
|
+
<AppHeader />
|
|
25
|
+
{children}
|
|
26
|
+
<Footer />
|
|
27
|
+
</RootProvider>
|
|
28
|
+
</body>
|
|
29
|
+
</html>
|
|
30
|
+
);
|
|
31
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import ReactLenis from 'lenis/react';
|
|
4
|
+
import { ThemeProvider } from 'next-themes';
|
|
5
|
+
import type { FC, PropsWithChildren } from 'react';
|
|
6
|
+
|
|
7
|
+
const RootProvider: FC<Readonly<PropsWithChildren>> = ({ children }) => (
|
|
8
|
+
<ReactLenis root>
|
|
9
|
+
<ThemeProvider attribute="class" defaultTheme="light">
|
|
10
|
+
{children}
|
|
11
|
+
</ThemeProvider>
|
|
12
|
+
</ReactLenis>
|
|
13
|
+
);
|
|
14
|
+
|
|
15
|
+
export default RootProvider;
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
@import url('https://fonts.googleapis.com/css2?family=Averia+Serif+Libre:ital,wght@0,300;0,400;0,700;1,300;1,400;1,700&family=Roboto+Slab:wght@400..700&display=swap');
|
|
2
|
+
|
|
3
|
+
@tailwind base;
|
|
4
|
+
@layer base {
|
|
5
|
+
body {
|
|
6
|
+
@apply bg-white-deep dark:bg-dark font-body;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
h1,
|
|
10
|
+
h2,
|
|
11
|
+
h3,
|
|
12
|
+
h4,
|
|
13
|
+
h5,
|
|
14
|
+
h6 {
|
|
15
|
+
@apply font-semibold font-heading;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
h1 {
|
|
19
|
+
font-size: clamp(2rem, 10vw, 3rem); /* 32px → 48px */
|
|
20
|
+
line-height: clamp(2.5rem, 11vw, 4rem); /* Fluid height */
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
h2 {
|
|
24
|
+
font-size: clamp(1.5rem, 8vw, 2rem); /* 24px → 32px */
|
|
25
|
+
line-height: clamp(2rem, 9vw, 3rem);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
h3 {
|
|
29
|
+
font-size: clamp(1.25rem, 6vw, 1.5rem); /* 20px → 24px */
|
|
30
|
+
line-height: clamp(1.75rem, 7vw, 2.5rem);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
h4 {
|
|
34
|
+
font-size: clamp(1.125rem, 4vw, 1.25rem); /* 18px → 20px */
|
|
35
|
+
line-height: clamp(1.5rem, 5vw, 2rem);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
h5 {
|
|
39
|
+
font-size: clamp(1rem, 3vw, 1.125rem); /* 16px → 18px */
|
|
40
|
+
line-height: clamp(1.25rem, 4vw, 1.75rem);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
h6 {
|
|
44
|
+
font-size: clamp(0.875rem, 2vw, 1rem); /* 14px → 16px */
|
|
45
|
+
line-height: clamp(1.125rem, 3vw, 1.5rem);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
p,
|
|
49
|
+
a,
|
|
50
|
+
ol,
|
|
51
|
+
ul,
|
|
52
|
+
li,
|
|
53
|
+
label,
|
|
54
|
+
div,
|
|
55
|
+
span {
|
|
56
|
+
font-size: clamp(0.875rem, 2vw, 1rem);
|
|
57
|
+
line-height: clamp(1.125rem, 3vw, 1.5rem);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
.container {
|
|
61
|
+
@apply px-4;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
@tailwind components;
|
|
66
|
+
|
|
67
|
+
@tailwind utilities;
|
|
68
|
+
@layer utilities {
|
|
69
|
+
.section-padding {
|
|
70
|
+
padding: min(10vw, 5rem) 0;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "nextjs-starter-boilerplate",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"private": true,
|
|
5
|
+
"type": "module",
|
|
6
|
+
"engines": {
|
|
7
|
+
"node": ">=18.17.0",
|
|
8
|
+
"yarn": ">=1.22.0"
|
|
9
|
+
},
|
|
10
|
+
"scripts": {
|
|
11
|
+
"preinstall": "npx only-allow yarn",
|
|
12
|
+
"dev": "next dev --turbopack",
|
|
13
|
+
"build": "next build",
|
|
14
|
+
"start": "next start",
|
|
15
|
+
"format": "prettier . --write",
|
|
16
|
+
"lint": "next lint --max-warnings=0",
|
|
17
|
+
"prepare": "husky"
|
|
18
|
+
},
|
|
19
|
+
"lint-staged": {
|
|
20
|
+
"*.{js,jsx,ts,tsx,md,html,css,json}": "prettier --write"
|
|
21
|
+
},
|
|
22
|
+
"dependencies": {
|
|
23
|
+
"clsx": "^2.1.1",
|
|
24
|
+
"lenis": "^1.1.1",
|
|
25
|
+
"next": "^15.3.4",
|
|
26
|
+
"next-themes": "^0.4.4",
|
|
27
|
+
"react": "19.0.0",
|
|
28
|
+
"react-dom": "19.0.0",
|
|
29
|
+
"sharp": "^0.33.5",
|
|
30
|
+
"tailwind-merge": "^2.3.0",
|
|
31
|
+
"tw-elements-react": "^1.0.0-alpha2"
|
|
32
|
+
},
|
|
33
|
+
"devDependencies": {
|
|
34
|
+
"@types/node": "^20",
|
|
35
|
+
"@types/react": "19.0.10",
|
|
36
|
+
"@types/react-dom": "19.0.4",
|
|
37
|
+
"eslint": "^8",
|
|
38
|
+
"eslint-config-next": "15.1.7",
|
|
39
|
+
"eslint-config-prettier": "^9.1.0",
|
|
40
|
+
"husky": "^9.0.11",
|
|
41
|
+
"lint-staged": "^15.2.2",
|
|
42
|
+
"only-allow": "^1.2.1",
|
|
43
|
+
"postcss": "^8",
|
|
44
|
+
"prettier": "3.2.5",
|
|
45
|
+
"tailwindcss": "^3.4.1",
|
|
46
|
+
"typescript": "^5",
|
|
47
|
+
"typescript-eslint": "^7.8.0"
|
|
48
|
+
},
|
|
49
|
+
"packageManager": "yarn@1.22.22"
|
|
50
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 394 80"><path fill="#000" d="M262 0h68.5v12.7h-27.2v66.6h-13.6V12.7H262V0ZM149 0v12.7H94v20.4h44.3v12.6H94v21h55v12.6H80.5V0h68.7zm34.3 0h-17.8l63.8 79.4h17.9l-32-39.7 32-39.6h-17.9l-23 28.6-23-28.6zm18.3 56.7-9-11-27.1 33.7h17.8l18.3-22.7z"/><path fill="#000" d="M81 79.3 17 0H0v79.3h13.6V17l50.2 62.3H81Zm252.6-.4c-1 0-1.8-.4-2.5-1s-1.1-1.6-1.1-2.6.3-1.8 1-2.5 1.6-1 2.6-1 1.8.3 2.5 1a3.4 3.4 0 0 1 .6 4.3 3.7 3.7 0 0 1-3 1.8zm23.2-33.5h6v23.3c0 2.1-.4 4-1.3 5.5a9.1 9.1 0 0 1-3.8 3.5c-1.6.8-3.5 1.3-5.7 1.3-2 0-3.7-.4-5.3-1s-2.8-1.8-3.7-3.2c-.9-1.3-1.4-3-1.4-5h6c.1.8.3 1.6.7 2.2s1 1.2 1.6 1.5c.7.4 1.5.5 2.4.5 1 0 1.8-.2 2.4-.6a4 4 0 0 0 1.6-1.8c.3-.8.5-1.8.5-3V45.5zm30.9 9.1a4.4 4.4 0 0 0-2-3.3 7.5 7.5 0 0 0-4.3-1.1c-1.3 0-2.4.2-3.3.5-.9.4-1.6 1-2 1.6a3.5 3.5 0 0 0-.3 4c.3.5.7.9 1.3 1.2l1.8 1 2 .5 3.2.8c1.3.3 2.5.7 3.7 1.2a13 13 0 0 1 3.2 1.8 8.1 8.1 0 0 1 3 6.5c0 2-.5 3.7-1.5 5.1a10 10 0 0 1-4.4 3.5c-1.8.8-4.1 1.2-6.8 1.2-2.6 0-4.9-.4-6.8-1.2-2-.8-3.4-2-4.5-3.5a10 10 0 0 1-1.7-5.6h6a5 5 0 0 0 3.5 4.6c1 .4 2.2.6 3.4.6 1.3 0 2.5-.2 3.5-.6 1-.4 1.8-1 2.4-1.7a4 4 0 0 0 .8-2.4c0-.9-.2-1.6-.7-2.2a11 11 0 0 0-2.1-1.4l-3.2-1-3.8-1c-2.8-.7-5-1.7-6.6-3.2a7.2 7.2 0 0 1-2.4-5.7 8 8 0 0 1 1.7-5 10 10 0 0 1 4.3-3.5c2-.8 4-1.2 6.4-1.2 2.3 0 4.4.4 6.2 1.2 1.8.8 3.2 2 4.3 3.4 1 1.4 1.5 3 1.5 5h-5.8z"/></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 283 64"><path fill="black" d="M141 16c-11 0-19 7-19 18s9 18 20 18c7 0 13-3 16-7l-7-5c-2 3-6 4-9 4-5 0-9-3-10-7h28v-3c0-11-8-18-19-18zm-9 15c1-4 4-7 9-7s8 3 9 7h-18zm117-15c-11 0-19 7-19 18s9 18 20 18c6 0 12-3 16-7l-8-5c-2 3-5 4-8 4-5 0-9-3-11-7h28l1-3c0-11-8-18-19-18zm-10 15c2-4 5-7 10-7s8 3 9 7h-19zm-39 3c0 6 4 10 10 10 4 0 7-2 9-5l8 5c-3 5-9 8-17 8-11 0-19-7-19-18s8-18 19-18c8 0 14 3 17 8l-8 5c-2-3-5-5-9-5-6 0-10 4-10 10zm83-29v46h-9V5h9zM37 0l37 64H0L37 0zm92 5-27 48L74 5h10l18 30 17-30h10zm59 12v10l-3-1c-6 0-10 4-10 10v15h-9V17h9v9c0-5 6-9 13-9z"/></svg>
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { cn } from '@/utils/class-merge';
|
|
4
|
+
import { TERipple } from 'tw-elements-react';
|
|
5
|
+
import type { IButtonProps } from './interface';
|
|
6
|
+
|
|
7
|
+
export default function Button({
|
|
8
|
+
children,
|
|
9
|
+
className,
|
|
10
|
+
size = 'md',
|
|
11
|
+
variant = 'primary',
|
|
12
|
+
disabled = false,
|
|
13
|
+
...rest
|
|
14
|
+
}: IButtonProps) {
|
|
15
|
+
return (
|
|
16
|
+
<TERipple>
|
|
17
|
+
<button
|
|
18
|
+
className={cn(
|
|
19
|
+
{
|
|
20
|
+
'py-3 px-5 text-lg': size === 'lg',
|
|
21
|
+
'py-2 px-4': size === 'md',
|
|
22
|
+
'py-1.5 px-3 text-sm': size === 'sm',
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
'bg-primary': variant === 'primary',
|
|
26
|
+
'bg-primary-light': variant === 'secondary',
|
|
27
|
+
'bg-transparent border': variant === 'transparent',
|
|
28
|
+
},
|
|
29
|
+
disabled ? 'disabled:cursor-not-allowed' : 'hover:shadow-md',
|
|
30
|
+
'flex items-center gap-2 rounded transition-all dark:bg-primary',
|
|
31
|
+
className
|
|
32
|
+
)}
|
|
33
|
+
disabled={disabled}
|
|
34
|
+
{...rest}
|
|
35
|
+
>
|
|
36
|
+
{children}
|
|
37
|
+
</button>
|
|
38
|
+
</TERipple>
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
Button.displayName = 'Button';
|