Welcome to Next.js!
Get started by editing this page.
#!/usr/bin/env python3 """ Next.js Project Initialization Script Initialize new Next.js project with best practices, TypeScript, and optimized configuration. """ import argparse import json import os import subprocess import sys from pathlib import Path from typing import Optional class NextJSInitializer: """Initialize Next.js project with best practices.""" def __init__( self, name: str, directory: Optional[Path] = None, typescript: bool = True, app_router: bool = True, src_dir: bool = False, tailwind: bool = False, eslint: bool = True, import_alias: str = "@/*", ): """ Initialize NextJSInitializer. Args: name: Project name directory: Target directory (default: current directory / name) typescript: Enable TypeScript app_router: Use App Router (recommended) src_dir: Use src/ directory tailwind: Include Tailwind CSS eslint: Include ESLint import_alias: Import alias pattern """ self.name = name self.directory = directory or Path.cwd() / name self.typescript = typescript self.app_router = app_router self.src_dir = src_dir self.tailwind = tailwind self.eslint = eslint self.import_alias = import_alias def validate_name(self) -> None: """Validate project name.""" if not self.name: raise ValueError("Project name cannot be empty") if not self.name.replace("-", "").replace("_", "").isalnum(): raise ValueError( "Project name can only contain letters, numbers, hyphens, and underscores" ) if self.name[0].isdigit(): raise ValueError("Project name cannot start with a number") def check_directory(self) -> None: """Check if target directory exists.""" if self.directory.exists(): raise FileExistsError(f"Directory '{self.directory}' already exists") def create_directory_structure(self) -> None: """Create project directory structure.""" print(f"Creating directory structure in {self.directory}...") # Create base directories self.directory.mkdir(parents=True, exist_ok=True) # Determine app/pages directory location base_dir = self.directory / "src" if self.src_dir else self.directory if self.app_router: app_dir = base_dir / "app" app_dir.mkdir(parents=True, exist_ok=True) (app_dir / "favicon.ico").touch() self._create_app_router_files(app_dir) else: pages_dir = base_dir / "pages" pages_dir.mkdir(parents=True, exist_ok=True) self._create_pages_router_files(pages_dir) # Create additional directories (self.directory / "public").mkdir(exist_ok=True) (base_dir / "components").mkdir(parents=True, exist_ok=True) (base_dir / "lib").mkdir(parents=True, exist_ok=True) def _create_app_router_files(self, app_dir: Path) -> None: """Create App Router files.""" ext = "tsx" if self.typescript else "jsx" # Create layout layout_content = self._get_layout_content() (app_dir / f"layout.{ext}").write_text(layout_content) # Create page page_content = self._get_page_content() (app_dir / f"page.{ext}").write_text(page_content) # Create global styles if self.tailwind: globals_content = self._get_tailwind_globals() else: globals_content = self._get_basic_globals() (app_dir / "globals.css").write_text(globals_content) def _create_pages_router_files(self, pages_dir: Path) -> None: """Create Pages Router files.""" ext = "tsx" if self.typescript else "jsx" # Create _app app_content = self._get_app_content() (pages_dir / f"_app.{ext}").write_text(app_content) # Create index index_content = self._get_index_content() (pages_dir / f"index.{ext}").write_text(index_content) def create_config_files(self) -> None: """Create configuration files.""" print("Creating configuration files...") # package.json package_json = self._get_package_json() (self.directory / "package.json").write_text( json.dumps(package_json, indent=2) ) # next.config.js next_config = self._get_next_config() (self.directory / "next.config.js").write_text(next_config) # tsconfig.json if self.typescript: tsconfig = self._get_tsconfig() (self.directory / "tsconfig.json").write_text( json.dumps(tsconfig, indent=2) ) # .eslintrc.json if self.eslint: eslint_config = self._get_eslint_config() (self.directory / ".eslintrc.json").write_text( json.dumps(eslint_config, indent=2) ) # tailwind.config if self.tailwind: tailwind_config = self._get_tailwind_config() ext = "ts" if self.typescript else "js" (self.directory / f"tailwind.config.{ext}").write_text(tailwind_config) postcss_config = self._get_postcss_config() (self.directory / "postcss.config.js").write_text(postcss_config) # .gitignore gitignore = self._get_gitignore() (self.directory / ".gitignore").write_text(gitignore) # README.md readme = self._get_readme() (self.directory / "README.md").write_text(readme) def _get_package_json(self) -> dict: """Generate package.json content.""" dependencies = { "next": "latest", "react": "latest", "react-dom": "latest", } dev_dependencies = {} if self.typescript: dev_dependencies.update( { "typescript": "^5.0.0", "@types/node": "^20.0.0", "@types/react": "^18.0.0", "@types/react-dom": "^18.0.0", } ) if self.eslint: dev_dependencies["eslint"] = "^8.0.0" dev_dependencies["eslint-config-next"] = "latest" if self.tailwind: dependencies["tailwindcss"] = "^3.3.0" dependencies["autoprefixer"] = "^10.0.0" dependencies["postcss"] = "^8.0.0" return { "name": self.name, "version": "0.1.0", "private": True, "scripts": { "dev": "next dev", "build": "next build", "start": "next start", "lint": "next lint" if self.eslint else None, }, "dependencies": dependencies, "devDependencies": dev_dependencies, } def _get_layout_content(self) -> str: """Generate layout.tsx content.""" import_css = ( "import './globals.css'\n" if not self.tailwind else "import './globals.css'\n" ) if self.typescript: return f"""{import_css} export const metadata = {{ title: '{self.name}', description: 'Generated by Next.js', }} export default function RootLayout({{ children, }}: {{ children: React.ReactNode }}) {{ return (
{{children}} ) }} """ return f"""{import_css} export const metadata = {{ title: '{self.name}', description: 'Generated by Next.js', }} export default function RootLayout({{ children }}) {{ return ( {{children}} ) }} """ def _get_page_content(self) -> str: """Generate page.tsx content.""" return """export default function Home() { return (Get started by editing this page.
Get started by editing this page.