Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .envrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
use flake . --impure
1 change: 1 addition & 0 deletions apps/cli/src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -189,5 +189,6 @@ export const ADDON_COMPATIBILITY = {
fumadocs: [],
opentui: [],
wxt: [],
"nix-flake": [],
none: [],
} as const;
2 changes: 2 additions & 0 deletions apps/cli/src/helpers/core/template-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ export async function processAndCopyFiles(
relativeDestPath = path.join(path.dirname(relativeDestPath), ".gitignore");
} else if (basename === "_npmrc") {
relativeDestPath = path.join(path.dirname(relativeDestPath), ".npmrc");
} else if (basename === "_envrc") {
relativeDestPath = path.join(path.dirname(relativeDestPath), ".envrc");
}

const destPath = path.join(destDir, relativeDestPath);
Expand Down
6 changes: 5 additions & 1 deletion apps/cli/src/prompts/addons.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,10 @@ function getAddonDisplay(addon: Addons): { label: string; hint: string } {
label = "WXT";
hint = "Build browser extensions";
break;
case "nix-flake":
label = "Nix Flake";
hint = "Reproducible dev environment with Nix";
break;
default:
label = addon;
hint = `Add ${addon}`;
Expand All @@ -74,7 +78,7 @@ function getAddonDisplay(addon: Addons): { label: string; hint: string } {
const ADDON_GROUPS = {
Documentation: ["starlight", "fumadocs"],
Linting: ["biome", "oxlint", "ultracite"],
Other: ["ruler", "pwa", "tauri", "husky", "opentui", "wxt", "turborepo"],
Other: ["ruler", "pwa", "tauri", "husky", "opentui", "wxt", "turborepo", "nix-flake"],
};

export async function getAddonsChoice(addons?: Addons[], frontends?: Frontend[], auth?: Auth) {
Expand Down
2 changes: 2 additions & 0 deletions apps/cli/templates/addons/nix-flake/_envrc.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
use flake

77 changes: 77 additions & 0 deletions apps/cli/templates/addons/nix-flake/flake.nix.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
{
description = "{{projectName}} devshell";

inputs = {
nixpkgs = {
url = "github:NixOS/nixpkgs/nixos-unstable";
};
};

outputs = { self, nixpkgs }:
let
mkShellFor = system:
let
pkgs = nixpkgs.legacyPackages.${system};
in
pkgs.mkShell {
packages = [
# package manager
{{#if (eq packageManager "bun")}}
pkgs.bun
{{else}}
pkgs.nodejs_22
{{/if}}
{{#if (eq packageManager "pnpm")}}
pkgs.pnpm
{{/if}}

# backend runtime (if different from package manager)
{{#if (and (eq runtime "bun") (ne packageManager "bun"))}}
pkgs.bun
{{/if}}
{{#if (and (eq runtime "node") (eq packageManager "bun"))}}
pkgs.nodejs_22
{{/if}}
{{#if (eq runtime "workers")}}
pkgs.wrangler
{{/if}}

# database tooling
{{#if (eq dbSetup "docker")}}
pkgs.docker-compose
{{/if}}
{{#if (and (eq database "postgres") (eq dbSetup "docker"))}}
pkgs.postgresql
{{/if}}
{{#if (and (eq database "mysql") (eq dbSetup "docker"))}}
pkgs.mariadb
{{/if}}
{{#if (and (eq database "mongodb") (eq dbSetup "docker"))}}
pkgs.mongosh
{{/if}}
{{#if (eq dbSetup "turso")}}
pkgs.turso-cli
{{/if}}
{{#if (eq dbSetup "supabase")}}
pkgs.supabase-cli
{{/if}}
];

shellHook = ''
if [ -n "$PS1" ]; then
{{#if (eq packageManager "bun")}}
echo "bun: $(bun --version)"
{{else}}
echo "node: $(node --version)"
{{/if}}
fi
'';
};
in
{
devShells.x86_64-linux.default = mkShellFor "x86_64-linux";
devShells.aarch64-linux.default = mkShellFor "aarch64-linux";
devShells.x86_64-darwin.default = mkShellFor "x86_64-darwin";
devShells.aarch64-darwin.default = mkShellFor "aarch64-darwin";
};
}
3 changes: 2 additions & 1 deletion apps/cli/test/addons.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { expectError, expectSuccess, runTRPCTest, type TestConfig } from "./test

describe("Addon Configurations", () => {
describe("Universal Addons (no frontend restrictions)", () => {
const universalAddons = ["biome", "husky", "turborepo", "oxlint"];
const universalAddons = ["biome", "husky", "turborepo", "oxlint", "nix-flake"];

for (const addon of universalAddons) {
it(`should work with ${addon} addon on any frontend`, async () => {
Expand Down Expand Up @@ -288,6 +288,7 @@ describe("Addon Configurations", () => {
"husky",
"turborepo",
"oxlint",
"nix-flake",
// Note: starlight, ultracite, ruler, fumadocs are prompt-controlled only
];

Expand Down
1 change: 1 addition & 0 deletions apps/web/content/docs/cli/options.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,7 @@ Additional features to include:
- `ultracite`: Ultracite configuration
- `oxlint`: Oxlint + Oxfmt (linting & formatting)
- `ruler`: Centralize your AI rules with Ruler
- `nix-flake`: Reproducible dev environment with Nix

```bash
create-better-t-stack --addons pwa biome husky
Expand Down
2 changes: 1 addition & 1 deletion apps/web/content/docs/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -310,7 +310,7 @@ See the full list in the [CLI Reference](/docs/cli). Key flags:
- `--orm`: drizzle, prisma, mongoose, none
- `--api`: trpc, orpc, none
- `--auth`: better-auth, clerk, none
- `--addons`: turborepo, pwa, tauri, biome, husky, starlight, fumadocs, ultracite, oxlint, ruler, none
- `--addons`: turborepo, pwa, tauri, biome, husky, starlight, fumadocs, ultracite, oxlint, ruler, nix-flake, none
- `--examples`: todo, ai, none

## Next Steps
Expand Down
8 changes: 8 additions & 0 deletions apps/web/src/lib/constant.ts
Original file line number Diff line number Diff line change
Expand Up @@ -559,6 +559,14 @@ export const TECH_OPTIONS: Record<
color: "from-emerald-500 to-emerald-700",
default: false,
},
{
id: "nix-flake",
name: "Nix Flake",
description: "Reproducible dev environment with Nix",
icon: "",
color: "from-sky-500 to-sky-700",
default: false,
},
{
id: "turborepo",
name: "Turborepo",
Expand Down
27 changes: 27 additions & 0 deletions flake.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

37 changes: 37 additions & 0 deletions flake.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
{
description = "create-t-stack devshell flake";

inputs = {
nixpkgs = {
url = "github:NixOS/nixpkgs/nixos-25.11";
};
};

outputs = { self, nixpkgs }:
let
mkShellFor = system:
let
pkgs = nixpkgs.legacyPackages.${system};
in
pkgs.mkShell {
packages = [
pkgs.bun
pkgs.nodejs_22
];

shellHook = ''
if [ -n "$PS1" ]; then
echo "bun: $(bun --version)"
fi
'';
};
in
{
# explicit nested outputs per system
devShells.x86_64-linux.default = mkShellFor "x86_64-linux";
devShells.aarch64-linux.default = mkShellFor "aarch64-linux";
devShells.x86_64-darwin.default = mkShellFor "x86_64-darwin";
devShells.aarch64-darwin.default = mkShellFor "aarch64-darwin";
};
}

1 change: 1 addition & 0 deletions packages/types/src/schemas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ export const AddonsSchema = z
"oxlint",
"opentui",
"wxt",
"nix-flake",
"none",
])
.describe("Additional addons");
Expand Down