├── .github └── workflows │ └── publish.yaml ├── .gitignore ├── LICENSE ├── README.md ├── bin └── create-t3svelte-app.js ├── overwrites ├── mongodb │ └── prisma │ │ └── schema.prisma ├── mysql │ └── prisma │ │ └── schema.prisma └── postgres │ └── prisma │ └── schema.prisma ├── package.json ├── src ├── cli.js └── main.js └── templates ├── +eslint_javascript ├── .eslintignore ├── .eslintrc.cjs └── package.txt ├── +eslint_prettier_javascript ├── .eslintignore ├── .eslintrc.cjs ├── .prettierignore ├── .prettierrc └── package.txt ├── +eslint_prettier_typescript ├── .eslintignore ├── .eslintrc.cjs ├── .prettierignore ├── .prettierrc └── package.txt ├── +eslint_typescript ├── .eslintignore ├── .eslintrc.cjs └── package.txt ├── +headlessui └── package.txt ├── +heroicons └── package.txt ├── +prettier ├── .prettierignore ├── .prettierrc └── package.txt ├── +prisma ├── package.txt ├── prisma │ └── schema.prisma └── src │ └── lib │ └── server │ └── prismaClient.ts ├── +prisma_trpc ├── package.txt ├── prisma │ └── schema.prisma └── src │ ├── hooks.server.ts │ └── lib │ ├── client │ └── trpc.ts │ └── server │ ├── prismaClient.ts │ └── trpcServer.ts ├── +tailwind ├── package.txt ├── postcss.config.cjs ├── src │ ├── app.css │ └── routes │ │ └── +layout.svelte ├── svelte.config.js └── tailwind.config.cjs ├── +tailwind_prettier_plugin └── package.txt ├── +trpc ├── package.txt └── src │ ├── hooks.server.ts │ └── lib │ ├── client │ └── trpc.ts │ └── server │ └── trpcServer.ts ├── base_javascript ├── .gitignore ├── .npmrc ├── README.md ├── jsconfig.json ├── package.json ├── src │ ├── app.d.ts │ ├── app.html │ └── routes │ │ └── +page.svelte ├── static │ └── favicon.png ├── svelte.config.js └── vite.config.js ├── base_typescript ├── .gitignore ├── .npmrc ├── README.md ├── package.json ├── src │ ├── app.d.ts │ ├── app.html │ └── routes │ │ └── +page.svelte ├── static │ └── favicon.png ├── svelte.config.js ├── tsconfig.json └── vite.config.ts └── standard ├── .eslintignore ├── .eslintrc.cjs ├── .gitignore ├── .npmrc ├── .prettierignore ├── .prettierrc ├── README.md ├── package.json ├── postcss.config.cjs ├── prisma └── schema.prisma ├── src ├── app.css ├── app.d.ts ├── app.html ├── hooks.server.ts ├── lib │ ├── client │ │ └── trpc.ts │ └── server │ │ ├── prismaClient.ts │ │ └── trpcServer.ts └── routes │ ├── +layout.svelte │ └── +page.svelte ├── static └── favicon.png ├── svelte.config.js ├── tailwind.config.cjs ├── tsconfig.json └── vite.config.ts /.github/workflows/publish.yaml: -------------------------------------------------------------------------------- 1 | name: "🚀 publish" 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | 8 | jobs: 9 | release: 10 | name: 🚀 publish 11 | runs-on: ubuntu-latest 12 | steps: 13 | - name: 📚 checkout 14 | uses: actions/checkout@v3 15 | - name: 🟢 node 16 | uses: actions/setup-node@v3 17 | with: 18 | node-version: 18 19 | registry-url: https://registry.npmjs.org 20 | - name: 🚀 publish 21 | run: npm publish --access public 22 | env: 23 | NODE_AUTH_TOKEN: ${{secrets.NPM_AUTH_TOKEN}} -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | package-lock.json 3 | .DS_Store 4 | *.log -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 zach-hopkins 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | T3-SvelteKit 3 |

*Looking for Maintainers! Message me...*

4 |

5 | 6 |

create-t3svelte-app

7 | 8 |

9 | 10 | 11 | NPM version 12 | 13 | 14 | License 15 | 16 | 17 | Stars 18 | 19 | 20 | Downloads 21 | 22 |

23 | 24 |

25 |
26 | Just Build 27 |
28 | npx create-t3svelte-app 29 |
30 |

31 | 32 | ## Outline 33 | 34 | * [Get Building](#get-building) 35 | * [npm](#npm) 36 | * [yarn](#yarn) 37 | * [Prisma Requirements](#prisma-requirements) 38 | * [Available Templates](#available-templates) 39 | * [Standard](#standard-recommended) 40 | * [Custom (Modular)](#custom-modular-build) 41 | * [Contributing](#contributing) 42 | * [Caveats & Addendums](#caveats--addendums) 43 | * [Server-Side Rendering](#server-side-rendering) 44 | * [Vercel's Edge Cache for Serverless Functions](#vercels-edge-cache-for-serverless-functions) 45 | * [Shoutouts](#shoutouts) 46 | * [License](#license) 47 | 48 | ## Get Building 49 |

create-t3svelte-app is completely modular. Choose the components you need!

