Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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
4 changes: 2 additions & 2 deletions apps/cli/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ Options:
--orm <type> ORM type (none, drizzle, prisma, mongoose)
--auth Include authentication
--no-auth Exclude authentication
--frontend <types...> Frontend types (tanstack-router, react-router, tanstack-start, next, nuxt, svelte, solid, native-nativewind, native-unistyles, none)
--frontend <types...> Frontend types (tanstack-router, react-router, tanstack-start, next, nuxt, svelte, solid, native-bare, native-uniwind, native-unistyles, none)
--addons <types...> Additional addons (pwa, tauri, starlight, biome, husky, turborepo, fumadocs, ultracite, oxlint, none)
--examples <types...> Examples to include (todo, ai, none)
--git Initialize git repository
Expand Down Expand Up @@ -119,7 +119,7 @@ npx create-better-t-stack my-app --backend elysia --runtime node
Create a project with multiple frontend options (one web + one native):

```bash
npx create-better-t-stack my-app --frontend tanstack-router native-nativewind
npx create-better-t-stack my-app --frontend tanstack-router native-bare
```

Create a project with examples:
Expand Down
3 changes: 2 additions & 1 deletion apps/cli/src/helpers/addons/examples-setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,8 @@ export async function setupExamples(config: ProjectConfig) {
frontend.includes("tanstack-start");
const hasNext = frontend.includes("next");
const hasReactNative =
frontend.includes("native-nativewind") ||
frontend.includes("native-bare") ||
frontend.includes("native-uniwind") ||
frontend.includes("native-unistyles");

if (webClientDirExists) {
Expand Down
3 changes: 2 additions & 1 deletion apps/cli/src/helpers/addons/ultracite-setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,8 @@ function getFrameworksFromFrontend(frontend: string[]): string[] {
"tanstack-start": "react",
next: "next",
nuxt: "vue",
"native-nativewind": "react",
"native-bare": "react",
"native-uniwind": "react",
"native-unistyles": "react",
svelte: "svelte",
solid: "solid",
Expand Down
11 changes: 7 additions & 4 deletions apps/cli/src/helpers/core/api-setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ function getFrontendType(frontend: Frontend[]): {
"tanstack-start",
"next",
];
const nativeFrontends = ["native-nativewind", "native-unistyles"];
const nativeFrontends = ["native-bare", "native-uniwind", "native-unistyles"];

return {
hasReactWeb: frontend.some((f) => reactBasedFrontends.includes(f)),
Expand Down Expand Up @@ -149,7 +149,8 @@ function getQueryDependencies(frontend: Frontend[]) {
"tanstack-router",
"tanstack-start",
"next",
"native-nativewind",
"native-bare",
"native-uniwind",
"native-unistyles",
];

Expand All @@ -162,12 +163,14 @@ function getQueryDependencies(frontend: Frontend[]) {
if (needsReactQuery) {
const hasReactWeb = frontend.some(
(f) =>
f !== "native-nativewind" &&
f !== "native-bare" &&
f !== "native-uniwind" &&
f !== "native-unistyles" &&
reactBasedFrontends.includes(f),
);
const hasNative =
frontend.includes("native-nativewind") ||
frontend.includes("native-bare") ||
frontend.includes("native-uniwind") ||
frontend.includes("native-unistyles");

if (hasReactWeb) {
Expand Down
16 changes: 10 additions & 6 deletions apps/cli/src/helpers/core/auth-setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,8 @@ export async function setupAuth(config: ProjectConfig) {
const convexBackendDirExists = await fs.pathExists(convexBackendDir);

const hasNativeForBA =
frontend.includes("native-nativewind") ||
frontend.includes("native-bare") ||
frontend.includes("native-uniwind") ||
frontend.includes("native-unistyles");

if (convexBackendDirExists) {
Expand Down Expand Up @@ -98,9 +99,10 @@ export async function setupAuth(config: ProjectConfig) {
}
}

const hasNativeWind = frontend.includes("native-nativewind");
const hasNativeBare = frontend.includes("native-bare");
const hasNativeUniwind = frontend.includes("native-uniwind");
const hasUnistyles = frontend.includes("native-unistyles");
if (nativeDirExists && (hasNativeWind || hasUnistyles)) {
if (nativeDirExists && (hasNativeBare || hasNativeUniwind || hasUnistyles)) {
await addPackageDependency({
dependencies: [
"better-auth",
Expand All @@ -116,12 +118,13 @@ export async function setupAuth(config: ProjectConfig) {
}
}

const hasNativeWind = frontend.includes("native-nativewind");
const hasNativeBare = frontend.includes("native-bare");
const hasNativeUniwind = frontend.includes("native-uniwind");
const hasUnistyles = frontend.includes("native-unistyles");
if (
auth === "clerk" &&
nativeDirExists &&
(hasNativeWind || hasUnistyles)
(hasNativeBare || hasNativeUniwind || hasUnistyles)
) {
await addPackageDependency({
dependencies: ["@clerk/clerk-expo"],
Expand Down Expand Up @@ -163,7 +166,8 @@ export async function setupAuth(config: ProjectConfig) {
}

if (
(frontend.includes("native-nativewind") ||
(frontend.includes("native-bare") ||
frontend.includes("native-uniwind") ||
frontend.includes("native-unistyles")) &&
nativeDirExists
) {
Expand Down
9 changes: 6 additions & 3 deletions apps/cli/src/helpers/core/create-readme.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@ function generateReadmeContent(options: ProjectConfig) {
const isConvex = backend === "convex";
const hasReactRouter = frontend.includes("react-router");
const hasNative =
frontend.includes("native-nativewind") ||
frontend.includes("native-bare") ||
frontend.includes("native-uniwind") ||
frontend.includes("native-unistyles");
const hasSvelte = frontend.includes("svelte");

Expand Down Expand Up @@ -321,7 +322,8 @@ function generateProjectStructure(
}

const hasNative =
frontend.includes("native-nativewind") ||
frontend.includes("native-bare") ||
frontend.includes("native-uniwind") ||
frontend.includes("native-unistyles");
if (hasNative) {
if (isBackendSelf) {
Expand Down Expand Up @@ -402,7 +404,8 @@ function generateFeaturesList(
const hasTanstackRouter = frontend.includes("tanstack-router");
const hasReactRouter = frontend.includes("react-router");
const hasNative =
frontend.includes("native-nativewind") ||
frontend.includes("native-bare") ||
frontend.includes("native-uniwind") ||
frontend.includes("native-unistyles");
const hasNext = frontend.includes("next");
const hasTanstackStart = frontend.includes("tanstack-start");
Expand Down
6 changes: 4 additions & 2 deletions apps/cli/src/helpers/core/env-setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,8 @@ export async function setupEnvironmentVariables(config: ProjectConfig) {
}

if (
frontend.includes("native-nativewind") ||
frontend.includes("native-bare") ||
frontend.includes("native-uniwind") ||
frontend.includes("native-unistyles")
) {
const nativeDir = path.join(projectDir, "apps/native");
Expand Down Expand Up @@ -277,7 +278,8 @@ export async function setupEnvironmentVariables(config: ProjectConfig) {
const envLocalPath = path.join(convexBackendDir, ".env.local");

const hasNative =
frontend.includes("native-nativewind") ||
frontend.includes("native-bare") ||
frontend.includes("native-uniwind") ||
frontend.includes("native-unistyles");
const hasWeb = hasWebFrontend;

Expand Down
6 changes: 4 additions & 2 deletions apps/cli/src/helpers/core/post-installation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,8 @@ export async function displayPostInstallInstructions(
? getLintingInstructions(runCmd)
: "";
const nativeInstructions =
frontend?.includes("native-nativewind") ||
frontend?.includes("native-bare") ||
frontend?.includes("native-uniwind") ||
frontend?.includes("native-unistyles")
? getNativeInstructions(isConvex, isBackendSelf, frontend || [])
: "";
Expand Down Expand Up @@ -103,7 +104,8 @@ export async function displayPostInstallInstructions(
].includes(f),
);
const hasNative =
frontend?.includes("native-nativewind") ||
frontend?.includes("native-bare") ||
frontend?.includes("native-uniwind") ||
frontend?.includes("native-unistyles");

const bunWebNativeWarning =
Expand Down
48 changes: 29 additions & 19 deletions apps/cli/src/helpers/core/template-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,9 +69,10 @@ export async function setupFrontendTemplates(
const hasNuxtWeb = context.frontend.includes("nuxt");
const hasSvelteWeb = context.frontend.includes("svelte");
const hasSolidWeb = context.frontend.includes("solid");
const hasNativeWind = context.frontend.includes("native-nativewind");
const hasNativeBare = context.frontend.includes("native-bare");
const hasNativeUniwind = context.frontend.includes("native-uniwind");
const hasUnistyles = context.frontend.includes("native-unistyles");
const _hasNative = hasNativeWind || hasUnistyles;
const _hasNative = hasNativeBare || hasNativeUniwind || hasUnistyles;
const isConvex = context.backend === "convex";

if (hasReactWeb || hasNuxtWeb || hasSvelteWeb || hasSolidWeb) {
Expand Down Expand Up @@ -201,7 +202,7 @@ export async function setupFrontendTemplates(
}
}

if (hasNativeWind || hasUnistyles) {
if (hasNativeBare || hasNativeUniwind || hasUnistyles) {
const nativeAppDir = path.join(projectDir, "apps/native");
await fs.ensureDir(nativeAppDir);

Expand All @@ -220,8 +221,10 @@ export async function setupFrontendTemplates(
}

let nativeFrameworkPath = "";
if (hasNativeWind) {
nativeFrameworkPath = "nativewind";
if (hasNativeBare) {
nativeFrameworkPath = "bare";
} else if (hasNativeUniwind) {
nativeFrameworkPath = "uniwind";
} else if (hasUnistyles) {
nativeFrameworkPath = "unistyles";
}
Expand Down Expand Up @@ -382,9 +385,10 @@ export async function setupAuthTemplate(
const hasNuxtWeb = context.frontend.includes("nuxt");
const hasSvelteWeb = context.frontend.includes("svelte");
const hasSolidWeb = context.frontend.includes("solid");
const hasNativeWind = context.frontend.includes("native-nativewind");
const hasNativeBare = context.frontend.includes("native-bare");
const hasUniwind = context.frontend.includes("native-uniwind");
const hasUnistyles = context.frontend.includes("native-unistyles");
const hasNative = hasNativeWind || hasUnistyles;
const hasNative = hasNativeBare || hasUniwind || hasUnistyles;

const authProvider = context.auth;

Expand Down Expand Up @@ -440,10 +444,9 @@ export async function setupAuthTemplate(
);
}

const hasNativeWind = context.frontend.includes("native-nativewind");
const hasUnistyles = context.frontend.includes("native-unistyles");
let nativeFrameworkPath = "";
if (hasNativeWind) nativeFrameworkPath = "nativewind";
if (hasNativeBare) nativeFrameworkPath = "bare";
else if (hasUniwind) nativeFrameworkPath = "uniwind";
else if (hasUnistyles) nativeFrameworkPath = "unistyles";
if (nativeFrameworkPath) {
const convexClerkNativeFrameworkSrc = path.join(
Expand Down Expand Up @@ -529,7 +532,8 @@ export async function setupAuthTemplate(
}

let nativeFrameworkPath = "";
if (hasNativeWind) nativeFrameworkPath = "nativewind";
if (hasNativeBare) nativeFrameworkPath = "bare";
else if (hasUniwind) nativeFrameworkPath = "uniwind";
else if (hasUnistyles) nativeFrameworkPath = "unistyles";
if (nativeFrameworkPath) {
const convexBetterAuthNativeFrameworkSrc = path.join(
Expand Down Expand Up @@ -690,8 +694,10 @@ export async function setupAuthTemplate(
}

let nativeFrameworkAuthPath = "";
if (hasNativeWind) {
nativeFrameworkAuthPath = "nativewind";
if (hasNativeBare) {
nativeFrameworkAuthPath = "bare";
} else if (hasUniwind) {
nativeFrameworkAuthPath = "uniwind";
} else if (hasUnistyles) {
nativeFrameworkAuthPath = "unistyles";
}
Expand Down Expand Up @@ -1034,13 +1040,16 @@ export async function setupExamplesTemplate(
}

if (nativeAppDirExists) {
const hasNativeWind = context.frontend.includes("native-nativewind");
const hasNativeBare = context.frontend.includes("native-bare");
const hasUniwind = context.frontend.includes("native-uniwind");
const hasUnistyles = context.frontend.includes("native-unistyles");

if (hasNativeWind || hasUnistyles) {
if (hasNativeBare || hasUniwind || hasUnistyles) {
let nativeFramework = "";
if (hasNativeWind) {
nativeFramework = "nativewind";
if (hasNativeBare) {
nativeFramework = "bare";
} else if (hasUniwind) {
nativeFramework = "uniwind";
} else if (hasUnistyles) {
nativeFramework = "unistyles";
}
Expand All @@ -1065,9 +1074,10 @@ export async function setupExamplesTemplate(

export async function handleExtras(projectDir: string, context: ProjectConfig) {
const extrasDir = path.join(PKG_ROOT, "templates/extras");
const hasNativeWind = context.frontend.includes("native-nativewind");
const hasNativeBare = context.frontend.includes("native-bare");
const hasUniwind = context.frontend.includes("native-uniwind");
const hasUnistyles = context.frontend.includes("native-unistyles");
const hasNative = hasNativeWind || hasUnistyles;
const hasNative = hasNativeBare || hasUniwind || hasUnistyles;

if (context.packageManager === "pnpm") {
const pnpmWorkspaceSrc = path.join(extrasDir, "pnpm-workspace.yaml");
Expand Down
6 changes: 4 additions & 2 deletions apps/cli/src/prompts/auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ export async function getAuthChoice(
"tanstack-router",
"tanstack-start",
"next",
"native-nativewind",
"native-bare",
"native-uniwind",
"native-unistyles",
].includes(f),
);
Expand All @@ -29,7 +30,8 @@ export async function getAuthChoice(
"tanstack-router",
"tanstack-start",
"next",
"native-nativewind",
"native-bare",
"native-uniwind",
"native-unistyles",
].includes(f),
);
Expand Down
11 changes: 8 additions & 3 deletions apps/cli/src/prompts/frontend.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,8 +92,13 @@ export async function getFrontendChoice(
message: "Choose native",
options: [
{
value: "native-nativewind" as const,
label: "NativeWind",
value: "native-bare" as const,
label: "Bare",
hint: "Bare Expo without styling library",
},
{
value: "native-uniwind" as const,
label: "UniWind",
hint: "Use Tailwind CSS for React Native",
},
{
Expand All @@ -102,7 +107,7 @@ export async function getFrontendChoice(
hint: "Consistent styling for React Native",
},
],
initialValue: "native-nativewind",
initialValue: "native-bare",
});

if (isCancel(nativeFramework)) return exitCancelled("Operation cancelled");
Expand Down
3 changes: 2 additions & 1 deletion apps/cli/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ export const FrontendSchema = z
"tanstack-start",
"next",
"nuxt",
"native-nativewind",
"native-bare",
"native-uniwind",
"native-unistyles",
"svelte",
"solid",
Expand Down
3 changes: 2 additions & 1 deletion apps/cli/src/utils/better-auth-plugin-setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ export async function setupBetterAuthPlugins(
}

if (
config.frontend?.includes("native-nativewind") ||
config.frontend?.includes("native-bare") ||
config.frontend?.includes("native-uniwind") ||
config.frontend?.includes("native-unistyles")
) {
pluginsToAdd.push("expo()");
Expand Down
Loading