#!/usr/bin/env python3 """ Fullstack Project Scaffolder Generates project structure and boilerplate for various fullstack architectures. Supports Next.js, FastAPI+React, MERN, Django+React, and more. Usage: python project_scaffolder.py nextjs my-app python project_scaffolder.py fastapi-react my-api --with-docker python project_scaffolder.py mern my-project --with-auth python project_scaffolder.py --list-templates """ import argparse import json import os import sys from pathlib import Path from typing import Dict, List, Optional # Project templates with file structures TEMPLATES = { "nextjs": { "name": "Next.js Full Stack", "description": "Next.js 14+ with App Router, TypeScript, Tailwind CSS", "structure": { "src/app": ["layout.tsx", "page.tsx", "globals.css", "api/health/route.ts"], "src/components/ui": ["Button.tsx", "Card.tsx", "Input.tsx"], "src/components/layout": ["Header.tsx", "Footer.tsx"], "src/lib": ["utils.ts", "db.ts"], "src/types": ["index.ts"], "public": [], "": ["package.json", "tsconfig.json", "tailwind.config.ts", "next.config.js", ".env.example", ".gitignore", "README.md"] } }, "fastapi-react": { "name": "FastAPI + React", "description": "FastAPI backend with React frontend, PostgreSQL", "structure": { "backend/app": ["__init__.py", "main.py", "config.py", "database.py"], "backend/app/api": ["__init__.py", "routes.py", "deps.py"], "backend/app/models": ["__init__.py", "user.py"], "backend/app/schemas": ["__init__.py", "user.py"], "backend": ["requirements.txt", "alembic.ini", "Dockerfile"], "frontend/src": ["App.tsx", "main.tsx", "index.css"], "frontend/src/components": ["Layout.tsx"], "frontend/src/hooks": ["useApi.ts"], "frontend": ["package.json", "tsconfig.json", "vite.config.ts", "Dockerfile"], "": ["docker-compose.yml", ".env.example", ".gitignore", "README.md"] } }, "mern": { "name": "MERN Stack", "description": "MongoDB, Express, React, Node.js with TypeScript", "structure": { "server/src": ["index.ts", "config.ts", "database.ts"], "server/src/routes": ["index.ts", "users.ts"], "server/src/models": ["User.ts"], "server/src/middleware": ["auth.ts", "error.ts"], "server": ["package.json", "tsconfig.json", "Dockerfile"], "client/src": ["App.tsx", "main.tsx"], "client/src/components": ["Layout.tsx"], "client/src/services": ["api.ts"], "client": ["package.json", "tsconfig.json", "vite.config.ts", "Dockerfile"], "": ["docker-compose.yml", ".env.example", ".gitignore", "README.md"] } }, "django-react": { "name": "Django + React", "description": "Django REST Framework backend with React frontend", "structure": { "backend/config": ["__init__.py", "settings.py", "urls.py", "wsgi.py"], "backend/apps/users": ["__init__.py", "models.py", "serializers.py", "views.py", "urls.py"], "backend": ["manage.py", "requirements.txt", "Dockerfile"], "frontend/src": ["App.tsx", "main.tsx"], "frontend/src/components": ["Layout.tsx"], "frontend": ["package.json", "tsconfig.json", "vite.config.ts", "Dockerfile"], "": ["docker-compose.yml", ".env.example", ".gitignore", "README.md"] } } } def get_file_content(template: str, filepath: str, project_name: str) -> str: """Generate file content based on template and file type.""" filename = Path(filepath).name contents = { # Next.js files "layout.tsx": f'''import type {{ Metadata }} from "next"; import "./globals.css"; export const metadata: Metadata = {{ title: "{project_name}", description: "Generated by project scaffolder", }}; export default function RootLayout({{ children, }}: {{ children: React.ReactNode; }}) {{ return ( {{children}} ); }} ''', "page.tsx": f'''export default function Home() {{ return (

{project_name}

Welcome to your new project.

); }} ''', "globals.css": '''@tailwind base; @tailwind components; @tailwind utilities; ''', "route.ts": '''import { NextResponse } from "next/server"; export async function GET() { return NextResponse.json({ status: "healthy", timestamp: new Date().toISOString(), }); } ''', "Button.tsx": '''import { ButtonHTMLAttributes, forwardRef } from "react"; interface ButtonProps extends ButtonHTMLAttributes { variant?: "primary" | "secondary" | "outline"; size?: "sm" | "md" | "lg"; } export const Button = forwardRef( ({ className = "", variant = "primary", size = "md", ...props }, ref) => { const base = "font-medium rounded-lg transition-colors"; const variants = { primary: "bg-blue-600 text-white hover:bg-blue-700", secondary: "bg-gray-200 text-gray-900 hover:bg-gray-300", outline: "border border-gray-300 hover:bg-gray-50", }; const sizes = { sm: "px-3 py-1.5 text-sm", md: "px-4 py-2", lg: "px-6 py-3 text-lg" }; return