Skip to content

Commit 5162efe

Browse files
feat!: new folder structure (t3-oss#934)
1 parent 46fe155 commit 5162efe

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

71 files changed

+1339
-730
lines changed

.changeset/loud-shirts-tap.md

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
"create-t3-app": major
3+
---
4+
5+
feat!: implement new folder structure
6+
7+
create-t3-app has decided to switch out the folder structure of the generated t3-app to, what is to us, a more minimal, logical and easier to understand structure.

.eslintrc.cjs

+6-4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
module.exports = {
22
parser: "@typescript-eslint/parser", // Specifies the ESLint parser
3-
plugins: ["unicorn", "turbo"],
3+
plugins: ["turbo"],
44
extends: [
55
"plugin:@typescript-eslint/recommended", // Uses the recommended rules from the @typescript-eslint/eslint-plugin
66
"plugin:prettier/recommended",
@@ -16,12 +16,14 @@ module.exports = {
1616
"@typescript-eslint/explicit-module-boundary-types": "off",
1717
"@typescript-eslint/no-explicit-any": "off",
1818
"@typescript-eslint/no-floating-promises": "error",
19-
"unicorn/filename-case": [
19+
"prettier/prettier": ["error", { endOfLine: "auto" }],
20+
"@typescript-eslint/no-unused-vars": [
2021
"error",
2122
{
22-
case: "camelCase",
23+
argsIgnorePattern: "^_",
24+
varsIgnorePattern: "^_",
25+
caughtErrorsIgnorePattern: "^_",
2326
},
2427
],
25-
"prettier/prettier": ["error", { endOfLine: "auto" }],
2628
},
2729
};

cli/.prettierrc.cjs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,5 @@
22
module.exports = {
33
...require("../.prettierrc.cjs"),
44
plugins: [require.resolve("prettier-plugin-tailwindcss")],
5-
tailwindConfig: "./template/addons/tailwind/tailwind.config.cjs",
5+
tailwindConfig: "./template/extras/config/tailwind.config.cjs",
66
};

cli/package.json

+12
Original file line numberDiff line numberDiff line change
@@ -50,12 +50,24 @@
5050
"sort-package-json": "^2.0.0"
5151
},
5252
"devDependencies": {
53+
"@prisma/client": "^4.8.0",
54+
"@tanstack/react-query": "^4.20.4",
55+
"@trpc/client": "^10.7.0",
56+
"@trpc/next": "^10.7.0",
57+
"@trpc/react-query": "^10.7.0",
58+
"@trpc/server": "^10.7.0",
5359
"@types/fs-extra": "^9.0.13",
5460
"@types/gradient-string": "^1.1.2",
5561
"@types/inquirer": "^9.0.2",
5662
"@types/node": "^18.8.0",
63+
"next": "^13.1.1",
64+
"next-auth": "^4.18.7",
5765
"prettier": "^2.8.0",
5866
"prettier-plugin-tailwindcss": "^0.2.0",
67+
"prisma": "^4.8.0",
68+
"react": "18.2.0",
69+
"react-dom": "18.2.0",
70+
"superjson": "^1.12.1",
5971
"tsup": "^6.2.3",
6072
"type-fest": "^3.0.0",
6173
"typescript": "^4.9.3"

cli/src/helpers/selectBoilerplate.ts

+12-12
Original file line numberDiff line numberDiff line change
@@ -11,17 +11,17 @@ export const selectAppFile = ({
1111
projectDir,
1212
packages,
1313
}: SelectBoilerplateProps) => {
14-
const appFileDir = path.join(PKG_ROOT, "template/page-studs/_app");
14+
const appFileDir = path.join(PKG_ROOT, "template/extras/src/pages/_app");
1515

16-
const usingTrpc = packages.trpc.inUse;
16+
const usingTRPC = packages.trpc.inUse;
1717
const usingNextAuth = packages.nextAuth.inUse;
1818

1919
let appFile = "";
20-
if (usingNextAuth && usingTrpc) {
20+
if (usingNextAuth && usingTRPC) {
2121
appFile = "with-auth-trpc.tsx";
22-
} else if (usingNextAuth && !usingTrpc) {
22+
} else if (usingNextAuth && !usingTRPC) {
2323
appFile = "with-auth.tsx";
24-
} else if (!usingNextAuth && usingTrpc) {
24+
} else if (!usingNextAuth && usingTRPC) {
2525
appFile = "with-trpc.tsx";
2626
}
2727

@@ -37,22 +37,22 @@ export const selectIndexFile = ({
3737
projectDir,
3838
packages,
3939
}: SelectBoilerplateProps) => {
40-
const indexFileDir = path.join(PKG_ROOT, "template/page-studs/index");
40+
const indexFileDir = path.join(PKG_ROOT, "template/extras/src/pages/index");
4141

42-
const usingTrpc = packages.trpc.inUse;
42+
const usingTRPC = packages.trpc.inUse;
4343
const usingTw = packages.tailwind.inUse;
4444
const usingAuth = packages.nextAuth.inUse;
4545

4646
let indexFile = "";
47-
if (usingTrpc && usingTw && usingAuth) {
47+
if (usingTRPC && usingTw && usingAuth) {
4848
indexFile = "with-auth-trpc-tw.tsx";
49-
} else if (usingTrpc && !usingTw && usingAuth) {
49+
} else if (usingTRPC && !usingTw && usingAuth) {
5050
indexFile = "with-auth-trpc.tsx";
51-
} else if (usingTrpc && usingTw) {
51+
} else if (usingTRPC && usingTw) {
5252
indexFile = "with-trpc-tw.tsx";
53-
} else if (usingTrpc && !usingTw) {
53+
} else if (usingTRPC && !usingTw) {
5454
indexFile = "with-trpc.tsx";
55-
} else if (!usingTrpc && usingTw) {
55+
} else if (!usingTRPC && usingTw) {
5656
indexFile = "with-tw.tsx";
5757
}
5858

cli/src/installers/envVars.ts

+40-39
Original file line numberDiff line numberDiff line change
@@ -7,32 +7,46 @@ export const envVariablesInstaller: Installer = ({ projectDir, packages }) => {
77
const usingAuth = packages?.nextAuth.inUse;
88
const usingPrisma = packages?.prisma.inUse;
99

10-
const envAssetDir = path.join(PKG_ROOT, "template/addons/env");
10+
const envContent = getEnvContent(!!usingAuth, !!usingPrisma);
1111

12-
let envSchemaFile = "";
13-
let envContent =
14-
"# When adding additional env variables, the schema in /env/schema.mjs should be updated accordingly\n";
12+
const envSchemaFile =
13+
usingAuth && usingPrisma
14+
? "with-auth-prisma.mjs"
15+
: usingAuth
16+
? "with-auth.mjs"
17+
: usingPrisma
18+
? "with-prisma.mjs"
19+
: "";
1520

16-
switch (true) {
17-
case usingAuth && usingPrisma:
18-
envSchemaFile = "auth-prisma-schema.mjs";
19-
break;
20-
case usingAuth:
21-
envSchemaFile = "auth-schema.mjs";
22-
break;
23-
case usingPrisma:
24-
envSchemaFile = "prisma-schema.mjs";
25-
break;
21+
if (envSchemaFile !== "") {
22+
const envSchemaSrc = path.join(
23+
PKG_ROOT,
24+
"template/extras/src/env/schema",
25+
envSchemaFile,
26+
);
27+
const envSchemaDest = path.join(projectDir, "src/env/schema.mjs");
28+
fs.copySync(envSchemaSrc, envSchemaDest);
2629
}
2730

28-
if (usingPrisma) {
29-
envContent += `
31+
const envDest = path.join(projectDir, ".env");
32+
const envExampleDest = path.join(projectDir, ".env.example");
33+
34+
fs.writeFileSync(envDest, envContent, "utf-8");
35+
fs.writeFileSync(envExampleDest, exampleEnvContent + envContent, "utf-8");
36+
};
37+
38+
const getEnvContent = (usingAuth: boolean, usingPrisma: boolean) => {
39+
let content =
40+
"# When adding additional env variables, the schema in /env/schema.mjs should be updated accordingly";
41+
42+
if (usingPrisma)
43+
content += `
3044
# Prisma
3145
DATABASE_URL=file:./db.sqlite
3246
`;
33-
}
34-
if (usingAuth) {
35-
envContent += `
47+
48+
if (usingAuth)
49+
content += `
3650
# Next Auth
3751
# You can generate the secret via 'openssl rand -base64 32' on Linux
3852
# More info: https://next-auth.js.org/configuration/options#secret
@@ -43,34 +57,21 @@ NEXTAUTH_URL=http://localhost:3000
4357
DISCORD_CLIENT_ID=
4458
DISCORD_CLIENT_SECRET=
4559
`;
46-
}
4760

48-
if (!envSchemaFile) {
49-
envContent += `
61+
if (!usingAuth && !usingPrisma)
62+
content += `
5063
# Example:
5164
# SERVERVAR=foo
5265
# NEXT_PUBLIC_CLIENTVAR=bar
5366
`;
54-
}
5567

56-
const envExampleContent =
57-
`# Since .env is gitignored, you can use .env.example to build a new \`.env\` file when you clone the repo.
68+
return content;
69+
};
70+
71+
const exampleEnvContent = `# Since .env is gitignored, you can use .env.example to build a new \`.env\` file when you clone the repo.
5872
# Keep this file up-to-date when you add new variables to \`.env\`.
5973
6074
# This file will be committed to version control, so make sure not to have any secrets in it.
6175
# If you are cloning this repo, create a copy of this file named \`.env\` and populate it with your secrets.
6276
63-
` + envContent;
64-
65-
if (envSchemaFile) {
66-
const envSchemaSrc = path.join(envAssetDir, envSchemaFile);
67-
const envSchemaDest = path.join(projectDir, "src/env/schema.mjs");
68-
fs.copySync(envSchemaSrc, envSchemaDest);
69-
}
70-
71-
const envDest = path.join(projectDir, ".env");
72-
const envExampleDest = path.join(projectDir, ".env.example");
73-
74-
fs.writeFileSync(envDest, envContent, "utf-8");
75-
fs.writeFileSync(envExampleDest, envExampleContent, "utf-8");
76-
};
77+
`;

cli/src/installers/index.ts

+8-8
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,12 @@ export type AvailablePackages = typeof availablePackages[number];
2222
*/
2323
export const dependencyVersionMap = {
2424
// NextAuth.js
25-
"next-auth": "^4.18.3",
25+
"next-auth": "^4.18.7",
2626
"@next-auth/prisma-adapter": "^1.0.5",
2727

2828
// Prisma
29-
prisma: "^4.5.0",
30-
"@prisma/client": "^4.5.0",
29+
prisma: "^4.8.0",
30+
"@prisma/client": "^4.8.0",
3131

3232
// TailwindCSS
3333
tailwindcss: "^3.2.0",
@@ -38,11 +38,11 @@ export const dependencyVersionMap = {
3838
"@types/prettier": "^2.7.2",
3939

4040
// tRPC
41-
"@trpc/client": "^10.0.0",
42-
"@trpc/server": "^10.0.0",
43-
"@trpc/react-query": "^10.0.0",
44-
"@trpc/next": "^10.0.0",
45-
"@tanstack/react-query": "^4.16.0",
41+
"@trpc/client": "^10.7.0",
42+
"@trpc/server": "^10.7.0",
43+
"@trpc/react-query": "^10.7.0",
44+
"@trpc/next": "^10.7.0",
45+
"@tanstack/react-query": "^4.20.0",
4646
superjson: "1.9.1",
4747
} as const;
4848
export type AvailableDependencies = keyof typeof dependencyVersionMap;

cli/src/installers/nextAuth.ts

+9-24
Original file line numberDiff line numberDiff line change
@@ -14,40 +14,25 @@ export const nextAuthInstaller: Installer = ({ projectDir, packages }) => {
1414
devMode: false,
1515
});
1616

17-
const nextAuthAssetDir = path.join(PKG_ROOT, "template/addons/next-auth");
17+
const extrasDir = path.join(PKG_ROOT, "template/extras");
1818

1919
const apiHandlerSrc = path.join(
20-
nextAuthAssetDir,
21-
packages?.prisma.inUse ? "api-handler-prisma.ts" : "api-handler.ts",
20+
extrasDir,
21+
"src/pages/api/auth/[...nextauth]",
22+
packages?.prisma.inUse ? "with-prisma.ts" : "base.ts",
2223
);
2324
const apiHandlerDest = path.join(
2425
projectDir,
2526
"src/pages/api/auth/[...nextauth].ts",
2627
);
2728

28-
const getServerAuthSessionSrc = path.join(
29-
nextAuthAssetDir,
30-
"get-server-auth-session.ts",
31-
);
32-
const getServerAuthSessionDest = path.join(
33-
projectDir,
34-
"src/server/common/get-server-auth-session.ts",
35-
);
36-
37-
const restrictedApiSrc = path.join(nextAuthAssetDir, "restricted.ts");
38-
const restrictedApiDest = path.join(
39-
projectDir,
40-
"src/pages/api/restricted.ts",
41-
);
29+
const getServerAuthSessionSrc = path.join(extrasDir, "src/server/auth.ts");
30+
const getServerAuthSessionDest = path.join(projectDir, "src/server/auth.ts");
4231

43-
const nextAuthDefinitionSrc = path.join(nextAuthAssetDir, "next-auth.d.ts");
44-
const nextAuthDefinitionDest = path.join(
45-
projectDir,
46-
"src/types/next-auth.d.ts",
47-
);
32+
const nextAuthDTSSrc = path.join(extrasDir, "src/types/next-auth.d.ts");
33+
const nextAuthDTSDest = path.join(projectDir, "src/types/next-auth.d.ts");
4834

4935
fs.copySync(apiHandlerSrc, apiHandlerDest);
5036
fs.copySync(getServerAuthSessionSrc, getServerAuthSessionDest);
51-
fs.copySync(restrictedApiSrc, restrictedApiDest);
52-
fs.copySync(nextAuthDefinitionSrc, nextAuthDefinitionDest);
37+
fs.copySync(nextAuthDTSSrc, nextAuthDTSDest);
5338
};

cli/src/installers/prisma.ts

+6-9
Original file line numberDiff line numberDiff line change
@@ -17,19 +17,17 @@ export const prismaInstaller: Installer = ({ projectDir, packages }) => {
1717
devMode: false,
1818
});
1919

20-
const prismaAssetDir = path.join(PKG_ROOT, "template/addons/prisma");
20+
const extrasDir = path.join(PKG_ROOT, "template/extras");
2121

2222
const schemaSrc = path.join(
23-
prismaAssetDir,
24-
packages?.nextAuth.inUse ? "auth-schema.prisma" : "schema.prisma",
23+
extrasDir,
24+
"prisma/schema",
25+
packages?.nextAuth.inUse ? "with-auth.prisma" : "base.prisma",
2526
);
2627
const schemaDest = path.join(projectDir, "prisma/schema.prisma");
2728

28-
const clientSrc = path.join(prismaAssetDir, "client.ts");
29-
const clientDest = path.join(projectDir, "src/server/db/client.ts");
30-
31-
const sampleApiRouteSrc = path.join(prismaAssetDir, "sample-api.ts");
32-
const sampleApiRouteDest = path.join(projectDir, "src/pages/api/examples.ts");
29+
const clientSrc = path.join(extrasDir, "src/server/db.ts");
30+
const clientDest = path.join(projectDir, "src/server/db.ts");
3331

3432
// add postinstall script to package.json
3533
const packageJsonPath = path.join(projectDir, "package.json");
@@ -39,7 +37,6 @@ export const prismaInstaller: Installer = ({ projectDir, packages }) => {
3937

4038
fs.copySync(schemaSrc, schemaDest);
4139
fs.copySync(clientSrc, clientDest);
42-
fs.copySync(sampleApiRouteSrc, sampleApiRouteDest);
4340
fs.writeJSONSync(packageJsonPath, packageJsonContent, {
4441
spaces: 2,
4542
});

cli/src/installers/tailwind.ts

+9-8
Original file line numberDiff line numberDiff line change
@@ -18,25 +18,26 @@ export const tailwindInstaller: Installer = ({ projectDir }) => {
1818
devMode: true,
1919
});
2020

21-
const twAssetDir = path.join(PKG_ROOT, "template/addons/tailwind");
21+
const extrasDir = path.join(PKG_ROOT, "template/extras");
2222

23-
const twCfgSrc = path.join(twAssetDir, "tailwind.config.cjs");
23+
const twCfgSrc = path.join(extrasDir, "config/tailwind.config.cjs");
2424
const twCfgDest = path.join(projectDir, "tailwind.config.cjs");
2525

26-
const postcssCfgSrc = path.join(twAssetDir, "postcss.config.cjs");
26+
const postcssCfgSrc = path.join(extrasDir, "config/postcss.config.cjs");
2727
const postcssCfgDest = path.join(projectDir, "postcss.config.cjs");
2828

29-
const prettierSrc = path.join(twAssetDir, "prettier.config.cjs");
29+
const prettierSrc = path.join(extrasDir, "config/prettier.config.cjs");
3030
const prettierDest = path.join(projectDir, "prettier.config.cjs");
3131

32-
const cssSrc = path.join(twAssetDir, "globals.css");
32+
const cssSrc = path.join(extrasDir, "src/styles/globals.css");
3333
const cssDest = path.join(projectDir, "src/styles/globals.css");
3434

35-
const indexModuleCss = path.join(projectDir, "src/pages/index.module.css");
36-
3735
fs.copySync(twCfgSrc, twCfgDest);
3836
fs.copySync(postcssCfgSrc, postcssCfgDest);
3937
fs.copySync(cssSrc, cssDest);
40-
fs.unlinkSync(indexModuleCss);
4138
fs.copySync(prettierSrc, prettierDest);
39+
40+
// Remove vanilla css file
41+
const indexModuleCss = path.join(projectDir, "src/pages/index.module.css");
42+
fs.unlinkSync(indexModuleCss);
4243
};

0 commit comments

Comments
 (0)