UNPKG

@consensys/create-web3-template

Version:

This is a CLI tool that scaffolds Next.js and React projects with a focus on Web3 development.

201 lines (181 loc) 5.65 kB
import path from "path"; import { promises as fs } from "fs"; import { NPM_COMMAND, PNPM_COMMAND, YARN_COMMAND } from "../constants/index.js"; import { createWagmiConfigFile, execAsync, updatePackageJsonDependencies, } from "./index.js"; export const createReactApp = async ( options: ProjectOptions, projectPath: string = "" ): Promise<void> => { console.log("Creating React project..."); const { projectName, packageManager } = options; const commands: Record< string, (projectName: string, path: string) => string > = { npm: NPM_COMMAND, yarn: YARN_COMMAND, pnpm: PNPM_COMMAND, }; const command = commands[packageManager]; if (!command) { console.error(`Unsupported package manager: ${packageManager}`); return; } try { await execAsync(command(projectName, projectPath)); console.log("React project created successfully!"); await updatePackageJsonDependencies( { "@consensys/connect-button": "^1.0.3", "@tanstack/react-query": "^5.51.23", viem: "2.x", wagmi: "^2.12.5", postcss: "^8.4.41", tailwindcss: "^3.4.10", autoprefixer: "^10.4.20", }, projectPath ? projectPath : projectName ); await createWagmiConfigFile(projectPath ? projectPath : projectName); await updateMainFile(projectPath ? projectPath : projectName); await updateAppFile(projectPath ? projectPath : projectName); await createClientProvider(projectPath ? projectPath : projectName); await createTalwindConfig(projectPath ? projectPath : projectName); await updateIndexCss(projectPath ? projectPath : projectName); } catch (error) { console.error("An error occurred during project creation:", error); } }; const updateMainFile = async (projectPath: string) => { const mainFilePath = path.join(projectPath, "src", "main.tsx"); await fs.writeFile( mainFilePath, ` import React from "react"; import ReactDOM from "react-dom/client"; import App from "./App.tsx"; import "./index.css"; import { WagmiProvider } from "wagmi"; import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; import { config } from "../wagmi.config.ts"; const queryClient = new QueryClient(); ReactDOM.createRoot(document.getElementById("root")!).render( <React.StrictMode> <WagmiProvider config={config}> <QueryClientProvider client={queryClient}> <App /> </QueryClientProvider> </WagmiProvider> </React.StrictMode> ); ` ); }; const updateAppFile = async (projectPath: string) => { const appFilePath = path.join(projectPath, "src", "App.tsx"); await fs.writeFile( appFilePath, ` import { client } from "./providers/client"; import { useEffect, useState } from "react"; import { useAccount } from "wagmi"; import { ConnectButton } from "@consensys/connect-button"; export default function Home() { const { isConnected, address } = useAccount(); const [blockNumber, setBlockNumber] = useState<bigint | null>(null); useEffect(() => { client.getBlockNumber().then((block) => { setBlockNumber(block); }); }, []); return ( <main className="relative flex flex-col items-center gap-20 min-h-screen mx-auto md:p-24"> <div className="flex justify-center pt-10 md:pt-0 z-10 max-w-5xl w-full lg:items-center lg:justify-between font-mono text-sm lg:flex"> <div className="absolute bottom-0 left-0 flex w-full items-end justify-center lg:static lg:h-auto lg:w-auto lg:bg-none"> <a className="pointer-events-none flex place-items-center gap-2 p-8 lg:pointer-events-auto lg:p-0" href="#" target="_blank" rel="noopener noreferrer" > By RAD Team </a> </div> <ConnectButton /> </div> <div className="flex mt-52 flex-col items-center"> <span className="text-3xl font-bold">Web3 Starter template</span> {isConnected && ( <span className="text-sm font-mono font-medium max-w-md text-center text-gray-500"> Connected to: {address} </span> )} <div className="text-sm font-mono font-medium max-w-md text-center text-gray-500"> {!blockNumber ? ( "Loading block number..." ) : ( <div>Linea block number: {Number(blockNumber)}</div> )} </div> </div> </main> ); } ` ); }; const createClientProvider = async (projectPath: string) => { await fs.mkdir(path.join(projectPath, "src", "providers")); const clientFilePath = path.join( projectPath, "src", "providers", "client.ts" ); await fs.writeFile( clientFilePath, ` import { createPublicClient, http } from "viem"; import { linea } from "viem/chains"; export const client = createPublicClient({ chain: linea, transport: http(), }); ` ); }; const createTalwindConfig = async (projectPath: string) => { const tailwindConfigPath = path.join(projectPath, "tailwind.config.js"); await execAsync(`cd ${projectPath} && npx tailwindcss init -p`); await fs.writeFile( tailwindConfigPath, ` /** @type {import('tailwindcss').Config} */ export default { content: [ "./index.html", "./src/**/*.{js,ts,jsx,tsx}", ], theme: { extend: {}, }, plugins: [], } ` ); }; const updateIndexCss = async (projectPath: string) => { const indexCssPath = path.join(projectPath, "src", "index.css"); await fs.writeFile( indexCssPath, ` @tailwind base; @tailwind components; @tailwind utilities; ` ); };