50 | 51 | ✅ Elegant full-stack framework powered by [SvelteKit](https://kit.svelte.dev/) 52 | ✅ Static typing support with [TypeScript](https://typescriptlang.org) 53 | ✅ End-to-end typesafe APIs with [tRPC](https://trpc.io) 54 | ✅ Enjoyable database interaction with [Prisma](https://www.prisma.io/) 55 | ✅ Efficient styling with [Tailwind CSS](https://tailwindcss.com/) 56 | 57 | ### npm 58 | 59 | ```bash 60 | npx create-t3svelte-app@latest 61 | ``` 62 | 63 | ### yarn 64 | 65 | ```bash 66 | yarn create t3svelte-app 67 | ``` 68 | 69 | ### Prisma Requirements 70 | 71 | If you choose not to init DB on first build, you can initialize prisma db at any time by editing the `DATABASE_URL` in `.env` and then running `npx prisma db pull` and `npx prisma generate`. You can read more about Prisma on their [docs](https://www.prisma.io/docs/reference/api-reference/command-reference). 72 | 73 | ## Available Templates 74 | 75 | A simple CLI with highly opinionated, out-of-the-box ready SvelteKit/tRPC/Prisma/Tailwind application. CLI options include 'Standard' and 'Custom' (modular build). Just run and start building. 76 | 77 | ### Standard (Recommended) 78 | 79 | - [**SvelteKit**](https://kit.svelte.dev/) 80 | - [**TypeScript**](https://www.typescriptlang.org/) 81 | - [**tRPC**](https://trpc.io/) - preconfigured with example API call in `+page.svelte` 82 | - [**Tailwind CSS**](https://tailwindcss.com/) - preconfigured with eslint/prettier & 'tailwind prettier plugin' integration 83 | - [**Prisma ORM**](https://www.prisma.io/) - CLI option to initialize DB on run - no need to run `prisma db pull` or `prisma db generate` 84 | 85 | ### Custom (Modular Build) 86 | 87 | #### Tech Stack Options: 88 | 89 | - SvelteKit 90 | - TypeScript || JavaScript 91 | - tRPC 92 | - Tailwind CSS 93 | - Prisma ORM 94 | 95 | #### Tool Options: 96 | 97 | - [ESLint](https://eslint.org/) 98 | - [Prettier](https://prettier.io/) 99 | - [Tailwind Prettier Plugin](https://github.com/tailwindlabs/prettier-plugin-tailwindcss) 100 | - [Prisma ORM](https://www.prisma.io/) 101 | - [Svelte Headless UI](https://github.com/rgossiaux/svelte-headlessui) 102 | - [Svelte HeroIcons](https://github.com/JustinVoitel/svelte-hero-icons) 103 | 104 | #### Config Options: 105 | 106 | - Git Init 107 | - DB Auto Configure w/ Prisma (Postgresql, MySQL, MongoDB, SQLite) 108 | - Auto Dependency Install 109 | 110 | ## Contributing 111 | 112 | See a bug? Want to help? Easiest way is to clone the main repo and run `npm link` in the cloned directory. You can code and then run `create-t3svelte-app` in any directory. 113 | 114 | ```bash 115 | git clone https://github.com/zach-hopkins/create-t3svelte-app 116 | cd create-t3svelte-app 117 | npm i 118 | npm link 119 | mkdir test-project 120 | cd test-project 121 | create-t3svelte-app 122 | ``` 123 | 124 | Run `npm unlink create-t3svelte-app` to undo. 125 | 126 | ## Caveats & Addendums 127 | 128 | ### Server-Side Rendering 129 | 130 | If you need to use the tRPC client in SvelteKit's [`load()`](https://kit.svelte.dev/docs/load) function for SSR, make sure to initialize it like so: 131 | 132 | ```ts 133 | // $lib/trpcClient.ts 134 | 135 | import { browser } from '$app/env'; 136 | import type { Router } from '$lib/trpcServer'; 137 | import * as trpc from '@trpc/client'; 138 | import type { LoadEvent } from "@sveltejs/kit"; 139 | 140 | const url = browser ? '/trpc' : 'http://localhost:3000/trpc'; 141 | export default (loadFetch?: LoadEvent['fetch']) => 142 | trpc.createTRPCClient({ 143 | url: loadFetch ? '/trpc' : url, 144 | transformer: trpcTransformer, 145 | ...(loadFetch && { fetch: loadFetch as typeof fetch }) 146 | }); 147 | 148 | ``` 149 | 150 | Then use it like so: 151 | 152 | ```ts 153 | // src/routes/+authors.svelte 154 | 155 | import trpcClient from '$lib/trpcClient'; 156 | import type { Load } from '@sveltejs/kit'; 157 | 158 | export const load: Load = async ({ fetch }) => { // 👈 make sure to pass in this fetch, not the global fetch 159 | const authors = await trpcClient(fetch).query('authors:browse', { 160 | genre: 'fantasy', 161 | }); 162 | return { props: { authors } }; 163 | }; 164 | ``` 165 | 166 | ### Vercel's Edge Cache for Serverless Functions 167 | 168 | Your server responses must [satisfy some criteria](https://vercel.com/docs/concepts/functions/edge-caching) in order for them to be cached on Vercel's Edge Network. tRPC's `responseMeta()` comes in handy here since you can initialize your handle in [`src/hooks.server.ts`](https://kit.svelte.dev/docs/hooks#server-hooks) like so: 169 | 170 | ```ts 171 | // src/hooks.server.ts 172 | 173 | import { router } from '$lib/trpcServer'; 174 | import { createTRPCHandle } from 'trpc-sveltekit'; 175 | 176 | export const handle = async ({ event, resolve }) => { 177 | const response = await createTRPCHandle({ 178 | url: '/trpc', 179 | event, 180 | resolve, 181 | responseMeta({ type, errors }) { 182 | if (type === 'query' && errors.length === 0) { 183 | const ONE_DAY_IN_SECONDS = 60 * 60 * 24; 184 | return { 185 | headers: { 186 | 'cache-control': `s-maxage=1, stale-while-revalidate=${ONE_DAY_IN_SECONDS}` 187 | } 188 | }; 189 | } 190 | return {}; 191 | } 192 | }); 193 | 194 | return response; 195 | }; 196 | ``` 197 | 198 | ## Shoutouts 199 | 200 | - [Theo @ T3](https://t3.gg/) for T3 Stack inspiration! 201 | - [Nexxel](https://github.com/nexxeln) for the OG create-t3-app! 202 | - [Ionut-Cristian Florescu](https://github.com/icflorescu/trpc-sveltekit) for his wonderful work on SvelteKit + tRPC & SSR Info! 203 | - [Ryan Gossiaux](https://github.com/rgossiaux) for enabling TailwindUI & HeadlessUI on Svelte! 204 | 205 | ## License 206 | 207 | [MIT](/LICENSE) 208 | 209 | -------------------------------------------------------------------------------- /bin/create-t3svelte-app.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | import cli from '../src/cli.js' 3 | cli(process.argv); -------------------------------------------------------------------------------- /overwrites/mongodb/prisma/schema.prisma: -------------------------------------------------------------------------------- 1 | generator client { 2 | provider = "prisma-client-js" 3 | } 4 | 5 | datasource db { 6 | provider = "mongodb" 7 | url = env("DATABASE_URL") 8 | } 9 | 10 | model User { 11 | id String @id @default(auto()) @map("_id") @db.ObjectId 12 | email String @unique 13 | name String? 14 | } -------------------------------------------------------------------------------- /overwrites/mysql/prisma/schema.prisma: -------------------------------------------------------------------------------- 1 | generator client { 2 | provider = "prisma-client-js" 3 | } 4 | 5 | datasource db { 6 | provider = "mysql" 7 | url = env("DATABASE_URL") 8 | } 9 | 10 | model User { 11 | id Int @id @default(autoincrement()) 12 | email String @unique 13 | name String? 14 | } -------------------------------------------------------------------------------- /overwrites/postgres/prisma/schema.prisma: -------------------------------------------------------------------------------- 1 | generator client { 2 | provider = "prisma-client-js" 3 | } 4 | 5 | datasource db { 6 | provider = "postgresql" 7 | url = env("DATABASE_URL") 8 | } 9 | 10 | model User { 11 | id Int @id @default(autoincrement()) 12 | email String @unique 13 | name String? 14 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "create-t3svelte-app", 3 | "version": "1.1.3", 4 | "description": "Rapidly setup T3 Stack with SvelteKit", 5 | "exports": "./index.js", 6 | "bin": { 7 | "create-t3svelte-app": "bin/create-t3svelte-app.js" 8 | }, 9 | "publishConfig": { 10 | "access": "public" 11 | }, 12 | "type": "module", 13 | "scripts": { 14 | "test": "echo \"Error: no test specified\" && exit 1" 15 | }, 16 | "keywords": [ 17 | "cli", 18 | "create-t3svelte-app" 19 | ], 20 | "author": "Zach Hopkins", 21 | "license": "MIT", 22 | "dependencies": { 23 | "arg": "^5.0.2", 24 | "chalk": "^5.0.1", 25 | "execa": "^6.1.0", 26 | "fs-extra": "^10.1.0", 27 | "inquirer": "^9.1.1", 28 | "listr": "^0.14.3", 29 | "pkg-install": "^1.0.0" 30 | }, 31 | "devDependencies": { 32 | "prettier": "^2.7.1" 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/cli.js: -------------------------------------------------------------------------------- 1 | import arg from 'arg' 2 | import inquirer from 'inquirer' 3 | import { createT3SvelteApp } from './main.js' 4 | 5 | function parseArgumentsIntoOptions(rawArgs) { 6 | const args = arg( 7 | { 8 | '--yes': Boolean, 9 | }, 10 | { 11 | argv: rawArgs.slice(2), 12 | } 13 | ) 14 | return { 15 | skipPrompts: args['--yes'] || false, 16 | template: args._[0], 17 | } 18 | } 19 | 20 | async function promptForMissingOptions(options) { 21 | const defaultTemplate = 'Standard' 22 | if (options.skipPrompts) { 23 | return { 24 | ...options, 25 | template: options.template || defaultTemplate, 26 | } 27 | } 28 | 29 | const baseQuestion = [] 30 | if (!options.template) { 31 | baseQuestion.push({ 32 | type: 'list', 33 | name: 'template', 34 | message: 'Please choose which project template to use', 35 | choices: ['Standard', 'Custom: TypeScript', 'Custom: JavaScript'], 36 | default: defaultTemplate, 37 | }) 38 | } 39 | 40 | const typeScriptQuestions = [] 41 | 42 | typeScriptQuestions.push({ 43 | type: 'checkbox', 44 | name: 'options', 45 | message: 'Please choose tech stack options', 46 | choices: [ 47 | { name: 'tRPC', checked: true }, 48 | { name: 'Prisma ORM', checked: true }, 49 | { name: 'Tailwind CSS', checked: true }, 50 | ], 51 | }) 52 | 53 | const javaScriptQuestions = [] 54 | 55 | javaScriptQuestions.push({ 56 | type: 'checkbox', 57 | name: 'options', 58 | message: 'Please choose tech stack options', 59 | choices: [ 60 | { name: 'Prisma ORM', checked: true }, 61 | { name: 'Tailwind CSS', checked: true }, 62 | ], 63 | }) 64 | 65 | let toolQuestions = [] 66 | 67 | toolQuestions.push({ 68 | type: 'checkbox', 69 | name: 'options', 70 | message: 'Please choose tech stack options', 71 | choices: [ 72 | { name: 'ESLint', checked: true }, 73 | { name: 'Prettier', checked: true }, 74 | { name: 'Tailwind Prettier', checked: true }, 75 | { name: 'Headless UI' }, 76 | { name: 'HeroIcons' }, 77 | ], 78 | }) 79 | 80 | const configQuestions = [] 81 | const configQuestionsNoPrisma = [] 82 | 83 | configQuestions.push({ 84 | type: 'checkbox', 85 | name: 'options', 86 | message: 'Please choose config options', 87 | choices: [ 88 | { name: 'Configure database', checked: true }, 89 | { name: 'Init .git', checked: true }, 90 | { name: 'Auto install dependencies', checked: true }, 91 | ], 92 | }) 93 | 94 | configQuestionsNoPrisma.push({ 95 | type: 'checkbox', 96 | name: 'options', 97 | message: 'Please choose config options', 98 | choices: [ 99 | { name: 'Init .git', checked: true }, 100 | { name: 'Auto install dependencies', checked: true }, 101 | ], 102 | }) 103 | 104 | //Inquirer Fork 2 (if needed) 105 | const dbSolutions = [] 106 | 107 | dbSolutions.push({ 108 | type: 'list', 109 | name: 'dbSolution', 110 | message: 'What DB technology are you using? (first 3 require URI string)', 111 | choices: ['Postgres', 'MySQL', 'MongoDB', 'SQLite', 'Other'], 112 | default: 'Postgres', 113 | }) 114 | 115 | //Inquirer Fork 3 (if needed) 116 | const dbQuestions = [] 117 | 118 | dbQuestions.push({ 119 | type: 'password', 120 | name: 'dbString', 121 | mask: true, 122 | message: 'Enter Full DB URI String', 123 | }) 124 | 125 | dbQuestions.push({ 126 | type: 'list', 127 | name: 'dbOperation', 128 | message: 'Init new DB schema (blank DB) or import schema from existing DB?', 129 | choices: ['New Schema', 'Import Existing Schema'], 130 | default: 'New Schema', 131 | }) 132 | 133 | /* */ 134 | /* Process Forks and Prompt Questions */ 135 | 136 | const baseTemplate = await inquirer.prompt(baseQuestion) //get base template 137 | let techOptions = [] 138 | let toolOptions = [] 139 | let requireURI = false 140 | let isStandard = false 141 | 142 | switch (baseTemplate.template) { 143 | case 'Custom: TypeScript': 144 | techOptions = (await inquirer.prompt(typeScriptQuestions)).options 145 | techOptions.push('TypeScript') 146 | break 147 | case 'Custom: JavaScript': 148 | techOptions = (await inquirer.prompt(javaScriptQuestions)).options 149 | techOptions.push('JavaScript') 150 | break 151 | default: //standard 152 | techOptions = ['tRPC', 'Prisma ORM', 'Tailwind CSS', 'TypeScript'] 153 | isStandard = true 154 | } 155 | 156 | if (!isStandard) { 157 | if (techOptions.includes('Tailwind CSS')) 158 | toolOptions = (await inquirer.prompt(toolQuestions)).options 159 | //remove tailwind prettier from options 160 | else { 161 | const tailwindPrettierIndex = toolQuestions[0].choices 162 | .map((object) => object.name) 163 | .indexOf('Tailwind Prettier') 164 | toolQuestions[0].choices = [ 165 | ...toolQuestions[0].choices.slice(0, tailwindPrettierIndex), 166 | ...toolQuestions[0].choices.slice(tailwindPrettierIndex + 1), 167 | ] 168 | toolOptions = (await inquirer.prompt(toolQuestions)).options 169 | } 170 | } else { 171 | //if Standard 172 | toolOptions = ['ESLint', 'Prettier', 'Tailwind Prettier'] 173 | } 174 | 175 | if (techOptions.includes('Prisma ORM')) 176 | var configOptions = (await inquirer.prompt(configQuestions)).options 177 | else var configOptions = (await inquirer.prompt(configQuestionsNoPrisma)).options 178 | 179 | const needsDatabase = configOptions.includes('Configure database') ? true : false 180 | if (needsDatabase) var dbSolutionAnswers = await inquirer.prompt(dbSolutions) 181 | 182 | if (dbSolutionAnswers) 183 | requireURI = 184 | dbSolutionAnswers.dbSolution == 'Postgres' || 185 | dbSolutionAnswers.dbSolution == 'MySQL' || 186 | dbSolutionAnswers.dbSolution == 'MongoDB' 187 | ? true 188 | : false 189 | 190 | if (needsDatabase && requireURI) var dbAnswers = await inquirer.prompt(dbQuestions) 191 | //Handle Empty Options 192 | else { 193 | var dbAnswers = { 194 | dbString: 'none', 195 | dbOperation: 'New Schema', 196 | } 197 | } 198 | if (!dbSolutionAnswers) var dbSolutionAnswers = { dbSolution: 'none' } 199 | 200 | //Manage Options 201 | const template = baseTemplate.template 202 | 203 | //Tech Stack 204 | const trpc = techOptions.includes('tRPC') 205 | const prisma = techOptions.includes('Prisma ORM') 206 | const scriptLang = techOptions.includes('TypeScript') ? 'TypeScript' : 'JavaScript' 207 | const tailwind = techOptions.includes('Tailwind CSS') 208 | 209 | //Tooling 210 | const eslint = toolOptions.includes('ESLint') 211 | const prettier = toolOptions.includes('Prettier') 212 | const tailwindPrettier = toolOptions.includes('Tailwind Prettier') && prettier ? true : false 213 | const headlessUI = toolOptions.includes('Headless UI') 214 | const heroIcons = toolOptions.includes('HeroIcons') 215 | 216 | //Configs 217 | const git = configOptions.includes('Init .git') 218 | const runInstall = configOptions.includes('Auto install dependencies') 219 | const db = configOptions.includes('Configure database') 220 | 221 | return { 222 | ...options, 223 | template: options.template || template, 224 | 225 | //Tech Stack 226 | scriptLang: scriptLang, 227 | optionals: { 228 | trpc: trpc, 229 | prisma: prisma, 230 | tailwind: tailwind, 231 | 232 | //Tooling 233 | eslint: eslint, 234 | prettier: prettier, 235 | tailwindPrettier: tailwindPrettier, 236 | headlessUI: headlessUI, 237 | heroIcons: heroIcons, 238 | }, 239 | //Configs 240 | git: git, 241 | runInstall: runInstall, 242 | db: db, 243 | 244 | //DB Specific 245 | dbString: dbAnswers.dbString, 246 | dbOperation: dbAnswers.dbOperation, 247 | dbSolution: dbSolutionAnswers.dbSolution, 248 | } 249 | } 250 | 251 | export default async function cli(args) { 252 | let options = parseArgumentsIntoOptions(args) 253 | options = await promptForMissingOptions(options) 254 | await createT3SvelteApp(options) 255 | } 256 | -------------------------------------------------------------------------------- /src/main.js: -------------------------------------------------------------------------------- 1 | import chalk from 'chalk' 2 | import fs from 'fs-extra' 3 | import path from 'path' 4 | import { promisify } from 'util' 5 | import { execa } from 'execa' 6 | import { fileURLToPath } from 'url' 7 | import Listr from 'listr' 8 | import { projectInstall } from 'pkg-install' 9 | import { exec } from 'child_process' 10 | 11 | const __filename = fileURLToPath(import.meta.url) 12 | const access = promisify(fs.access) 13 | 14 | // CREDIT: https://github.com/t3-oss/create-t3-app/blob/44a107b8d5345023bafc8a773322e5ee39ba8580/cli/src/utils/getUserPkgManager.ts 15 | function getUserPkgManager() { 16 | // This environment variable is set by npm and yarn but pnpm seems less consistent 17 | const userAgent = process.env.npm_config_user_agent; 18 | 19 | if (userAgent) { 20 | if (userAgent.startsWith("yarn")) { 21 | return "yarn"; 22 | } else if (userAgent.startsWith("pnpm")) { 23 | return "pnpm"; 24 | } else { 25 | return "npm"; 26 | } 27 | } else { 28 | // If no user agent is set, assume npm 29 | return "npm"; 30 | } 31 | }; 32 | 33 | const userPkgManager = getUserPkgManager() 34 | console.log('Using: %s ', chalk.green.bold(userPkgManager)) 35 | 36 | async function copyTemplateFiles(options, templateName = 'overwrites', templateBaseDir = '/') { 37 | await fs.copy(options.templateDirectory, options.targetDirectory) 38 | await fs.writeFile(options.targetDirectory + "/.npmrc", "engine-strict=true") 39 | await fs.writeFile(options.targetDirectory + "/.gitignore", ".DS_Store\nnode_modules\n/build\n/.svelte-kit\n/package\n.env") 40 | if (templateName != 'standard' && templateName != 'overwrites') await copyOptionalFiles(options, templateBaseDir) 41 | return 42 | } 43 | 44 | async function copyOptionalFiles(options, templateBaseDir) { 45 | let dirArray = [] 46 | let selectedOptionals = [] 47 | const scriptLang = options.scriptLang.toLowerCase() 48 | 49 | for (const [key, value] of Object.entries(options.optionals)) { 50 | if (value === true) selectedOptionals.push(key) 51 | } 52 | 53 | /* set dirs for optional additions */ 54 | 55 | //Tech Stack 56 | if (selectedOptionals.includes('prisma') && selectedOptionals.includes('trpc')) 57 | dirArray.push(templateBaseDir + '+prisma_trpc') 58 | else if (selectedOptionals.includes('trpc')) dirArray.push(templateBaseDir + '+trpc') 59 | else if (selectedOptionals.includes('prisma')) dirArray.push(templateBaseDir + '+prisma') 60 | 61 | if (selectedOptionals.includes('tailwind')) dirArray.push(templateBaseDir + '+tailwind') 62 | 63 | //Tooling 64 | if (selectedOptionals.includes('eslint') && selectedOptionals.includes('prettier')) { 65 | if (scriptLang == 'typescript') dirArray.push(templateBaseDir + '+eslint_prettier_typescript') 66 | else dirArray.push(templateBaseDir + '+eslint_prettier_javascript') 67 | } else if (selectedOptionals.includes('eslint')) { 68 | if (scriptLang == 'typescript') dirArray.push(templateBaseDir + '+eslint_typescript') 69 | else dirArray.push(templateBaseDir + '+eslint_javascript') 70 | } else if (selectedOptionals.includes('prettier')) dirArray.push(templateBaseDir + '+prettier') 71 | 72 | if (selectedOptionals.includes('heroIcons')) dirArray.push(templateBaseDir + '+heroicons') 73 | 74 | if (selectedOptionals.includes('headlessUI')) dirArray.push(templateBaseDir + '+headlessui') 75 | 76 | if (selectedOptionals.includes('tailwindPrettier')) 77 | dirArray.push(templateBaseDir + '+tailwind_prettier_plugin') 78 | 79 | const npmCommands = await compileInstalls(dirArray) 80 | 81 | for (let urlIndex in dirArray) { 82 | fs.copySync(dirArray[urlIndex], options.targetDirectory) 83 | } 84 | 85 | for (let commandIndex in npmCommands) { 86 | await new Promise(function(resolve, reject) { 87 | exec(npmCommands[commandIndex], (err, stdout, stderr) => { 88 | if (err) { 89 | reject(err) 90 | } else { 91 | resolve({ stdout, stderr }) 92 | } 93 | }) 94 | }) 95 | } 96 | 97 | //cleanup package.txt 98 | fs.removeSync(options.targetDirectory + '/package.txt') 99 | 100 | return 101 | } 102 | 103 | async function compileInstalls(dirArray) { 104 | //read package.txt for each optional package to configure package.json 105 | let npmCommands = [] 106 | for (let urlIndex in dirArray) { 107 | let lines = fs.readFileSync(dirArray[urlIndex] + '/package.txt', 'utf8').replace('\n', '') 108 | if (userPkgManager === 'pnpm') { 109 | lines = lines 110 | .replace(/npm/g, 'pnpm') 111 | .replace(/--no-package-lock /g, '') 112 | .replace(/--package-lock-only/g, '--lockfile-only') 113 | } else if (userPkgManager === 'yarn') { 114 | lines = lines 115 | .replace(/npm install/g, 'yarn add') 116 | .replace(/--no-package-lock /g, '') 117 | .replace(/--package-lock-only/g, '--mode update-lockfile') 118 | } 119 | npmCommands.push(lines) 120 | } 121 | return npmCommands 122 | } 123 | 124 | async function configureDatabase(options) { 125 | await copyEnvFile(options) 126 | const operation = options.dbOperation == 'Import Existing Schema' ? 'pull' : 'push' 127 | const basePath = options.templateDirectory.split('/templates')[0] 128 | const overwriteFolder = options.dbSolution.toLowerCase() 129 | const customOptions = { 130 | targetDirectory: options.targetDirectory, 131 | templateDirectory: basePath + '/overwrites/' + overwriteFolder 132 | } 133 | 134 | const overwriteRequired = ['postgres', 'mysql', 'mongodb'] //add DBs requiring overwrite here 135 | if (overwriteRequired.includes(overwriteFolder)) //guard clause to only overwrite when needed (Postgres, mySQL, mongodb etc) 136 | await copyTemplateFiles(customOptions) 137 | 138 | const resultPull = await execa('npx', ['prisma', 'db', operation], { 139 | cwd: options.targetDirectory, 140 | }) 141 | if (operation == 'pull') { 142 | const resultGenerate = await execa('npx', ['prisma', 'generate'], { 143 | cwd: options.targetDirectory, 144 | }) 145 | if (resultGenerate.failed) return Promise.reject(new Error('Failed to intialize DB via Prisma')) 146 | } 147 | if (resultPull.failed) { 148 | return Promise.reject(new Error('Failed to intialize DB via Prisma')) 149 | } 150 | return 151 | } 152 | 153 | async function copyEnvFile(options) { 154 | const content = `DATABASE_URL="${options.dbString}"` 155 | const file = options.targetDirectory + '/.env' 156 | fs.writeFile(file, content, function(err) { 157 | if (err) { 158 | throw err 159 | } 160 | return 161 | }) 162 | } 163 | 164 | async function initGit(options) { 165 | const result = await execa('git', ['init'], { 166 | cwd: options.targetDirectory, 167 | }) 168 | 169 | if (result.failed) { 170 | console.log('Failed to init git') 171 | return Promise.reject(new Error('Failed to initialize git')) 172 | } 173 | return 174 | } 175 | 176 | export async function createT3SvelteApp(options) { 177 | options = { 178 | ...options, 179 | targetDirectory: options.targetDirectory || process.cwd(), 180 | } 181 | const templateBaseDir = path.resolve(__filename, '../../templates') 182 | const templateName = options.template.toLowerCase() 183 | let templateDir = '' 184 | 185 | if (templateName == 'standard') templateDir = templateBaseDir + '/standard' 186 | else if (templateName == 'custom: typescript') templateDir = templateBaseDir + '/base_typescript' 187 | else templateDir = templateBaseDir + '/base_javascript' 188 | 189 | options.templateDirectory = templateDir 190 | 191 | try { 192 | await access(templateDir, fs.constants.R_OK) 193 | } catch (err) { 194 | console.log(templateDir) 195 | console.error('%s Invalid template name', chalk.red.bold('ERROR')) 196 | process.exit(1) 197 | } 198 | 199 | const tasks = new Listr([ 200 | { 201 | title: 'Copy project files', 202 | task: () => copyTemplateFiles(options, templateName, templateBaseDir + '/'), 203 | }, 204 | { 205 | title: 'Initialize git', 206 | task: () => initGit(options), 207 | enabled: () => options.git, 208 | }, 209 | { 210 | title: 'Install dependencies', 211 | task: () => { 212 | projectInstall({ 213 | prefer: userPkgManager, 214 | cwd: options.targetDirectory, 215 | }) 216 | }, 217 | enabled: () => options.runInstall, 218 | }, 219 | { 220 | title: 'Initialize DB', 221 | task: () => configureDatabase(options), 222 | enabled: () => options.db, 223 | }, 224 | ]) 225 | 226 | await tasks.run() 227 | console.log('%s SvelteT3 is ready!', chalk.green.bold('DONE')) 228 | return true 229 | } 230 | -------------------------------------------------------------------------------- /templates/+eslint_javascript/.eslintignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /build 4 | /.svelte-kit 5 | /package 6 | .env 7 | .env.* 8 | !.env.example 9 | 10 | # Ignore files for PNPM, NPM and YARN 11 | pnpm-lock.yaml 12 | package-lock.json 13 | yarn.lock 14 | -------------------------------------------------------------------------------- /templates/+eslint_javascript/.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | extends: ['eslint:recommended'], 4 | plugins: ['svelte3'], 5 | overrides: [{ files: ['*.svelte'], processor: 'svelte3/svelte3' }], 6 | parserOptions: { 7 | sourceType: 'module', 8 | ecmaVersion: 2020 9 | }, 10 | env: { 11 | browser: true, 12 | es2017: true, 13 | node: true 14 | } 15 | }; 16 | -------------------------------------------------------------------------------- /templates/+eslint_javascript/package.txt: -------------------------------------------------------------------------------- 1 | npm install --save -D --package-lock-only --no-package-lock eslint eslint-plugin-svelte3 -------------------------------------------------------------------------------- /templates/+eslint_prettier_javascript/.eslintignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /build 4 | /.svelte-kit 5 | /package 6 | .env 7 | .env.* 8 | !.env.example 9 | 10 | # Ignore files for PNPM, NPM and YARN 11 | pnpm-lock.yaml 12 | package-lock.json 13 | yarn.lock 14 | -------------------------------------------------------------------------------- /templates/+eslint_prettier_javascript/.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | extends: ['eslint:recommended', 'prettier'], 4 | plugins: ['svelte3'], 5 | overrides: [{ files: ['*.svelte'], processor: 'svelte3/svelte3' }], 6 | parserOptions: { 7 | sourceType: 'module', 8 | ecmaVersion: 2020 9 | }, 10 | env: { 11 | browser: true, 12 | es2017: true, 13 | node: true 14 | } 15 | }; 16 | -------------------------------------------------------------------------------- /templates/+eslint_prettier_javascript/.prettierignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /build 4 | /.svelte-kit 5 | /package 6 | .env 7 | .env.* 8 | !.env.example 9 | 10 | # Ignore files for PNPM, NPM and YARN 11 | pnpm-lock.yaml 12 | package-lock.json 13 | yarn.lock 14 | -------------------------------------------------------------------------------- /templates/+eslint_prettier_javascript/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "useTabs": true, 3 | "singleQuote": true, 4 | "tabWidth": 2, 5 | "trailingComma": "es5", 6 | "printWidth": 100, 7 | "pluginSearchDirs": ["."], 8 | "overrides": [{ "files": "*.svelte", "options": { "parser": "svelte" } }] 9 | } 10 | -------------------------------------------------------------------------------- /templates/+eslint_prettier_javascript/package.txt: -------------------------------------------------------------------------------- 1 | npm install --save -D --package-lock-only --no-package-lock eslint eslint-plugin-svelte3 prettier prettier-plugin-svelte eslint-config-prettier -------------------------------------------------------------------------------- /templates/+eslint_prettier_typescript/.eslintignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /build 4 | /.svelte-kit 5 | /package 6 | .env 7 | .env.* 8 | !.env.example 9 | 10 | # Ignore files for PNPM, NPM and YARN 11 | pnpm-lock.yaml 12 | package-lock.json 13 | yarn.lock 14 | -------------------------------------------------------------------------------- /templates/+eslint_prettier_typescript/.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | parser: '@typescript-eslint/parser', 4 | extends: ['eslint:recommended', 'plugin:@typescript-eslint/recommended', 'prettier'], 5 | plugins: ['svelte3', '@typescript-eslint'], 6 | ignorePatterns: ['*.cjs'], 7 | overrides: [{ files: ['*.svelte'], processor: 'svelte3/svelte3' }], 8 | settings: { 9 | 'svelte3/typescript': () => require('typescript') 10 | }, 11 | parserOptions: { 12 | sourceType: 'module', 13 | ecmaVersion: 2020 14 | }, 15 | env: { 16 | browser: true, 17 | es2017: true, 18 | node: true 19 | } 20 | }; 21 | -------------------------------------------------------------------------------- /templates/+eslint_prettier_typescript/.prettierignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /build 4 | /.svelte-kit 5 | /package 6 | .env 7 | .env.* 8 | !.env.example 9 | 10 | # Ignore files for PNPM, NPM and YARN 11 | pnpm-lock.yaml 12 | package-lock.json 13 | yarn.lock 14 | -------------------------------------------------------------------------------- /templates/+eslint_prettier_typescript/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "useTabs": true, 3 | "singleQuote": true, 4 | "tabWidth": 2, 5 | "trailingComma": "es5", 6 | "printWidth": 100, 7 | "pluginSearchDirs": ["."], 8 | "overrides": [{ "files": "*.svelte", "options": { "parser": "svelte" } }] 9 | } 10 | -------------------------------------------------------------------------------- /templates/+eslint_prettier_typescript/package.txt: -------------------------------------------------------------------------------- 1 | npm install --save -D --package-lock-only --no-package-lock prettier prettier-plugin-svelte eslint eslint-plugin-svelte3 @typescript-eslint/parser @typescript-eslint/eslint-plugin eslint-config-prettier -------------------------------------------------------------------------------- /templates/+eslint_typescript/.eslintignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /build 4 | /.svelte-kit 5 | /package 6 | .env 7 | .env.* 8 | !.env.example 9 | 10 | # Ignore files for PNPM, NPM and YARN 11 | pnpm-lock.yaml 12 | package-lock.json 13 | yarn.lock 14 | -------------------------------------------------------------------------------- /templates/+eslint_typescript/.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | parser: '@typescript-eslint/parser', 4 | extends: ['eslint:recommended', 'plugin:@typescript-eslint/recommended'], 5 | plugins: ['svelte3', '@typescript-eslint'], 6 | ignorePatterns: ['*.cjs'], 7 | overrides: [{ files: ['*.svelte'], processor: 'svelte3/svelte3' }], 8 | settings: { 9 | 'svelte3/typescript': () => require('typescript') 10 | }, 11 | parserOptions: { 12 | sourceType: 'module', 13 | ecmaVersion: 2020 14 | }, 15 | env: { 16 | browser: true, 17 | es2017: true, 18 | node: true 19 | } 20 | }; 21 | -------------------------------------------------------------------------------- /templates/+eslint_typescript/package.txt: -------------------------------------------------------------------------------- 1 | npm install --save -D --package-lock-only --no-package-lock eslint eslint-plugin-svelte3 @typescript-eslint/parser @typescript-eslint/eslint-plugin -------------------------------------------------------------------------------- /templates/+headlessui/package.txt: -------------------------------------------------------------------------------- 1 | npm install --save -D --package-lock-only --no-package-lock @rgossiaux/svelte-headlessui -------------------------------------------------------------------------------- /templates/+heroicons/package.txt: -------------------------------------------------------------------------------- 1 | npm install --save -D --package-lock-only --no-package-lock @rgossiaux/svelte-heroicons -------------------------------------------------------------------------------- /templates/+prettier/.prettierignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /build 4 | /.svelte-kit 5 | /package 6 | .env 7 | .env.* 8 | !.env.example 9 | 10 | # Ignore files for PNPM, NPM and YARN 11 | pnpm-lock.yaml 12 | package-lock.json 13 | yarn.lock 14 | -------------------------------------------------------------------------------- /templates/+prettier/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "useTabs": true, 3 | "singleQuote": true, 4 | "tabWidth": 2, 5 | "trailingComma": "es5", 6 | "printWidth": 100, 7 | "pluginSearchDirs": ["."], 8 | "overrides": [{ "files": "*.svelte", "options": { "parser": "svelte" } }] 9 | } 10 | -------------------------------------------------------------------------------- /templates/+prettier/package.txt: -------------------------------------------------------------------------------- 1 | npm install --save -D --package-lock-only --no-package-lock prettier prettier-plugin-svelte -------------------------------------------------------------------------------- /templates/+prisma/package.txt: -------------------------------------------------------------------------------- 1 | npm install --save -D --package-lock-only --no-package-lock prisma @prisma/client 2 | -------------------------------------------------------------------------------- /templates/+prisma/prisma/schema.prisma: -------------------------------------------------------------------------------- 1 | generator client { 2 | provider = "prisma-client-js" 3 | } 4 | 5 | datasource db { 6 | provider = "sqlite" 7 | url = "file:./main.db" 8 | //url = env("DATABASE_URL") 9 | } 10 | 11 | model User { 12 | id Int @id @default(autoincrement()) 13 | email String @unique 14 | name String? 15 | } -------------------------------------------------------------------------------- /templates/+prisma/src/lib/server/prismaClient.ts: -------------------------------------------------------------------------------- 1 | import pkg from '@prisma/client'; 2 | const { PrismaClient } = pkg; 3 | 4 | const prismaClient = new PrismaClient(); 5 | export default prismaClient; 6 | -------------------------------------------------------------------------------- /templates/+prisma_trpc/package.txt: -------------------------------------------------------------------------------- 1 | npm install --save --package-lock-only --no-package-lock @trpc/client@"^9.27.2" @trpc/server@"^9.27.2" trpc-sveltekit trpc-transformer zod && npm install --save -D --package-lock-only --no-package-lock @prisma/client prisma 2 | -------------------------------------------------------------------------------- /templates/+prisma_trpc/prisma/schema.prisma: -------------------------------------------------------------------------------- 1 | generator client { 2 | provider = "prisma-client-js" 3 | } 4 | 5 | datasource db { 6 | provider = "sqlite" 7 | url = "file:./main.db" 8 | //url = env("DATABASE_URL") 9 | } 10 | 11 | model User { 12 | id Int @id @default(autoincrement()) 13 | email String @unique 14 | name String? 15 | } -------------------------------------------------------------------------------- /templates/+prisma_trpc/src/hooks.server.ts: -------------------------------------------------------------------------------- 1 | import type { Handle } from '@sveltejs/kit' 2 | import { createContext, responseMeta, router } from '$lib/server/trpcServer' 3 | import { createTRPCHandle } from 'trpc-sveltekit' 4 | 5 | export const handle: Handle = async ({ event, resolve }) => { 6 | const response = await createTRPCHandle({ 7 | url: '/trpc', // optional; defaults to '/trpc' 8 | router, 9 | createContext, // optional 10 | responseMeta, // optional 11 | event, 12 | resolve, 13 | }) 14 | 15 | return response 16 | } 17 | -------------------------------------------------------------------------------- /templates/+prisma_trpc/src/lib/client/trpc.ts: -------------------------------------------------------------------------------- 1 | import type { Router } from '$lib/server/trpcServer' // 👈 only the types are imported from the server 2 | import * as trpc from '@trpc/client' 3 | import trpcTransformer from 'trpc-transformer' 4 | import type { inferProcedureInput, inferProcedureOutput } from '@trpc/server' 5 | 6 | const url = '/trpc' 7 | 8 | export default (loadFetch?: typeof fetch) => 9 | trpc.createTRPCClient({ 10 | url: loadFetch ? '/trpc' : url, 11 | transformer: trpcTransformer, 12 | ...(loadFetch && { fetch: loadFetch }), 13 | }) 14 | 15 | type Query = keyof Router['_def']['queries'] 16 | type Mutation = keyof Router['_def']['mutations'] 17 | 18 | export type InferQueryOutput = inferProcedureOutput< 19 | Router['_def']['queries'][RouteKey] 20 | > 21 | export type InferQueryInput = inferProcedureInput< 22 | Router['_def']['queries'][RouteKey] 23 | > 24 | export type InferMutationOutput = inferProcedureOutput< 25 | Router['_def']['mutations'][RouteKey] 26 | > 27 | export type InferMutationInput = inferProcedureInput< 28 | Router['_def']['mutations'][RouteKey] 29 | > 30 | -------------------------------------------------------------------------------- /templates/+prisma_trpc/src/lib/server/prismaClient.ts: -------------------------------------------------------------------------------- 1 | import pkg from '@prisma/client'; 2 | const { PrismaClient } = pkg; 3 | 4 | const prismaClient = new PrismaClient(); 5 | export default prismaClient; 6 | -------------------------------------------------------------------------------- /templates/+prisma_trpc/src/lib/server/trpcServer.ts: -------------------------------------------------------------------------------- 1 | import type { inferAsyncReturnType } from '@trpc/server' 2 | import * as trpc from '@trpc/server' 3 | import trpcTransformer from 'trpc-transformer' 4 | import prismaClient from './prismaClient' 5 | import { z } from 'zod' 6 | 7 | // optional 8 | export const createContext = () => { 9 | // ... 10 | return { 11 | /** context data */ 12 | } 13 | } 14 | 15 | // optional 16 | export const responseMeta = () => { 17 | // ... 18 | return { 19 | // { headers: ... } 20 | } 21 | } 22 | 23 | export const router = trpc 24 | .router>() 25 | .transformer(trpcTransformer) 26 | // queries and mutations... 27 | .query('getUser', { 28 | input: z.number(), 29 | resolve: ({ input }) => 30 | prismaClient.user.findFirst({ 31 | select: { 32 | email: true, 33 | }, 34 | where: { 35 | id: input, 36 | }, 37 | }), 38 | }) 39 | 40 | export type Router = typeof router 41 | -------------------------------------------------------------------------------- /templates/+tailwind/package.txt: -------------------------------------------------------------------------------- 1 | npm install --save -D --package-lock-only --no-package-lock postcss autoprefixer tailwindcss @tailwindcss/forms -------------------------------------------------------------------------------- /templates/+tailwind/postcss.config.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | } 7 | -------------------------------------------------------------------------------- /templates/+tailwind/src/app.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; -------------------------------------------------------------------------------- /templates/+tailwind/src/routes/+layout.svelte: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /templates/+tailwind/svelte.config.js: -------------------------------------------------------------------------------- 1 | import adapter from '@sveltejs/adapter-auto' 2 | import preprocess from 'svelte-preprocess' 3 | 4 | /** @type {import('@sveltejs/kit').Config} */ 5 | const config = { 6 | // Consult https://github.com/sveltejs/svelte-preprocess 7 | // for more information about preprocessors 8 | preprocess: preprocess({ 9 | postcss: true, 10 | }), 11 | kit: { 12 | adapter: adapter(), 13 | }, 14 | } 15 | 16 | export default config 17 | -------------------------------------------------------------------------------- /templates/+tailwind/tailwind.config.cjs: -------------------------------------------------------------------------------- 1 | /** @type {import('tailwindcss').Config} */ 2 | module.exports = { 3 | content: ['./src/**/*.{html,js,svelte,ts}'], 4 | theme: { 5 | extend: {} 6 | }, 7 | plugins: [require('@tailwindcss/forms')] 8 | }; 9 | -------------------------------------------------------------------------------- /templates/+tailwind_prettier_plugin/package.txt: -------------------------------------------------------------------------------- 1 | npm install --save -D --package-lock-only --no-package-lock prettier-plugin-tailwindcss -------------------------------------------------------------------------------- /templates/+trpc/package.txt: -------------------------------------------------------------------------------- 1 | npm install --save --package-lock-only --no-package-lock @trpc/client@"^9.27.2" @trpc/server@"^9.27.2" trpc-sveltekit trpc-transformer zod 2 | -------------------------------------------------------------------------------- /templates/+trpc/src/hooks.server.ts: -------------------------------------------------------------------------------- 1 | import type { Handle } from '@sveltejs/kit' 2 | import { createContext, responseMeta, router } from '$lib/server/trpcServer' 3 | import { createTRPCHandle } from 'trpc-sveltekit' 4 | 5 | export const handle: Handle = async ({ event, resolve }) => { 6 | const response = await createTRPCHandle({ 7 | url: '/trpc', // optional; defaults to '/trpc' 8 | router, 9 | createContext, // optional 10 | responseMeta, // optional 11 | event, 12 | resolve, 13 | }) 14 | 15 | return response 16 | } 17 | -------------------------------------------------------------------------------- /templates/+trpc/src/lib/client/trpc.ts: -------------------------------------------------------------------------------- 1 | import type { Router } from '$lib/server/trpcServer' // 👈 only the types are imported from the server 2 | import * as trpc from '@trpc/client' 3 | import trpcTransformer from 'trpc-transformer' 4 | import type { inferProcedureInput, inferProcedureOutput } from '@trpc/server' 5 | 6 | const url = '/trpc' 7 | 8 | export default (loadFetch?: typeof fetch) => 9 | trpc.createTRPCClient({ 10 | url: loadFetch ? '/trpc' : url, 11 | transformer: trpcTransformer, 12 | ...(loadFetch && { fetch: loadFetch }), 13 | }) 14 | 15 | type Query = keyof Router['_def']['queries'] 16 | type Mutation = keyof Router['_def']['mutations'] 17 | 18 | export type InferQueryOutput = inferProcedureOutput< 19 | Router['_def']['queries'][RouteKey] 20 | > 21 | export type InferQueryInput = inferProcedureInput< 22 | Router['_def']['queries'][RouteKey] 23 | > 24 | export type InferMutationOutput = inferProcedureOutput< 25 | Router['_def']['mutations'][RouteKey] 26 | > 27 | export type InferMutationInput = inferProcedureInput< 28 | Router['_def']['mutations'][RouteKey] 29 | > 30 | -------------------------------------------------------------------------------- /templates/+trpc/src/lib/server/trpcServer.ts: -------------------------------------------------------------------------------- 1 | //import prismaClient from './prismaClient' 2 | import type { inferAsyncReturnType } from '@trpc/server' 3 | import * as trpc from '@trpc/server' 4 | import trpcTransformer from 'trpc-transformer' 5 | import { z } from 'zod' 6 | 7 | // optional 8 | export const createContext = () => { 9 | // ... 10 | return { 11 | /** context data */ 12 | } 13 | } 14 | 15 | // optional 16 | export const responseMeta = () => { 17 | // ... 18 | return { 19 | // { headers: ... } 20 | } 21 | } 22 | 23 | export const router = trpc 24 | .router>() 25 | .transformer(trpcTransformer) 26 | // queries and mutations... 27 | .query('getUser', { 28 | input: z.number(), 29 | resolve: ({ input }) => 30 | // prismaClient.user.findFirst({ 31 | // select: { 32 | // email: true, 33 | // }, 34 | // where: { 35 | // id: input, 36 | // }, 37 | // }), 38 | }) 39 | 40 | export type Router = typeof router 41 | -------------------------------------------------------------------------------- /templates/base_javascript/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /build 4 | /.svelte-kit 5 | /package 6 | .env 7 | .env.* 8 | !.env.example 9 | -------------------------------------------------------------------------------- /templates/base_javascript/.npmrc: -------------------------------------------------------------------------------- 1 | engine-strict=true 2 | -------------------------------------------------------------------------------- /templates/base_javascript/README.md: -------------------------------------------------------------------------------- 1 | # T3Svelte Starter Project 2 | 3 | \*SvelteKit 4 | 5 | \*Typescript 6 | 7 | \*tRPC 8 | 9 | \*Prisma 10 | 11 | \*Tailwind CSS (@forms | @heroicons | @headlessui configured for Tailwind UI) 12 | 13 | \*Prettier + Prettier Tailwind + ESLint Preconfigured 14 | -------------------------------------------------------------------------------- /templates/base_javascript/jsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./.svelte-kit/tsconfig.json", 3 | "compilerOptions": { 4 | "allowJs": true, 5 | "checkJs": true, 6 | "esModuleInterop": true, 7 | "forceConsistentCasingInFileNames": true, 8 | "resolveJsonModule": true, 9 | "skipLibCheck": true, 10 | "sourceMap": true, 11 | "strict": true 12 | } 13 | // Path aliases are handled by https://kit.svelte.dev/docs/configuration#alias and https://kit.svelte.dev/docs/configuration#files 14 | // 15 | // If you want to overwrite includes/excludes, make sure to copy over the relevant includes/excludes 16 | // from the referenced tsconfig.json - TypeScript does not merge them in 17 | } 18 | -------------------------------------------------------------------------------- /templates/base_javascript/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "t3svelte-app", 3 | "version": "0.0.1", 4 | "private": true, 5 | "scripts": { 6 | "dev": "vite dev", 7 | "build": "vite build", 8 | "preview": "vite preview", 9 | "check": "svelte-kit sync && svelte-check --tsconfig ./jsconfig.json", 10 | "check:watch": "svelte-kit sync && svelte-check --tsconfig ./jsconfig.json --watch", 11 | "lint": "prettier --check . && eslint .", 12 | "format": "prettier --write ." 13 | }, 14 | "devDependencies": { 15 | "@sveltejs/adapter-auto": "next", 16 | "@sveltejs/kit": "next", 17 | "svelte": "^3.44.0", 18 | "svelte-check": "^2.7.1", 19 | "svelte-preprocess": "^4.10.7", 20 | "typescript": "^4.7.4", 21 | "vite": "^4.0.0" 22 | }, 23 | "type": "module", 24 | "dependencies": { 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /templates/base_javascript/src/app.d.ts: -------------------------------------------------------------------------------- 1 | // See https://kit.svelte.dev/docs/types#app 2 | // for information about these interfaces 3 | // and what to do when importing types 4 | declare namespace App { 5 | // interface Locals {} 6 | // interface PageData {} 7 | // interface Platform {} 8 | } 9 | -------------------------------------------------------------------------------- /templates/base_javascript/src/app.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | %sveltekit.head% 8 | 9 | 10 |
%sveltekit.body%
11 | 12 | 13 | -------------------------------------------------------------------------------- /templates/base_javascript/src/routes/+page.svelte: -------------------------------------------------------------------------------- 1 | 6 | 7 |
8 |
9 | T3-SvelteKit 13 |
14 |

Welcome to T3 SvelteKit

15 | -------------------------------------------------------------------------------- /templates/base_javascript/static/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zach-hopkins/create-t3svelte-app/52e10122a2349bb4d2f5cbd1e16217ba08146966/templates/base_javascript/static/favicon.png -------------------------------------------------------------------------------- /templates/base_javascript/svelte.config.js: -------------------------------------------------------------------------------- 1 | import adapter from '@sveltejs/adapter-auto' 2 | import preprocess from 'svelte-preprocess' 3 | 4 | /** @type {import('@sveltejs/kit').Config} */ 5 | const config = { 6 | // Consult https://github.com/sveltejs/svelte-preprocess 7 | // for more information about preprocessors 8 | preprocess: preprocess({ 9 | }), 10 | kit: { 11 | adapter: adapter(), 12 | }, 13 | } 14 | 15 | export default config 16 | -------------------------------------------------------------------------------- /templates/base_javascript/vite.config.js: -------------------------------------------------------------------------------- 1 | import { sveltekit } from '@sveltejs/kit/vite'; 2 | 3 | /** @type {import('vite').UserConfig} */ 4 | const config = { 5 | plugins: [sveltekit()] 6 | }; 7 | 8 | export default config; 9 | -------------------------------------------------------------------------------- /templates/base_typescript/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /build 4 | /.svelte-kit 5 | /package 6 | .env 7 | .env.* 8 | !.env.example 9 | -------------------------------------------------------------------------------- /templates/base_typescript/.npmrc: -------------------------------------------------------------------------------- 1 | engine-strict=true 2 | -------------------------------------------------------------------------------- /templates/base_typescript/README.md: -------------------------------------------------------------------------------- 1 | # T3Svelte Starter Project 2 | 3 | *SvelteKit 4 | 5 | *Typescript 6 | 7 | *tRPC 8 | 9 | *Prisma 10 | 11 | *Tailwind CSS (@forms | @heroicons | @headlessui configured for Tailwind UI) 12 | 13 | *Prettier + Prettier Tailwind + ESLint Preconfigured 14 | -------------------------------------------------------------------------------- /templates/base_typescript/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "t3svelte-app", 3 | "version": "0.0.1", 4 | "private": true, 5 | "scripts": { 6 | "dev": "vite dev", 7 | "build": "vite build", 8 | "preview": "vite preview", 9 | "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json", 10 | "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch", 11 | "lint": "prettier --check . && eslint .", 12 | "format": "prettier --write ." 13 | }, 14 | "devDependencies": { 15 | "@sveltejs/adapter-auto": "next", 16 | "@sveltejs/kit": "next", 17 | "svelte": "^3.44.0", 18 | "svelte-check": "^2.7.1", 19 | "svelte-preprocess": "^4.10.7", 20 | "tslib": "^2.3.1", 21 | "typescript": "^4.7.4", 22 | "vite": "^4.0.0" 23 | }, 24 | "type": "module", 25 | "dependencies": { 26 | } 27 | } -------------------------------------------------------------------------------- /templates/base_typescript/src/app.d.ts: -------------------------------------------------------------------------------- 1 | // See https://kit.svelte.dev/docs/types#app 2 | // for information about these interfaces 3 | // and what to do when importing types 4 | declare namespace App { 5 | // interface Locals {} 6 | // interface PageData {} 7 | // interface Platform {} 8 | } 9 | -------------------------------------------------------------------------------- /templates/base_typescript/src/app.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | %sveltekit.head% 8 | 9 | 10 |
%sveltekit.body%
11 | 12 | 13 | -------------------------------------------------------------------------------- /templates/base_typescript/src/routes/+page.svelte: -------------------------------------------------------------------------------- 1 | 12 | 13 |
14 |
15 | T3-SvelteKit 19 |
20 |

Welcome to T3 SvelteKit

-------------------------------------------------------------------------------- /templates/base_typescript/static/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zach-hopkins/create-t3svelte-app/52e10122a2349bb4d2f5cbd1e16217ba08146966/templates/base_typescript/static/favicon.png -------------------------------------------------------------------------------- /templates/base_typescript/svelte.config.js: -------------------------------------------------------------------------------- 1 | import adapter from '@sveltejs/adapter-auto' 2 | import preprocess from 'svelte-preprocess' 3 | 4 | /** @type {import('@sveltejs/kit').Config} */ 5 | const config = { 6 | // Consult https://github.com/sveltejs/svelte-preprocess 7 | // for more information about preprocessors 8 | preprocess: preprocess({ 9 | }), 10 | kit: { 11 | adapter: adapter(), 12 | }, 13 | } 14 | 15 | export default config 16 | -------------------------------------------------------------------------------- /templates/base_typescript/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./.svelte-kit/tsconfig.json", 3 | "compilerOptions": { 4 | "allowJs": true, 5 | "checkJs": true, 6 | "esModuleInterop": true, 7 | "forceConsistentCasingInFileNames": true, 8 | "resolveJsonModule": true, 9 | "skipLibCheck": true, 10 | "sourceMap": true, 11 | "strict": true 12 | } 13 | // Path aliases are handled by https://kit.svelte.dev/docs/configuration#alias 14 | // 15 | // If you want to overwrite includes/excludes, make sure to copy over the relevant includes/excludes 16 | // from the referenced tsconfig.json - TypeScript does not merge them in 17 | } 18 | -------------------------------------------------------------------------------- /templates/base_typescript/vite.config.ts: -------------------------------------------------------------------------------- 1 | import { sveltekit } from '@sveltejs/kit/vite'; 2 | import type { UserConfig } from 'vite'; 3 | 4 | const config: UserConfig = { 5 | plugins: [sveltekit()] 6 | }; 7 | 8 | export default config; 9 | -------------------------------------------------------------------------------- /templates/standard/.eslintignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /build 4 | /.svelte-kit 5 | /package 6 | .env 7 | .env.* 8 | !.env.example 9 | 10 | # Ignore files for PNPM, NPM and YARN 11 | pnpm-lock.yaml 12 | package-lock.json 13 | yarn.lock 14 | -------------------------------------------------------------------------------- /templates/standard/.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | parser: '@typescript-eslint/parser', 4 | extends: ['eslint:recommended', 'plugin:@typescript-eslint/recommended', 'prettier'], 5 | plugins: ['svelte3', '@typescript-eslint'], 6 | ignorePatterns: ['*.cjs'], 7 | overrides: [{ files: ['*.svelte'], processor: 'svelte3/svelte3' }], 8 | settings: { 9 | 'svelte3/typescript': () => require('typescript') 10 | }, 11 | parserOptions: { 12 | sourceType: 'module', 13 | ecmaVersion: 2020 14 | }, 15 | env: { 16 | browser: true, 17 | es2017: true, 18 | node: true 19 | } 20 | }; 21 | -------------------------------------------------------------------------------- /templates/standard/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /build 4 | /.svelte-kit 5 | /package 6 | .env 7 | .env.* 8 | !.env.example 9 | -------------------------------------------------------------------------------- /templates/standard/.npmrc: -------------------------------------------------------------------------------- 1 | engine-strict=true 2 | -------------------------------------------------------------------------------- /templates/standard/.prettierignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /build 4 | /.svelte-kit 5 | /package 6 | .env 7 | .env.* 8 | !.env.example 9 | 10 | # Ignore files for PNPM, NPM and YARN 11 | pnpm-lock.yaml 12 | package-lock.json 13 | yarn.lock 14 | -------------------------------------------------------------------------------- /templates/standard/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "useTabs": true, 3 | "singleQuote": true, 4 | "tabWidth": 2, 5 | "trailingComma": "es5", 6 | "semi": false, 7 | "bracketSameLine": true, 8 | "printWidth": 100, 9 | "pluginSearchDirs": ["."], 10 | "overrides": [{ "files": "*.svelte", "options": { "parser": "svelte" } }] 11 | } 12 | -------------------------------------------------------------------------------- /templates/standard/README.md: -------------------------------------------------------------------------------- 1 | # T3Svelte Starter Project 2 | 3 | *SvelteKit 4 | 5 | *Typescript 6 | 7 | *tRPC 8 | 9 | *Prisma 10 | 11 | *Tailwind CSS (@forms | @heroicons | @headlessui configured for Tailwind UI) 12 | 13 | *Prettier + Prettier Tailwind + ESLint Preconfigured 14 | -------------------------------------------------------------------------------- /templates/standard/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "t3svelte-app", 3 | "version": "0.0.1", 4 | "scripts": { 5 | "dev": "vite dev", 6 | "build": "vite build", 7 | "preview": "vite preview", 8 | "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json", 9 | "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch", 10 | "lint": "prettier --check . && eslint .", 11 | "format": "prettier --write ." 12 | }, 13 | "devDependencies": { 14 | "@rgossiaux/svelte-heroicons": "^0.1.2", 15 | "@sveltejs/adapter-auto": "next", 16 | "@sveltejs/kit": "next", 17 | "@typescript-eslint/eslint-plugin": "^5.27.0", 18 | "@typescript-eslint/parser": "^5.27.0", 19 | "autoprefixer": "^10.4.8", 20 | "eslint": "^8.16.0", 21 | "eslint-config-prettier": "^8.3.0", 22 | "eslint-plugin-svelte3": "^4.0.0", 23 | "postcss": "^8.4.16", 24 | "prettier": "^2.6.2", 25 | "prettier-plugin-svelte": "^2.7.0", 26 | "prettier-plugin-tailwindcss": "^0.1.13", 27 | "prisma": "^4.3.1", 28 | "svelte": "^3.44.0", 29 | "svelte-check": "^2.7.1", 30 | "svelte-preprocess": "^4.10.7", 31 | "tailwindcss": "^3.1.8", 32 | "tslib": "^2.3.1", 33 | "typescript": "^4.7.4", 34 | "vite": "^4.0.0", 35 | "@tailwindcss/forms": "^0.5.3", 36 | "@rgossiaux/svelte-headlessui": "^1.0.2" 37 | }, 38 | "type": "module", 39 | "dependencies": { 40 | "@prisma/client": "^4.3.1", 41 | "@trpc/client": "^9.27.2", 42 | "@trpc/server": "^9.27.2", 43 | "trpc-sveltekit": "^2.3.2", 44 | "trpc-transformer": "^2.1.1", 45 | "zod": "^3.19.0" 46 | } 47 | } -------------------------------------------------------------------------------- /templates/standard/postcss.config.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | } 7 | -------------------------------------------------------------------------------- /templates/standard/prisma/schema.prisma: -------------------------------------------------------------------------------- 1 | generator client { 2 | provider = "prisma-client-js" 3 | } 4 | 5 | datasource db { 6 | provider = "sqlite" 7 | url = "file:./main.db" 8 | //url = env("DATABASE_URL") 9 | } 10 | 11 | model User { 12 | id Int @id @default(autoincrement()) 13 | email String @unique 14 | name String? 15 | } -------------------------------------------------------------------------------- /templates/standard/src/app.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; -------------------------------------------------------------------------------- /templates/standard/src/app.d.ts: -------------------------------------------------------------------------------- 1 | // See https://kit.svelte.dev/docs/types#app 2 | // for information about these interfaces 3 | // and what to do when importing types 4 | declare namespace App { 5 | // interface Locals {} 6 | // interface PageData {} 7 | // interface Platform {} 8 | } 9 | -------------------------------------------------------------------------------- /templates/standard/src/app.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | %sveltekit.head% 8 | 9 | 10 |
%sveltekit.body%
11 | 12 | 13 | -------------------------------------------------------------------------------- /templates/standard/src/hooks.server.ts: -------------------------------------------------------------------------------- 1 | import type { Handle } from '@sveltejs/kit' 2 | import { createContext, responseMeta, router } from '$lib/server/trpcServer' 3 | import { createTRPCHandle } from 'trpc-sveltekit' 4 | 5 | export const handle: Handle = async ({ event, resolve }) => { 6 | const response = await createTRPCHandle({ 7 | url: '/trpc', // optional; defaults to '/trpc' 8 | router, 9 | createContext, // optional 10 | responseMeta, // optional 11 | event, 12 | resolve, 13 | }) 14 | 15 | return response 16 | } 17 | -------------------------------------------------------------------------------- /templates/standard/src/lib/client/trpc.ts: -------------------------------------------------------------------------------- 1 | import type { Router } from '$lib/server/trpcServer' // 👈 only the types are imported from the server 2 | import * as trpc from '@trpc/client' 3 | import trpcTransformer from 'trpc-transformer' 4 | import type { inferProcedureInput, inferProcedureOutput } from '@trpc/server' 5 | 6 | const url = '/trpc' 7 | 8 | export default (loadFetch?: typeof fetch) => 9 | trpc.createTRPCClient({ 10 | url: loadFetch ? '/trpc' : url, 11 | transformer: trpcTransformer, 12 | ...(loadFetch && { fetch: loadFetch }), 13 | }) 14 | 15 | type Query = keyof Router['_def']['queries'] 16 | type Mutation = keyof Router['_def']['mutations'] 17 | 18 | export type InferQueryOutput = inferProcedureOutput< 19 | Router['_def']['queries'][RouteKey] 20 | > 21 | export type InferQueryInput = inferProcedureInput< 22 | Router['_def']['queries'][RouteKey] 23 | > 24 | export type InferMutationOutput = inferProcedureOutput< 25 | Router['_def']['mutations'][RouteKey] 26 | > 27 | export type InferMutationInput = inferProcedureInput< 28 | Router['_def']['mutations'][RouteKey] 29 | > 30 | -------------------------------------------------------------------------------- /templates/standard/src/lib/server/prismaClient.ts: -------------------------------------------------------------------------------- 1 | import pkg from '@prisma/client'; 2 | const { PrismaClient } = pkg; 3 | 4 | const prismaClient = new PrismaClient(); 5 | export default prismaClient; 6 | -------------------------------------------------------------------------------- /templates/standard/src/lib/server/trpcServer.ts: -------------------------------------------------------------------------------- 1 | import type { inferAsyncReturnType } from '@trpc/server' 2 | import * as trpc from '@trpc/server' 3 | import trpcTransformer from 'trpc-transformer' 4 | import prismaClient from './prismaClient' 5 | import { z } from 'zod' 6 | 7 | // optional 8 | export const createContext = () => { 9 | // ... 10 | return { 11 | /** context data */ 12 | } 13 | } 14 | 15 | // optional 16 | export const responseMeta = () => { 17 | // ... 18 | return { 19 | // { headers: ... } 20 | } 21 | } 22 | 23 | export const router = trpc 24 | .router>() 25 | .transformer(trpcTransformer) 26 | // queries and mutations... 27 | .query('getUser', { 28 | input: z.number(), 29 | resolve: ({ input }) => 30 | prismaClient.user.findFirst({ 31 | select: { 32 | email: true, 33 | }, 34 | where: { 35 | id: input, 36 | }, 37 | }), 38 | }) 39 | 40 | export type Router = typeof router 41 | -------------------------------------------------------------------------------- /templates/standard/src/routes/+layout.svelte: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /templates/standard/src/routes/+page.svelte: -------------------------------------------------------------------------------- 1 | 12 | 13 |
14 |
15 | T3-SvelteKit 19 |
20 |

Welcome to T3 SvelteKit

-------------------------------------------------------------------------------- /templates/standard/static/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zach-hopkins/create-t3svelte-app/52e10122a2349bb4d2f5cbd1e16217ba08146966/templates/standard/static/favicon.png -------------------------------------------------------------------------------- /templates/standard/svelte.config.js: -------------------------------------------------------------------------------- 1 | import adapter from '@sveltejs/adapter-auto' 2 | import preprocess from 'svelte-preprocess' 3 | 4 | /** @type {import('@sveltejs/kit').Config} */ 5 | const config = { 6 | // Consult https://github.com/sveltejs/svelte-preprocess 7 | // for more information about preprocessors 8 | preprocess: preprocess({ 9 | }), 10 | kit: { 11 | adapter: adapter(), 12 | }, 13 | } 14 | 15 | export default config 16 | -------------------------------------------------------------------------------- /templates/standard/tailwind.config.cjs: -------------------------------------------------------------------------------- 1 | /** @type {import('tailwindcss').Config} */ 2 | module.exports = { 3 | content: ['./src/**/*.{html,js,svelte,ts}'], 4 | theme: { 5 | extend: {} 6 | }, 7 | plugins: [require('@tailwindcss/forms')] 8 | }; 9 | -------------------------------------------------------------------------------- /templates/standard/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./.svelte-kit/tsconfig.json", 3 | "compilerOptions": { 4 | "allowJs": true, 5 | "checkJs": true, 6 | "esModuleInterop": true, 7 | "forceConsistentCasingInFileNames": true, 8 | "resolveJsonModule": true, 9 | "skipLibCheck": true, 10 | "sourceMap": true, 11 | "strict": true 12 | } 13 | // Path aliases are handled by https://kit.svelte.dev/docs/configuration#alias 14 | // 15 | // If you want to overwrite includes/excludes, make sure to copy over the relevant includes/excludes 16 | // from the referenced tsconfig.json - TypeScript does not merge them in 17 | } 18 | -------------------------------------------------------------------------------- /templates/standard/vite.config.ts: -------------------------------------------------------------------------------- 1 | import { sveltekit } from '@sveltejs/kit/vite'; 2 | import type { UserConfig } from 'vite'; 3 | 4 | const config: UserConfig = { 5 | plugins: [sveltekit()] 6 | }; 7 | 8 | export default config; 9 | --------------------------------------------------------------------------------