Welcome to {{package-name}}
++ A minimal Next.js TypeScript template with App Router, powered by + Bun and Nix. +
+ + +diff --git a/.gitignore b/.gitignore index 248e5ac..350c6d5 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,12 @@ node_modules/ # Build output dist/ build/ +.next/ +out/ + +# TypeScript +*.tsbuildinfo +next-env.d.ts # Direnv .direnv/ diff --git a/README.md b/README.md index 9473058..f7d138e 100644 --- a/README.md +++ b/README.md @@ -1,29 +1,82 @@ -# JavaScript Template +# JavaScript Templates -A minimal JavaScript development template using Nix. Key features: +A family of minimal JavaScript development templates using Nix for reproducible +environments. Choose the right foundation for your project while maintaining +consistent tooling and workflows. -- Nix + Flakes for reproducible environments -- Bun (fast JavaScript runtime & package manager) -- Vite (development server & build tool) -- Node.js (mature REPL with custom helpers) -- ESLint + Prettier (linting & formatting) -- Devshell commands via just +## Available Templates -## Prerequisites +### Vanilla + +Minimal JavaScript template for interactive sites and applications. + +**Best for:** + +- Interactive tools and utilities +- Client-side games +- Dashboards and data visualizations +- Projects that don't need a framework + +**Tech stack:** + +- Vite (development server & bundler) +- Vanilla JavaScript (no framework) +- Node.js REPL with custom helpers + +### Next.js + +TypeScript template with App Router for modern web applications. + +**Best for:** + +- Full-stack applications (e-commerce, SaaS) +- Static sites with growth potential +- Projects needing API routes +- Server-side rendering or static generation + +**Tech stack:** + +- Next.js 15 with App Router +- React 19 +- TypeScript +- Optimized for Vercel deployment + +## Shared Foundation + +All templates include: + +- **Nix + Flakes** - reproducible development environments +- **Bun** - fast JavaScript runtime & package manager +- **ESLint + Prettier** - code quality and formatting +- **just** - consistent command-line interface +- **FHS compatibility** - toggle for NixOS edge cases + +## Getting Started + +### Prerequisites - [Nix](https://nixos.org/download.html) with flakes enabled - [direnv](https://direnv.net/) (optional but recommended) -## Getting Started +### Initialize a Project -Initialize a new project using [omnix](https://omnix.page): +Using [omnix](https://omnix.page): + +**Vanilla template:** ```sh nix run nixpkgs#omnix -- \ - init github:sajenim/javascript-template -o ./my-project + init github:sajenim/javascript-templates -o ./my-project ``` -Then enter the development environment: +**Next.js template:** + +```sh +nix run nixpkgs#omnix -- \ + init github:sajenim/javascript-templates#nextjs -o ./my-nextjs-app +``` + +### Enter Development Environment ```sh cd my-project @@ -31,37 +84,106 @@ direnv allow # Or use: nix develop just dev ``` -**NixOS users:** If bun-installed binaries fail to find system libraries, enable FHS compatibility: +### NixOS FHS Compatibility + +If bun-installed binaries fail to find system libraries, enable FHS +compatibility: ```nix # nix/modules/devshell.nix fhs = true; ``` -## Available Commands +## Common Commands -Run `just` to see all available commands: +Both templates share the same command interface: ```sh -just dev # Start dev server -just repl # Node.js REPL with helpers -just lint # Lint with ESLint -just format # Format with Prettier +just # List all available commands +just dev # Start development server just build # Production build +just lint # Lint code +just format # Format code just clean # Clean build artifacts -just update # Update flake inputs -just upgrade # Upgrade bun packages +just update # Update Nix flake inputs +just upgrade # Upgrade package dependencies ``` +### Template-Specific Commands + +**Vanilla:** + +```sh +just repl # Node.js REPL with custom helpers +just preview # Preview production build +``` + +**Next.js:** + +```sh +just start # Start production server +just typecheck # TypeScript type checking +just check # Run format-check, lint, and typecheck +``` + +## Next.js Static Export + +For pure static sites (no server-side features), enable static export: + +```js +// templates/nextjs/next.config.js +const nextConfig = { + output: 'export', + // ... +}; +``` + +Note: This disables API routes and server-side rendering. + ## Customization -This template provides minimal, sensible defaults. Customize as needed: +All templates provide minimal, sensible defaults. Customize as needed: + +**Vanilla:** - Modify linting rules in `eslint.config.js` +- Add custom REPL helpers in `.replrc.js` +- Extend Vite config if needed + +**Next.js:** + +- Configure Next.js in `next.config.js` +- Customize ESLint rules in `.eslintrc.json` +- Adjust TypeScript settings in `tsconfig.json` +- Extend ESLint config for stricter rules + +**Both templates:** + - Add Prettier config via `.prettierrc` if needed - Extend `Justfile` with project-specific commands -- Add custom REPL helpers in `.replrc.js` +- Adjust Nix devshell in `nix/modules/devshell.nix` + +## Template Comparison + +| Feature | Vanilla | Next.js | +| ------------------ | ------- | ------- | +| Framework | None | Next.js | +| Language | JS | TS | +| Bundler | Vite | Next.js | +| Client-side only | ✓ | ✗ | +| Server-side API | ✗ | ✓ | +| Static generation | ✓ | ✓ | +| Type checking | ✗ | ✓ | +| React components | ✗ | ✓ | +| File-based routing | ✗ | ✓ | ## Acknowledgments -- [srid's haskell-template](https://github.com/srid/haskell-template) +- [srid's haskell-template](https://github.com/srid/haskell-template) - + inspiration for Nix flakes structure +- [Next.js](https://nextjs.org/) - React framework for production +- [Bun](https://bun.sh/) - fast JavaScript runtime + +## License + +MIT diff --git a/flake.nix b/flake.nix index 2fa174a..3dde900 100644 --- a/flake.nix +++ b/flake.nix @@ -1,5 +1,5 @@ { - description = "Nix template for JavaScript projects, powered by Bun"; + description = "Nix templates for JavaScript projects, powered by Bun"; inputs = { nixpkgs.url = "github:nixos/nixpkgs/nixos-24.11"; diff --git a/nix/modules/devshell.nix b/nix/modules/devshell.nix index 6b88beb..ca858e0 100644 --- a/nix/modules/devshell.nix +++ b/nix/modules/devshell.nix @@ -22,6 +22,7 @@ in { [ bun nodejs + typescript eslint just prettierd diff --git a/nix/modules/template.nix b/nix/modules/template.nix index c936a64..ea22107 100644 --- a/nix/modules/template.nix +++ b/nix/modules/template.nix @@ -1,19 +1,41 @@ -{inputs, ...}: { +{inputs, ...}: let + root = inputs.self; +in { flake = rec { - templates.default = { - description = "A minimal JavaScript project template with Bun and Nix"; - path = inputs.self; + templates = { + default = { + description = "Minimal JavaScript template with Vite and Bun"; + path = "${root}/templates/vanilla"; + }; + + nextjs = { + description = "Next.js TypeScript template with App Router for Vercel"; + path = "${root}/templates/nextjs"; + }; }; - om.templates.javascript-template = { - template = templates.default; - params = [ - { - name = "package-name"; - description = "Name of the JavaScript package"; - placeholder = "javascript-template"; - } - ]; + om.templates = { + javascript-vanilla = { + template = templates.default; + params = [ + { + name = "package-name"; + description = "Name of the JavaScript package"; + placeholder = "my-project"; + } + ]; + }; + + javascript-nextjs = { + template = templates.nextjs; + params = [ + { + name = "package-name"; + description = "Name of the Next.js project"; + placeholder = "my-nextjs-app"; + } + ]; + }; }; }; } diff --git a/templates/nextjs/.eslintrc.json b/templates/nextjs/.eslintrc.json new file mode 100644 index 0000000..3722418 --- /dev/null +++ b/templates/nextjs/.eslintrc.json @@ -0,0 +1,3 @@ +{ + "extends": ["next/core-web-vitals", "next/typescript"] +} diff --git a/templates/nextjs/.prettierignore b/templates/nextjs/.prettierignore new file mode 100644 index 0000000..7fa5f54 --- /dev/null +++ b/templates/nextjs/.prettierignore @@ -0,0 +1,3 @@ +.next +node_modules +bun.lockb diff --git a/templates/nextjs/Justfile b/templates/nextjs/Justfile new file mode 100644 index 0000000..5f6022b --- /dev/null +++ b/templates/nextjs/Justfile @@ -0,0 +1,66 @@ +# List available commands +default: + @just --list + +# Start development server with hot reload +dev: + bun run dev + +# Add a package dependency +add package: + bun add {{package}} + +# Add a dev dependency +add-dev package: + bun add -d {{package}} + +# Remove a package dependency +remove package: + bun remove {{package}} + +# Build for production +build: + bun run build + +# Start production server +start: + bun run start + +# Install dependencies +install: + bun install + +# Update flake inputs +update: + nix flake update + +# Upgrade package dependencies +upgrade: + bun update + +# Clean build artifacts and dependencies +clean: + rm -rf .next node_modules bun.lockb + +# Format code with prettierd +format: + prettierd --write . + +# Check formatting without making changes +format-check: + prettierd --check . + +# Lint code with Next.js ESLint +lint: + bun run lint + +# Lint and auto-fix issues +lint-fix: + bun run lint -- --fix + +# Type check with TypeScript +typecheck: + tsc --noEmit + +# Check formatting, linting, and types +check: format-check lint typecheck diff --git a/templates/nextjs/app/globals.css b/templates/nextjs/app/globals.css new file mode 100644 index 0000000..362edd5 --- /dev/null +++ b/templates/nextjs/app/globals.css @@ -0,0 +1,64 @@ +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +body { + font-family: system-ui, -apple-system, sans-serif; + line-height: 1.6; + padding: 2rem; + background: #f5f5f5; + color: #333; +} + +main { + max-width: 800px; + margin: 0 auto; + padding: 2rem; + background: white; + border-radius: 8px; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); +} + +h1 { + margin-bottom: 1rem; + color: #2c3e50; +} + +p { + margin-bottom: 1.5rem; +} + +code { + padding: 0.2em 0.4em; + background: #f0f0f0; + border-radius: 3px; + font-family: 'Monaco', 'Courier New', monospace; + font-size: 0.9em; +} + +.container { + display: flex; + flex-direction: column; + gap: 1.5rem; +} + +.links { + display: flex; + gap: 1rem; + flex-wrap: wrap; +} + +.links a { + padding: 0.5rem 1rem; + background: #2c3e50; + color: white; + text-decoration: none; + border-radius: 4px; + transition: background 0.2s; +} + +.links a:hover { + background: #34495e; +} diff --git a/templates/nextjs/app/layout.tsx b/templates/nextjs/app/layout.tsx new file mode 100644 index 0000000..ec657b0 --- /dev/null +++ b/templates/nextjs/app/layout.tsx @@ -0,0 +1,19 @@ +import type { Metadata } from 'next'; +import './globals.css'; + +export const metadata: Metadata = { + title: '{{package-name}}', + description: 'A Next.js application built with Bun and Nix', +}; + +export default function RootLayout({ + children, +}: Readonly<{ + children: React.ReactNode; +}>) { + return ( + +
{children} + + ); +} diff --git a/templates/nextjs/app/page.tsx b/templates/nextjs/app/page.tsx new file mode 100644 index 0000000..77db059 --- /dev/null +++ b/templates/nextjs/app/page.tsx @@ -0,0 +1,37 @@ +export default function Home() { + return ( ++ A minimal Next.js TypeScript template with App Router, powered by + Bun and Nix. +
+ + +