{"id":18160715,"url":"https://github.com/blankeos/solid-launch","last_synced_at":"2025-05-07T08:44:56.080Z","repository":{"id":243108806,"uuid":"811417805","full_name":"Blankeos/solid-launch","owner":"Blankeos","description":"🧊 My SolidJS + Vike + Hono + tRPC Starter","archived":false,"fork":false,"pushed_at":"2025-04-22T17:27:45.000Z","size":1438,"stargazers_count":33,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-04-22T18:44:22.434Z","etag":null,"topics":["auth","boilerplate","hono","honojs","lucia-auth-v3","saas","solid","solid-js","solidjs","sqlite","starter-kit","tailwindcss","template","trpc","vike","vite"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Blankeos.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2024-06-06T14:59:50.000Z","updated_at":"2025-04-22T17:27:47.000Z","dependencies_parsed_at":"2024-06-24T15:11:48.265Z","dependency_job_id":"6861d491-945f-4c0d-8206-92a358cdef71","html_url":"https://github.com/Blankeos/solid-launch","commit_stats":null,"previous_names":["blankeos/solid-launch"],"tags_count":0,"template":true,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Blankeos%2Fsolid-launch","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Blankeos%2Fsolid-launch/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Blankeos%2Fsolid-launch/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Blankeos%2Fsolid-launch/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Blankeos","download_url":"https://codeload.github.com/Blankeos/solid-launch/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252846352,"owners_count":21813422,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["auth","boilerplate","hono","honojs","lucia-auth-v3","saas","solid","solid-js","solidjs","sqlite","starter-kit","tailwindcss","template","trpc","vike","vite"],"created_at":"2024-11-02T08:09:08.437Z","updated_at":"2025-05-07T08:44:56.061Z","avatar_url":"https://github.com/Blankeos.png","language":"TypeScript","readme":"## 💙 Solid Launch\n\n\u003e An sophisticated boiler-plate built for **simplicity**.\n\n![Image](https://assets.solidjs.com/banner?type=Starter%20Kit\u0026background=tiles\u0026project=Solid%20Launch)\n\n[Carlo](https://carlo.vercel.app/)'s starter for making a Vike + Solid app with batteries included on stuff I like after experimenting for years.\n\nThis is handcrafted from my own research. This might not work for you, but it works for me. 🤓\n\nYou can also try my other starters:\n\n- [🐇 Solid Hop](https://github.com/blankeos/solid-hop) - Less-opinionated Vike Solid boilerplate. Like `npx create solid` but simpler.\n- [🧡 Svelte Launch](https://github.com/blankeos/svelte-launch) - Svelte, but same robust practices.\n\n### Benefits\n\n- [x] 🐭 **Handcrafted and minimal** - picked and chose \"do one thing, do it well\" libraries that are just enough to get the job done. Just looks a bit bloated at a glance. (I kinda made my own NextJS from scatch here)\n- [x] ⚡️ **Super-fast dev server** - way faster than NextJS thanks to Vite. You need to feel it to believe it! It can also literally build your app in seconds.\n- [x] 💨 **Fast, efficient, fine-grained Reactivity** - thanks to Solid, it's possibly the most enjoyable framework I used that uses JSX. Has state management primitives out-of-the-box and keeps the experience a breeze.\n- [x] 🐍 **Extremely customizable** - you're not at the mercy of limited APIs and paradigms set by big frameworks or third-party services. Swap with your preferred JS backend framework/runtime if you want. Vike is just a middleware. Most of the tech I use here are open-source and roll-your-own type of thing. Hack it up! You're a dev aren't you?\n- [x] ☁️ **Selfhost-ready** - Crafted with simple hosting in mind that'll still probably scale to millions. Just spin up Docker container on a good'ol VPS without locking into serverless. DHH and Shayan influenced me on this. You can still host it on serverless tho. I think? lol\n- [x] **🔋 Batteries-included** - took care of the hard stuff for you. A well-thought-out folder structure from years of making projects: a design system, components, utilities, hooks, constants, an adequate backend DDD-inspired sliced architecture that isn't overkill, dockerizing your app, and most importantly---perfectly-crafted those pesky config files.\n- [x] 🔑 Authentication-Ready - One thing devs get stuck on. There's a practical auth implemented from scratch here that doesn't vendor-lock you into any auth provider.\n  - [x] Password\n  - [ ] Transactional Emails (Forgot Password, Email Verification)\n  - [ ] OAuth\n  - [ ] Magic Link\n  - [ ] User Management Dashboard\n\n### Tech Stack\n\n- [x] **Bun** - Runtime and package manager. You can always switch to Node and PNPM if you wish.\n- [x] **SolidJS** - Frontend framework that I like. Pretty underrated, but awesome!\n- [x] **Vike** - Like NextJS, but just a middleware. SSR library on-top of Vite. Use on any JS backend. Flexible, Simple, and Fast!\n- [x] **Hono** - 2nd fastest Bun framework(?), run anywhere, uses easy-to-understand web-standard paradigms.\n- [x] **tRPC** - E2E typesafety without context switching. Just amazing DevX.\n- [x] **Tailwind** - Styling the web has been pretty pleasant with it. I even use it on React Native for work. It's amazing.\n- [x] **Prisma** - Great _migrations_ workflow, but I want to maximize perf.\n- [x] **Kysely** - Great typesafe _query builder_ for SQL, minimally wraps around db connection.\n- [x] **SQLite/LibSQL (Turso)** - Cheapest database, easy to use.\n- [x] **Lucia Book + Arctic** - Makes self-rolling auth easy, and not dependent on any third-party. (You may learn a thing or two with this low-level implementation as well!)\n- [ ] **SES or MimePost** - Emails\n- [ ] **Backblaze** - Cheap blob object storage with an S3-compatible API.\n- [ ] **Paddle** - Accept payments and pay foreign taxes.\n\n### QuickStart\n\nI'll assume you don't want to change anything with this setup after cloning so let's get to work!\n\n1. Copy the environment variables\n\n   ```sh\n   cp .env.example .env\n   ```\n\n2. Replace the `\u003cabsolute_url\u003e` in the local database with:\n\n   ```sh\n   pwd # If it outputs: /User/Projects/solid-launch\n\n   # Replace the .env with:\n   DATABASE_URL=\"file:/User/Projects/solid-launch/local.db\"\n   ```\n\n3. Generate\n\n   ```sh\n   bun db:generate # generates Kysely and Prisma client types.\n   bun db:migrate # migrates your database.\n   ```\n\n4. Install deps and run dev\n\n   ```sh\n   bun install\n   bun dev\n   ```\n\n### Useful Development Tips\n\nI took care of the painstaking parts to help you develop easily on a SPA + SSR + backend paradigm. You can take take these practices to different projects as well.\n\n1.  Make use of the `code-snippets` I added. It'll help!\n2.  Check all typescript errors (`Cmd` + `Shift` + `B` \u003e `tsc:watch tsconfig.json`).\n3.  Authentication Practices - I have these out-of-the-box for you so you won't have to build it.\n\n    - Getting Current User\n\n      ```ts\n      import { useAuthContext } from '@/context/auth.context';\n\n      export default function MyComponent() {\n        const { user } = useAuthContext();\n      }\n      ```\n\n    - Login, Logout, Register\n\n      ```tsx\n      import { useAuthContext } from '@/context/auth.context';\n\n      export default function MyComponent() {\n        const { login, logout, register } = useAuthContext();\n      }\n      ```\n\n    - Hydrating Current User\n\n      This will also automatically hydrate in your layouts. Anywhere you use `useAuthStore()`, it's magic. (Thanks to Vike's `useData()`. Fun fact: You actually can't do this in SolidStart because it's architecturally different to Vike).\n\n      ```tsx\n      // +data.ts\n      import { initTRPCSSRClient } from '@/lib/trpc-ssr-client';\n      import { PageContext } from 'vike/types';\n\n      export type Data = ReturnType\u003cAwaited\u003ctypeof data\u003e\u003e;\n\n      export async function data(pageContext: PageContext) {\n        const { request, response } = pageContext;\n\n        const trpcClient = initTRPCSSRClient(request.header(), response.headers); // Pass the headers here.\n\n        const result = await trpcClient.auth.currentUser.query();\n\n        return {\n          user: result.user ?? null,\n        };\n      }\n      ```\n\n    - Protecting Routes (Client-Side)\n\n      ```tsx\n      import ProtectedRoute from '@/components/common/protected-route';\n\n      export default MyComponent() {\n         return (\n            \u003cProtectedRoute\u003e\n              On the server (hydration), this part will not be rendered if unauthenticated.\n\n              On the client, you will be redirected to a public route if unauthenticated.\n            \u003c/ProtectedRoute\u003e\n         )\n      }\n      ```\n\n    - Protecting Routes (SSR)\n\n      ```ts\n      // +guard.ts (If you don't have +data.ts in the same route).\n      export async function guard(pageContext: PageContext) {\n        const { request, response } = pageContext;\n\n        const trpcClient = initTRPCSSRClient(request.header(), response.headers); // Pass the headers here.\n\n        const result = await trpcClient.auth.currentUser.query();\n\n        if (!result.user) {\n          throw redirect('/'); // Must be a public route.\n        }\n      }\n\n      // +guard.ts (If you already have a +data.ts that gets the user).\n      // ⚠️ I have not tested this. This depends on `+guard` being called after `+data` is resolved.\n      export async function guard(pageContext: PageContext) {\n        if (!pageContext.data?.user) {\n          throw redirect('/'); // Must be a public route.\n        }\n      }\n      ```\n\n4.  Dataloading Practices - Also have these out-of-the-box for most usecases since they're tricky to do if you're clueless:\n    - Tanstack Query (Client-only) - Use `trpc-client.ts`\n    - Hydrated Tanstack Query (SSR) - Use `create-dehydrated-state.ts` + `trpc-ssr-client.ts`\n\n### Backend Architecture\n\nMy backend architecture is inspired by DDD where I separate in layers, but I keep it pragmatic by not going too overkill with Entities, Domains, and Aggregates. I personally still like the anemic data-driven architecture for most of my apps since the\napps I make aren't too business-logic-heavy.\n\n```sh\n.\n└── server/ # - root\n    ├── dao/ # - data-access-objects\n    │   └── *.dao.ts\n    ├── modules/\n    │   └── \u003cmodule\u003e/\n    │       ├── services/\n    │       │   └── *.service.ts # 1 service usecase\n    │       └── \u003cmodule\u003e.controller.ts\n    └── _app.ts # - root TRPC router.\n```\n\n- **`dao`** - abstracted away all queries here to interface with them as plain functions. It actually helps me mentally collocate db queries from service logic when I'm using them inside the service.\n- **`modules`** - a vertical slice of each module-group. This just depends on how I feel about grouping them. You get better overtime.\n- **`\u003cmodule\u003e.controller.ts`** - pretty much a group of http endpoints. I can put the DTOs/Validations for each endpoint here without context-switching.\n- **`services`** - these are even smaller pieces of logic that can be used inside each endpoint. It's not necessary to use if the app isn't too big, but it helps.\n- **`_app.ts`** - The root trpc router where the `AppRouter` type is exported.\n\n### Deployment\n\n\u003e [!WARNING]\n\u003e\n\u003e Still in progress\n\nHere are some guides on how to deploy.\n\n- [ ] Kamal (self-host VPS - I recommend)\n- [ ] Dokku (self-host VPS)\n- [ ] Caprover (self-host VPS)\n- [ ] Cloudflare (serverless + static)\n- [ ] Vercel (serverless + static)\n- [ ] Netlify (static)\n\n### Limitations\n\n- Websockets and Bun\n  - It works fine in Prod. But activating Vite HMR + Websockets is not possible in Bun.\n  - This is because Bun doesn't work with `Connect.Server` middlewares (which Vite uses). [[Source 1]](https://github.com/oven-sh/bun/issues/12212) [[Source 2]](https://github.com/honojs/vite-plugins/issues/140#issuecomment-2200134094)\n  - Bun Workaround: Having a separate process to run the Websocket server and your HTTP Server. Just make sure to use the same pubsub across these two processes (You can do this using Redis). Also make sure to combine them in a single process in production.\n  - Alternative recommendation: Use Node instead as it's possible to use `Connect.Server` middlewares in their `http` server: [PoC](https://github.com/Blankeos/realtime-user-status-node).\n\n### Future Plans\n\n\u003e I'll probably make a swapping guide soon. To replace to these:\n\u003e\n\u003e - Runtime: Bun -\u003e Node\n\u003e - Package Manager: Bun -\u003e PNPM\n\u003e - ORM: Prisma -\u003e Drizzle\n\u003e - Database: SQLite -\u003e PostgreSQL, CockroachDB, MongoDB\n\n\u003c!-- ## Usage\n\n```bash\n$ npm install # or pnpm install or yarn install\n```\n\n### Learn more on the [Solid Website](https://solidjs.com) and come chat with us on our [Discord](https://discord.com/invite/solidjs)\n\n## Available Scripts\n\nIn the project directory, you can run:\n\n### `npm run dev`\n\nRuns the app in the development mode.\u003cbr\u003e\nOpen [http://localhost:5173](http://localhost:5173) to view it in the browser.\n\n### `npm run build`\n\nBuilds the app for production to the `dist` folder.\u003cbr\u003e\nIt correctly bundles Solid in production mode and optimizes the build for the best performance.\n\nThe build is minified and the filenames include the hashes.\u003cbr\u003e\nYour app is ready to be deployed!\n\n## Deployment\n\nLearn more about deploying your application with the [documentations](https://vitejs.dev/guide/static-deploy.html) --\u003e\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fblankeos%2Fsolid-launch","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fblankeos%2Fsolid-launch","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fblankeos%2Fsolid-launch/lists"}