├── .env.example ├── .eslintignore ├── .eslintrc.cjs ├── .gitignore ├── .prettierignore ├── .vscode ├── extensions.json ├── launch.json ├── qwik-city.code-snippets ├── qwik.code-snippets └── settings.json ├── LICENSE ├── README.md ├── adapters └── vercel-edge │ └── vite.config.ts ├── components.json ├── drizzle.config.ts ├── drizzle ├── 0000_smooth_puck.sql └── meta │ ├── 0000_snapshot.json │ └── _journal.json ├── package.json ├── postcss.config.ts ├── prettier.config.ts ├── public ├── .well-known │ └── assetlinks.json ├── fonts │ ├── poppins-400.woff2 │ ├── poppins-500.woff2 │ └── poppins-700.woff2 ├── icons │ ├── X-dark │ │ ├── android-chrome-192x192.png │ │ ├── android-chrome-512x512.png │ │ ├── apple-touch-icon.png │ │ ├── favicon-16x16.png │ │ ├── favicon-32x32.png │ │ ├── favicon.ico │ │ ├── mstile-150x150.png │ │ └── safari-pinned-tab.svg │ ├── X-feature-graphic.png │ ├── X-icon-transparent-dark.png │ ├── X-light │ │ ├── android-chrome-192x192.png │ │ ├── android-chrome-512x512.png │ │ ├── apple-touch-icon.png │ │ ├── favicon-16x16.png │ │ ├── favicon-32x32.png │ │ ├── favicon.ico │ │ ├── mstile-150x150.png │ │ └── safari-pinned-tab.svg │ ├── X-og-image.png │ └── X │ │ ├── icon-128x128.png │ │ ├── icon-144x144.png │ │ ├── icon-152x152.png │ │ ├── icon-192x192.png │ │ ├── icon-384x384.png │ │ ├── icon-48x48.png │ │ ├── icon-512x512.png │ │ ├── icon-72x72.png │ │ └── icon-96x96.png ├── manifest.json ├── robots.txt └── screenshots │ ├── account.jpg │ ├── profile.jpg │ ├── signin.jpg │ └── x.jpg ├── src ├── components │ ├── auth │ │ ├── signin.tsx │ │ └── signout.tsx │ ├── partytown │ │ └── partytown.tsx │ ├── router-head │ │ └── router-head.tsx │ └── ui │ │ ├── button.tsx │ │ ├── card.tsx │ │ ├── checkbox.tsx │ │ ├── input.tsx │ │ ├── label.tsx │ │ ├── sidebarNav.tsx │ │ └── textarea.tsx ├── drizzle │ ├── db.ts │ └── schema │ │ └── auth.ts ├── entry.dev.tsx ├── entry.preview.tsx ├── entry.ssr.tsx ├── entry.vercel-edge.tsx ├── global.css ├── integrations │ └── react │ │ └── ui │ │ ├── progress.tsx │ │ └── separator.tsx ├── lib │ └── utils.ts ├── qwik-auth.d.ts ├── root.tsx └── routes │ ├── documentation │ └── index.tsx │ ├── index.tsx │ ├── layout.tsx │ ├── plugin@auth.ts │ ├── pub │ ├── layout.tsx │ ├── privacy-policy │ │ └── index.mdx │ └── terms-of-service │ │ └── index.mdx │ ├── service-worker.ts │ ├── settings │ ├── account │ │ └── index.tsx │ ├── contact │ │ └── index.tsx │ ├── layout.tsx │ └── profile │ │ └── index.tsx │ └── signin │ ├── accept-cookies.tsx │ └── index.tsx ├── tailwind.config.ts ├── tsconfig.json ├── vercel.json └── vite.config.ts /.env.example: -------------------------------------------------------------------------------- 1 | # Remember to put your secrets in a .env file and check that it is properly included in your .gitignore. 2 | 3 | #Auth.js 4 | AUTH_SECRET= 5 | 6 | ## PROVIDERS 7 | ### Discord Provider 8 | DISCORD_CLIENT_ID= 9 | DISCORD_CLIENT_SECRET= 10 | ### Google Provider 11 | GOOGLE_CLIENT_ID= 12 | GOOGLE_CLIENT_SECRET= 13 | ### Github Provider 14 | GITHUB_CLIENT_ID= 15 | GITHUB_CLIENT_SECRET= 16 | ### Twitter Provider 17 | TWITTER_CLIENT_ID= 18 | TWITTER_CLIENT_SECRET= 19 | ### Facebook Provider 20 | FACEBOOK_CLIENT_ID= 21 | FACEBOOK_CLIENT_SECRET= 22 | ### Twitch Provider 23 | TWITCH_CLIENT_ID= 24 | TWITCH_CLIENT_SECRET= 25 | 26 | # Drizzle 27 | DATABASE= 28 | DATABASE_HOST= 29 | DATABASE_USERNAME= 30 | DATABASE_PASSWORD= 31 | 32 | DATABASE_URL= -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | **/*.log 2 | **/.DS_Store 3 | *. 4 | .vscode/settings.json 5 | .history 6 | .yarn 7 | bazel-* 8 | bazel-bin 9 | bazel-out 10 | bazel-qwik 11 | bazel-testlogs 12 | dist 13 | dist-dev 14 | lib 15 | lib-types 16 | etc 17 | external 18 | node_modules 19 | temp 20 | tsc-out 21 | tsdoc-metadata.json 22 | target 23 | output 24 | rollup.config.js 25 | build 26 | .cache 27 | .vscode 28 | .rollup.cache 29 | dist 30 | tsconfig.tsbuildinfo 31 | vite.config.ts 32 | *.spec.tsx 33 | *.spec.ts 34 | .netlify 35 | pnpm-lock.yaml 36 | package-lock.json 37 | yarn.lock 38 | server 39 | -------------------------------------------------------------------------------- /.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | env: { 4 | browser: true, 5 | es2021: true, 6 | node: true, 7 | }, 8 | extends: [ 9 | "eslint:recommended", 10 | "plugin:@typescript-eslint/recommended", 11 | "plugin:qwik/recommended", 12 | ], 13 | parser: "@typescript-eslint/parser", 14 | parserOptions: { 15 | tsconfigRootDir: __dirname, 16 | project: ["./tsconfig.json"], 17 | ecmaVersion: 2021, 18 | sourceType: "module", 19 | ecmaFeatures: { 20 | jsx: true, 21 | }, 22 | }, 23 | plugins: ["@typescript-eslint"], 24 | rules: { 25 | "@typescript-eslint/no-explicit-any": "off", 26 | "@typescript-eslint/explicit-module-boundary-types": "off", 27 | "@typescript-eslint/no-inferrable-types": "off", 28 | "@typescript-eslint/no-non-null-assertion": "off", 29 | "@typescript-eslint/no-empty-interface": "off", 30 | "@typescript-eslint/no-namespace": "off", 31 | "@typescript-eslint/no-empty-function": "off", 32 | "@typescript-eslint/no-this-alias": "off", 33 | "@typescript-eslint/ban-types": "off", 34 | "@typescript-eslint/ban-ts-comment": "off", 35 | "@typescript-eslint/no-unused-vars": ["error"], 36 | "@typescript-eslint/consistent-type-imports": "warn", 37 | "@typescript-eslint/no-unnecessary-condition": "warn", 38 | "no-console": "warn", 39 | "no-case-declarations": "off", 40 | "prefer-spread": "off", 41 | "qwik/no-react-props": "off", 42 | }, 43 | }; 44 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Build 2 | /dist 3 | /lib 4 | /lib-types 5 | /server 6 | 7 | # Development 8 | node_modules 9 | *.local 10 | 11 | # Cache 12 | .cache 13 | .mf 14 | .rollup.cache 15 | tsconfig.tsbuildinfo 16 | 17 | # Logs 18 | logs 19 | *.log 20 | npm-debug.log* 21 | yarn-debug.log* 22 | yarn-error.log* 23 | pnpm-debug.log* 24 | lerna-debug.log* 25 | 26 | # Editor 27 | !.vscode/launch.json 28 | !.vscode/*.code-snippets 29 | 30 | .idea 31 | .DS_Store 32 | *.suo 33 | *.ntvs* 34 | *.njsproj 35 | *.sln 36 | *.sw? 37 | 38 | # Yarn 39 | .yarn/* 40 | !.yarn/releases 41 | 42 | # Vercel 43 | .vercel 44 | 45 | #env 46 | .env 47 | .env.local 48 | 49 | #package managers 50 | pnpm-lock.yaml 51 | package-lock.json 52 | yarn.lock -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | **/*.log 2 | **/.DS_Store 3 | *. 4 | .vscode/settings.json 5 | .history 6 | .yarn 7 | bazel-* 8 | bazel-bin 9 | bazel-out 10 | bazel-qwik 11 | bazel-testlogs 12 | dist 13 | dist-dev 14 | lib 15 | lib-types 16 | etc 17 | external 18 | node_modules 19 | temp 20 | tsc-out 21 | tsdoc-metadata.json 22 | target 23 | output 24 | rollup.config.js 25 | build 26 | .cache 27 | .vscode 28 | .rollup.cache 29 | dist 30 | tsconfig.tsbuildinfo 31 | vite.config.ts 32 | *.spec.tsx 33 | *.spec.ts 34 | .netlify 35 | pnpm-lock.yaml 36 | package-lock.json 37 | yarn.lock 38 | server 39 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": ["dbaeumer.vscode-eslint", "unifiedjs.vscode-mdx"], 3 | "unwantedRecommendations": [] 4 | } 5 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "type": "node", 9 | "name": "dev.debug", 10 | "request": "launch", 11 | "skipFiles": ["/**"], 12 | "cwd": "${workspaceFolder}", 13 | "program": "${workspaceFolder}/node_modules/vite/bin/vite.js", 14 | "args": ["--mode", "ssr", "--force"] 15 | } 16 | ] 17 | } 18 | -------------------------------------------------------------------------------- /.vscode/qwik-city.code-snippets: -------------------------------------------------------------------------------- 1 | { 2 | "onRequest": { 3 | "scope": "javascriptreact,typescriptreact", 4 | "prefix": "qonRequest", 5 | "description": "onRequest function for a route index", 6 | "body": [ 7 | "export const onRequest: RequestHandler = (request) => {", 8 | " $0", 9 | "};" 10 | ] 11 | }, 12 | "loader$": { 13 | "scope": "javascriptreact,typescriptreact", 14 | "prefix": "qloader$", 15 | "description": "loader$()", 16 | "body": ["export const $1 = routeLoader$(() => {", " $0", "});"] 17 | }, 18 | "action$": { 19 | "scope": "javascriptreact,typescriptreact", 20 | "prefix": "qaction$", 21 | "description": "action$()", 22 | "body": ["export const $1 = routeAction$((data) => {", " $0", "});"] 23 | }, 24 | "Full Page": { 25 | "scope": "javascriptreact,typescriptreact", 26 | "prefix": "qpage", 27 | "description": "Simple page component", 28 | "body": [ 29 | "import { component$ } from '@builder.io/qwik';", 30 | "", 31 | "export default component$(() => {", 32 | " $0", 33 | "});" 34 | ] 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /.vscode/qwik.code-snippets: -------------------------------------------------------------------------------- 1 | { 2 | "Qwik component (simple)": { 3 | "scope": "javascriptreact,typescriptreact", 4 | "prefix": "qcomponent$", 5 | "description": "Simple Qwik component", 6 | "body": [ 7 | "export const ${1:${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/}} = component$(() => {", 8 | " return <${2:div}>$4", 9 | "});" 10 | ] 11 | }, 12 | "Qwik component (props)": { 13 | "scope": "typescriptreact", 14 | "prefix": "qcomponent$ + props", 15 | "description": "Qwik component w/ props", 16 | "body": [ 17 | "export interface ${1:${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/}}Props {", 18 | " $2", 19 | "}", 20 | "", 21 | "export const $1 = component$<$1Props>((props) => {", 22 | " const ${2:count} = useSignal(0);", 23 | " return (", 24 | " <${3:div} on${4:Click}$={(ev) => {$5}}>", 25 | " $6", 26 | " ", 27 | " );", 28 | "});" 29 | ] 30 | }, 31 | "Qwik signal": { 32 | "scope": "javascriptreact,typescriptreact", 33 | "prefix": "quseSignal", 34 | "description": "useSignal() declaration", 35 | "body": ["const ${1:foo} = useSignal($2);", "$0"] 36 | }, 37 | "Qwik store": { 38 | "scope": "javascriptreact,typescriptreact", 39 | "prefix": "quseStore", 40 | "description": "useStore() declaration", 41 | "body": ["const ${1:state} = useStore({", " $2", "});", "$0"] 42 | }, 43 | "$ hook": { 44 | "scope": "javascriptreact,typescriptreact", 45 | "prefix": "q$", 46 | "description": "$() function hook", 47 | "body": ["$(() => {", " $0", "});", ""] 48 | }, 49 | "useVisibleTask": { 50 | "scope": "javascriptreact,typescriptreact", 51 | "prefix": "quseVisibleTask", 52 | "description": "useVisibleTask$() function hook", 53 | "body": ["useVisibleTask$(({ track }) => {", " $0", "});", ""] 54 | }, 55 | "useTask": { 56 | "scope": "javascriptreact,typescriptreact", 57 | "prefix": "quseTask$", 58 | "description": "useTask$() function hook", 59 | "body": [ 60 | "useTask$(({ track }) => {", 61 | " track(() => $1);", 62 | " $0", 63 | "});", 64 | "" 65 | ] 66 | }, 67 | "useResource": { 68 | "scope": "javascriptreact,typescriptreact", 69 | "prefix": "quseResource$", 70 | "description": "useResource$() declaration", 71 | "body": [ 72 | "const $1 = useResource$(({ track, cleanup }) => {", 73 | " $0", 74 | "});", 75 | "" 76 | ] 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "emmet.includeLanguages": { 3 | "typescriptreact": "html" 4 | }, 5 | "emmet.preferences": { 6 | // to ensure closing tags are used (e.g. not just like in HTML) 7 | // https://github.com/microsoft/vscode/commit/083bf9020407ea5a91199eb1f0b373859df8d600#diff-88456bc9b7caa2f8126aea0107b4671db0f094961aaf39a7c689f890e23aaaba 8 | "output.selfClosingStyle": "xhtml" 9 | }, 10 | "css.lint.unknownAtRules": "ignore", 11 | "tailwindCSS.experimental.classRegex": [ 12 | ["cva\\(([^)]*)\\)", "[\"'`]([^\"'`]*).*?[\"'`]"], 13 | ["cx\\(([^)]*)\\)", "(?:'|\"|`)([^']*)(?:'|\"|`)"] 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Maïeul Chevalier 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 | Click to see the source 3 |
4 | 5 |

Web-first, cross-platform stack for building apps at scale.

6 | 7 |
8 | 9 |

🙅‍♂️ No more re-writing your code for different platforms

10 |

🙅‍♂️ No more backend slowness

11 |

🙅‍♂️ No more frontend optimization

12 | 13 |
14 | 15 |

🙋‍♂️ Deployable on the web, mobile & desktop

16 |

🙋‍♂️ SSR first & Edge-Ready

17 |

🙋‍♂️ Signals based & Resumable

18 | 19 |
20 | 21 |

Website demo

22 |

23 | Play Store demo 👀 24 |

25 | 26 |
27 | 28 |

Come say hi on Discord 👋

29 | 30 |
31 |
32 | 33 | ## Core design 34 | 35 | **Empowering** 36 | 37 | An all-in-one toolbox for you to stop worrying about DX, scalability, performance, security, compatibility, customizability, maintainability, data modeling, data quality, and costs. 38 | 39 | **Intelligible** 40 | 41 | A place for you to easily weigh the pros and cons of each fullstack framework, components library/collection, API architecture, Database, ORM, analytics service, Auth toolkit, deployment strategy, and development tool. 42 | 43 | **Flexible** 44 | 45 | A cli to let you choose great alternatives that better match your project requirements _(tbd)_. 46 | 47 | ## Building blocks - bleeding edge, but production-ready. 48 | 49 | - ⚡️ **Fullstack framework: [Qwik](https://qwik.builder.io/)** 50 | - Make your app performant right from the start thanks to built-in resumability, automatic lazy-loading ($), signals-based reactivity, edge deployment, and server actions/loaders 51 | - Enjoy the best DX imaginable with code colocation, server/client RPC calls, app-wide middlewares, and automatic image optimization 52 | - Use any library from other frameworks (React & Angular ✅; Svelte, Solid & Vue incoming) 53 | - ✨ **Components ~~library~~ collection: [Qwikcn](https://github.com/x-ploration-of-mars/qwikcn) (Shadcn "port" with Tailwind & headless components)** 54 | 55 | > ⚠️ Qwikcn is still a work in progress and should be considered as experimental! 56 | 57 | - Own your components and create your own design system to match your own brand requirements 58 | - Copy/Paste UI templates to speed up your scaffolding 59 | - Customize your sections and components easily with Tailwind utility classes 60 | - Bring in your favorite icon library: Lucide, HeroIcons, Font Awesome, etc. 61 | - Ship less CSS with Tailwind’s JIT (just in time) engine 62 | - Style your forms and markdown easily with @tailwindcss/forms and @tailwindcss/typography 63 | - Integrate your components with StoryBook _(tbd)_ 64 | 65 | - 🦺 **API layer: [Server actions/loaders](https://qwik.builder.io/docs/route-loader/)** 66 | - Never break your app again with end-to-end type safety 67 | - Handle Form validation with **Valibot** and **modular-form** 68 | - Rate limit your requests with **Upstash** (serverless Redis) _(tbd)_ 69 | - 💦 **ORM: [Drizzle](https://orm.drizzle.team/)** 70 | - Define a type-safe schema and take advantage of Intellisense/Auto-completion 71 | - Write queries even faster than raw SQL 72 | - Don’t worry about joins (thank you, relational queries) 73 | - Run migrations with ease 74 | - Use it anywhere, even on the edge 75 | - 💪 **Database: [Planetscale](https://planetscale.com/) (Turso & Neon incoming)** 76 | - Scale to planet scale 77 | - Don’t worry about costs 78 | - Branch your database like you branch your code 79 | - Organize your migrations with deploy requests 80 | - Seamlessly deploy and revert schema changes with no downtime 81 | - Get real-time insights into your database performance 82 | - Integrate with third-party services for data warehousing, etc. 83 | - 🎯 **Analytics: [GA4](https://analytics.google.com/analytics) (Plausible & Umami incoming)** 84 | - Enjoy a [100% free](https://support.google.com/analytics/answer/1070983?hl=en#zippy=%2Cin-this-article) non-open-source software 85 | - Keep track of your AARRR metrics with ease thanks to well-designed visualizations 86 | - Enjoy the power of cohort-based analysis to measure app usage and learn from your users 87 | - Run A/B tests with GrowthBook to find out what drives your users 88 | - Works on any platform 89 | - 🔐 **Auth: Auth.js ([Qwik-Auth](https://qwik.builder.io/docs/integrations/authjs/))** 90 | - Enjoy a 100% free open-source auth solution 91 | - Easily implement social and OTP login 92 | - RBAC/ABAC support with custom user properties _(tbd)_ 93 | - Choose between Database or JWT sessions _(tbd)_ 94 | - Own your auth backend and improve query performance 95 | - 🍀 **Development tools:** 96 | - Vscode extensions: Eslint, Prettier, Pretty Typescript Errors 97 | - AI assistants: [Codeium](https://codeium.com/) & [chatgpt](https://chat.openai.com/) 98 | - VScode shortcuts: `ctrl + d` `ctrl + f` `ctrl + shift + f` `ctrl + p` 99 | - Logging _(tbd)_ 100 | - [Icon generation](https://tools.crawlink.com/tools/pwa-icon-generator/) 101 | - 🌐📱💻🥽 **Deployment: [Vercel](https://qwik.builder.io/docs/deployments/vercel-edge/) (Netlify + Cloudflare incoming) + [TWA](https://www.pwabuilder.com/)** 102 | > ⚠️ Be aware that there is currently no deployment option for Vercel serverless on Qwik. It means a bit of extra latency with Planetscale's free tier that is deployed in one region vs Qwik on the edge. 103 | - Deploy your app seamlessly on the web, but also on mobile and desktop with just one codebase 104 | - Take advantage of the wide ecosystem of npm libraries from the web 105 | - Port your web app to native easily without impacting performance & development costs 106 | 107 | Credits to [create-t3-app](https://github.com/t3-oss/create-t3-app) and the [epic-stack](https://github.com/epicweb-dev/epic-stack) that I’ve used as inspiration to make the 𝕏 stack a better stack. 108 | 109 |
110 | 111 | # How to _(wip)_ 112 | 113 | ## Test locally 114 | 115 | - Clone project `git clone https://github.com/x-ploration/x-stack.git` 116 | - Install dependencies `npm install` 117 | 118 | ### Add env variables 119 | 120 | - Copy `.env.example` into `.env` 121 | - Add `AUTH_SECRET` with this [secret generator](https://generate-secret.vercel.app/32) or with `openssl rand -base64 32` 122 | - Add Discord provider `DISCORD_CLIENT_ID` `DISCORD_CLIENT_SECRET` with https://discord.com/developers/applications. You will need to create a new application (top-right corner button `New Application`) and copy the “client id” and “client_secret” from the oauth2 settings. 123 | - Add Planetscale env vars. `DATABASE` `DATABASE_HOST` `DATABASE_USERNAME` `DATABASE_PASSWORD` with https://app.planetscale.com/. Go to `branches`, select your branch, click `connect`, and copy/paste. 124 | 125 | ### Add discord redirect 126 | 127 | - Add discord redirect to your localhost url (e.g. `http://localhost:5173/api/auth/callback/discord`) 128 | 129 | ### Replace GA4 property 130 | 131 | - In root.tsx, change id=G-VNBJX46X1T to your own GA4 property id 132 | 133 | ## Deploy 134 | 135 | - Push your code into a new GitHub repository 136 | - Go to vercel dashboard, `Add New` project (top-right button), and select your repository. Remember to add production env vars (the database env vars should point to your production database). 137 | - On your terminal, run build command `npm run build` 138 | - On your terminal, run deploy command `npm run deploy` 139 | - Add discord redirect to your production url (e.g. `https://x-stack.vercel.app/api/auth/callback/discord`). 140 | 141 |
142 | 143 | # Evaluation & Alternatives _(wip)_ 144 | 145 | The days of the MEAN (MongoDB, Express, Angular, Node.js) and MERN (MongoDB, Express, React, Node.js) stacks are over. For better or for worse, the web has gotten richer and richer. We now have amazing alternatives to what we used to use popping now and then, and this can feel overwhelming. So why not try to discuss and compare them in one single place? 146 | 147 | ## Fullstack Frameworks 148 | 149 | When we look at a fullstack framework, we need to take into consideration many aspects: Reactivity; SSR; DX; the ecosystem. Most frameworks have at least acceptable levels of reactivity, SSR, and DX, but the ecosystem is what makes the difference. So who is winning the battle? 150 | 151 | - 1️⃣ Qwik — Thanks to its serialized/resumable/compiled model, Qwik scores at the highest in many aspects: SSR _(ofc)_, but also Reactivity, DX, and **the ecosystem** (because you can run React inside of Qwik 🤯). Anything you can do in React, you can do in Qwik. But the opposite is not true. I wonder what could be possibly done in other frameworks that couldn’t be in Qwik 🤔. 152 | - 2️⃣ React / Next / Remix — If you ask me, I’d say Next comes next (👈), followed by Remix. They are not as good in terms of Reactivity as Svelte, Solid, or even Vue, but you will find libraries you won’t find natively built in the other frameworks (e.g. [react webcam](https://www.npmjs.com/package/react-webcam)) and get newer trendy libraries sooner (hi 👋 [shadcn](https://github.com/shadcn-ui/ui)). 153 | - 3️⃣ Svelte — I’d say it’s Svelte, because it is lightweight and brings significant performance gains, and it has Sveltekit ready. Rich Harris has also got some swag 👌. 154 | - 4️⃣ Vue / Nuxt 3 — Although I highly respect Daniel Roe, I think apart from small performance gains, Vue 3’s composition api is simply React hooks into Vue. It isn’t worth losing the ecosystem. 155 | - 5️⃣ Solid / Solidstart — Although Ryan is one of my heroes, Solidstart is still not solid (👈) enough to be used in production ☹️. 156 | - 6️⃣ Angular… 157 | 158 | ## Authentication 159 | 160 | - 1️⃣ Auth.js/Next-Auth — Open-source; 100% free; surprisingly powerful and flexible for an open-source library. 161 | - You won't find even half of its available adapters anywhere else. 162 | - Allows you to easily write custom logic through callbacks. 163 | - You can set up RBAC/ABAC pretty easily. 164 | - You can use jwt instead of database sessions if you want, although it's can be more complex and thus less secure. 165 | - 2️⃣ Clerk — Not open-source; hard to beat the DX; good if you’re not just looking for basic auth but a complete identity management solution that’s **easy** to use. 166 | - Supports RBAC/ABAC. 167 | - Supports jwt has a crazy number of frameworks and third-party integrations. 168 | - The only catch is that it’s good if you don’t have more than 10,000 users, because (I’ll let you do the maths) $0.02/$0.05 is not cheap. 169 | - 3️⃣ Supertokens — Open-source; really powerful; fair pricing; can be self-hosted; not so easy; good if you’re looking for advanced auth and identity management features that you couldn’t find elsewhere. 170 | - 4️⃣ Supabase Auth — Open-source; not free; works with Postgres and Row-level security; good if you only use postgres. 171 | - It uses jwt sessions with refresh tokens under the hood. Expiry time is set to 1 hour by default, which means that if an attacker gets hold of the jwt token (not the refresh token), he will have access to your user’s account until that jwt expires. This is why, if you’re using Supabase Auth, you should use it with Postgres for maximum security. 172 | - 5️⃣ Firebase Auth — Not open-source; free but not free if you use identity platform; works with Firestore, Firebase real-time database, and Firebase security rules; good if you only use Firebase. 173 | - It uses jwt sessions with refresh tokens under the hood. Expiry time is set to 1 hour by default, which means that if an attacker gets hold of the jwt token (not the refresh token), he will have access to your user’s account until that jwt expires. This is why, if you’re using Firebase Auth, you should use it with Firebase security rules for maximum security. 174 | - 6️⃣ Lucia — Open-source; 100% free; works with server loaders & actions only; doesn't support jwt sessions; A bit new and might be more flexible but might also require deeper auth knowledge to implement than Auth.js; good if you hate jayson web tokens. 175 | - 7️⃣ Auth0 — not OAuth; not cheap; not easy to use. 176 | - 8️⃣ AWS Cognito — If you want to be locked in AWS forever. 177 | - 9️⃣ Google Identity Platform — If you want to be locked in GCP forever. 178 | - 🔟 Okta, Onelogin, FusionAuth, Keycloak — don't know much about them. 179 | 180 | ## Components collections → [🔗comparison-table](https://docs.google.com/spreadsheets/d/1CHG5uK4AoMEl4giF9uY0RDJawjTdtT27gFwoIdRlxTY/edit#gid=225083988) _(wip)_ 181 | 182 | - 1️⃣ Shadcn/ui 183 | - 2️⃣ Tailwind-ui 184 | - 3️⃣ Bootstrap 185 | - 4️⃣ MUI 186 | - 5️⃣ Bulma 187 | - 6️⃣ Chakra-ui 188 | - 7️⃣ Mantine 189 | - 8️⃣ Ark UI 190 | 191 | ## API Architecture 192 | 193 | - 1️⃣ tRPC 194 | - 2️⃣ REST 195 | - 3️⃣ GraphQL 196 | - 4️⃣ loader/action RPC calls 197 | 198 | ## Database Platform 199 | 200 | - 1️⃣ Planetscale 201 | - 2️⃣ Turso 202 | - 3️⃣ Neon 203 | - 4️⃣ CockroachDB 204 | - 5️⃣ Supabase 205 | - 6️⃣ Railway 206 | - 7️⃣ SurrealDB 207 | - 8️⃣ Neo4j Aura 208 | - 9️⃣ MongoDB 209 | - 1️⃣0️⃣ Fauna 210 | - 1️⃣1️⃣ ArrangoDB 211 | 212 | ## ORM 213 | 214 | - 1️⃣ Drizzle 215 | - 2️⃣ Kysely 216 | - 3️⃣ Prisma 217 | - 4️⃣ Knex 218 | - 5️⃣ TypeORM 219 | 220 | ## Analytics 221 | 222 | - 1️⃣ GA4 223 | - 2️⃣ Umami 224 | - 3️⃣ Plausible 225 | - 4️⃣ Mixpanel 226 | - 5️⃣ Amplitude 227 | - 6️⃣ Matomo 228 | - 7️⃣ Piwik Pro 229 | - 8️⃣ Heap 230 | - 9️⃣ Hotjar 231 | - 1️⃣0️⃣ Gauges 232 | - 1️⃣1️⃣ PostHog 233 | 234 | ## A/B Testing 235 | 236 | - 1️⃣ GrowthBook 237 | - 2️⃣ Optimizely 238 | 239 | ## Rate Limiting 240 | 241 | - 1️⃣ Upstash 242 | - 2️⃣ Redis 243 | - 3️⃣ Memcached 244 | 245 | ## Deployment 246 | 247 | - 1️⃣ Vercel 248 | - 2️⃣ Netlify 249 | - 3️⃣ Cloudflare pages 250 | - 4️⃣ AWS 251 | - 5️⃣ GCP 252 | - 6️⃣ Azure 253 | 254 | ## Cross Platform solutions 255 | 256 | The main goal of a cross-platform solution is to write your code once, and run it on multiple platforms to reduce development costs. But before we take a look at the available options, we need to talk about the fundamentals. 257 | 258 | The core difference between web and native is that web always starts blank while native starts with a shell. As long as it's been built, you can access anything on the web, but you have to request the static parts (the shell) and the dynamic parts (the body) as part of the initial requests. On native apps on the other hand, you pre-download the static parts and then request the dynamic parts as the application is running. 259 | 260 | All of this might seem obvious, but this fundamental difference forces you to choose between three strategies: web-first, native-first, or native-only. 261 | 262 | ### Web-first strategy 263 | 264 | Web-first means that you build you app on the web and optimize it for the web with SSR for better SEO and performance - and then you port it to native. On the web, you are obviously limited to the web APIs, and so are you (more or less) when porting to native (for example, you can still use push notifications on native, which is a native API). 265 | 266 | The key thing to understand here is that your native apps will mostly consist of an empty shell that serves your SSR optimized web app. This might feel a bit wrong, but an SSR optimized app with proper UI transitions and prefetching mechanisms can result in far better UX: an app that feels like an app with almost **zero** loading times. 267 | 268 | > This is currently the strategy being used by the 𝕏 stack demo. 269 | 270 | ### Native-first 271 | 272 | Native-first means that you build your app as if it were a native app on native and on the web, so that it can use the native APIs with equivalent fallbacks on the browser. For example, your app will use the native camera access on the android and ios apps, but will fallback to the web camera access on the web. 273 | 274 | This approach has two major drawbacks. **(1)** In order to make this happen, you need to deploy your app as a static or CSR app that will fetch the body of the app once the static shell is up and running, which is known to be slower and bad for SEO. **(2)** It requires writing complex code that bridges the web and native APIs and will either result in limited capabilities or in imcompatibilities that will force you to write different code for native and web. 275 | 276 | ### Native-only 277 | 278 | Native-only means that you build your app for all platforms except for the web. This allows you to use the native APIs to their full capabilities and even extend them further. This requires building your app quite differently than mobile-first and forces you to give up on having a website, which can be okay if you don't expect much benefits from SEO. 279 | 280 | > The 𝕏 stack could potentially be used for native-only if future solutions support SSR out of the box. This would require testing. 281 | 282 |
283 | 284 | - 1️⃣ PWA — Web-first. 285 | - Installable through ios and android apps stores 286 | - Better performance than webviews on Android thanks to [TWA](https://developer.chrome.com/docs/android/trusted-web-activity/) 287 | - Incredibly easy to build with the web manifest 288 | - Needs a bit more testing on ios as a webview. 289 | > Push notifications should work with PWA on ios now. You can see PWA as a web app deployable on ios, android and desktop, hence web-first. 290 | - 2️⃣ Capacitor — Native-first or Native-only. 291 | - Slow on Android because [Android webviews are slow](https://github.com/ionic-team/capacitor/discussions/3899) 292 | - Doesn't work with SSR (server.url isn't intended for use in production and it is impossible to set-up authentication tools that use cookies with it) 293 | - Can be buggy if you don't use Ionic 294 | - Plugins are quite limited, aren't updated often and can be buggy 295 | - 3️⃣ Tauri — Native-first, Native-only and **potentially** web-first (requires testing) 296 | - Still in alpha/beta. 297 | - Likely slow on Android because [Android webviews are slow](https://github.com/ionic-team/capacitor/discussions/3899) 298 | - 4️⃣ Socket-Supply — Native-first, Native-only and **potentially** web-first (requires testing) 299 | - Still in alpha/beta 300 | - Likely Slow on Android because [Android webviews are slow](https://github.com/ionic-team/capacitor/discussions/3899) 301 | - Allows you to implement an on-the-device backend (e.g. for handling file-system access) thanks to built-in Rust security. 302 | - Can extend native APIs with Socket APIs like P2P capabilities. 303 | - 5️⃣ React-Native — Native-only (ios and android) 304 | - Battle tested for ios and android 305 | - React native for web is a joke, isn't it? 306 | - Limited to React (no automatic lazy-loading, no signals-based reactivity) 307 | 308 |
309 | 310 | # Contributors _(tbd)_ 311 | -------------------------------------------------------------------------------- /adapters/vercel-edge/vite.config.ts: -------------------------------------------------------------------------------- 1 | import { vercelEdgeAdapter } from "@builder.io/qwik-city/adapters/vercel-edge/vite"; 2 | import { extendConfig } from "@builder.io/qwik-city/vite"; 3 | import baseConfig from "../../vite.config"; 4 | 5 | export default extendConfig(baseConfig, () => { 6 | return { 7 | build: { 8 | ssr: true, 9 | rollupOptions: { 10 | input: ["src/entry.vercel-edge.tsx", "@qwik-city-plan"], 11 | }, 12 | outDir: ".vercel/output/functions/_qwik-city.func", 13 | }, 14 | plugins: [vercelEdgeAdapter()], 15 | }; 16 | }); 17 | -------------------------------------------------------------------------------- /components.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://ui.shadcn.com/schema.json", 3 | "style": "default", 4 | "rsc": false, 5 | "tsx": true, 6 | "tailwind": { 7 | "config": "tailwind.config.js", 8 | "css": "src/global.css", 9 | "baseColor": "zinc", 10 | "cssVariables": true 11 | }, 12 | "aliases": { 13 | "components": "~/integrations/react", 14 | "utils": "~/lib/utils" 15 | } 16 | } -------------------------------------------------------------------------------- /drizzle.config.ts: -------------------------------------------------------------------------------- 1 | import type { Config } from "drizzle-kit"; 2 | import * as dotenv from "dotenv"; 3 | dotenv.config(); 4 | 5 | export default { 6 | schema: "./src/drizzle/schema/*", 7 | driver: "mysql2", 8 | out: "./drizzle", 9 | dbCredentials: { 10 | host: process.env["DATABASE_HOST"]!, 11 | database: process.env["DATABASE"]!, 12 | user: process.env["DATABASE_USERNAME"]!, 13 | password: process.env["DATABASE_PASSWORD"]!, 14 | }, 15 | } satisfies Config; 16 | -------------------------------------------------------------------------------- /drizzle/0000_smooth_puck.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE `todo_items` ( 2 | `id` serial AUTO_INCREMENT NOT NULL, 3 | `text` varchar(256), 4 | CONSTRAINT `todo_items_id` PRIMARY KEY(`id`) 5 | ); 6 | --> statement-breakpoint 7 | CREATE TABLE `todo_lists` ( 8 | `id` serial AUTO_INCREMENT NOT NULL, 9 | `name` varchar(256), 10 | CONSTRAINT `todo_lists_id` PRIMARY KEY(`id`) 11 | ); 12 | -------------------------------------------------------------------------------- /drizzle/meta/0000_snapshot.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "5", 3 | "dialect": "mysql", 4 | "id": "127c65f1-4c65-4548-a619-02a518228fe5", 5 | "prevId": "00000000-0000-0000-0000-000000000000", 6 | "tables": { 7 | "todo_items": { 8 | "name": "todo_items", 9 | "columns": { 10 | "id": { 11 | "name": "id", 12 | "type": "serial", 13 | "primaryKey": false, 14 | "notNull": true, 15 | "autoincrement": true 16 | }, 17 | "text": { 18 | "name": "text", 19 | "type": "varchar(256)", 20 | "primaryKey": false, 21 | "notNull": false, 22 | "autoincrement": false 23 | } 24 | }, 25 | "indexes": {}, 26 | "foreignKeys": {}, 27 | "compositePrimaryKeys": { 28 | "todo_items_id": { 29 | "name": "todo_items_id", 30 | "columns": [ 31 | "id" 32 | ] 33 | } 34 | }, 35 | "uniqueConstraints": {} 36 | }, 37 | "todo_lists": { 38 | "name": "todo_lists", 39 | "columns": { 40 | "id": { 41 | "name": "id", 42 | "type": "serial", 43 | "primaryKey": false, 44 | "notNull": true, 45 | "autoincrement": true 46 | }, 47 | "name": { 48 | "name": "name", 49 | "type": "varchar(256)", 50 | "primaryKey": false, 51 | "notNull": false, 52 | "autoincrement": false 53 | } 54 | }, 55 | "indexes": {}, 56 | "foreignKeys": {}, 57 | "compositePrimaryKeys": { 58 | "todo_lists_id": { 59 | "name": "todo_lists_id", 60 | "columns": [ 61 | "id" 62 | ] 63 | } 64 | }, 65 | "uniqueConstraints": {} 66 | } 67 | }, 68 | "schemas": {}, 69 | "_meta": { 70 | "schemas": {}, 71 | "tables": {}, 72 | "columns": {} 73 | } 74 | } -------------------------------------------------------------------------------- /drizzle/meta/_journal.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "5", 3 | "dialect": "mysql", 4 | "entries": [ 5 | { 6 | "idx": 0, 7 | "version": "5", 8 | "when": 1690812916453, 9 | "tag": "0000_smooth_puck", 10 | "breakpoints": true 11 | } 12 | ] 13 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "x-stack", 3 | "description": "Demo App with Routing built-in (recommended)", 4 | "engines": { 5 | "node": ">=15.0.0" 6 | }, 7 | "private": true, 8 | "scripts": { 9 | "build": "qwik build", 10 | "build.client": "vite build", 11 | "build.preview": "vite build --ssr src/entry.preview.tsx", 12 | "build.server": "vite build -c adapters/vercel-edge/vite.config.ts", 13 | "build.types": "tsc --incremental --noEmit", 14 | "deploy": "vercel deploy", 15 | "dev": "vite --mode ssr", 16 | "dev.debug": "node --inspect-brk ./node_modules/vite/bin/vite.js --mode ssr --force", 17 | "fmt": "prettier --write .", 18 | "fmt.check": "prettier --check .", 19 | "lint": "eslint \"src/**/*.ts*\"", 20 | "preview": "qwik build preview && vite preview --open", 21 | "start": "vite --open --mode ssr", 22 | "db:generate": "drizzle-kit generate:mysql", 23 | "db:push": "drizzle-kit push:mysql", 24 | "db:up": "drizzle-kit up:mysql", 25 | "studio": "drizzle-kit studio", 26 | "qwik": "qwik" 27 | }, 28 | "devDependencies": { 29 | "@auth/core": "0.13.0", 30 | "@builder.io/qwik": "1.4.3", 31 | "@builder.io/qwik-auth": "0.1.3", 32 | "@builder.io/qwik-city": "1.4.3", 33 | "@builder.io/qwik-react": "0.5.0", 34 | "@qwik-ui/headless": "0.2.2", 35 | "@tailwindcss/forms": "0.5.7", 36 | "@tailwindcss/typography": "0.5.10", 37 | "@types/eslint": "8.44.4", 38 | "@types/gtag.js": "0.0.18", 39 | "@types/node": "20.11.10", 40 | "@types/react": "18.2.28", 41 | "@types/react-dom": "18.2.13", 42 | "@typescript-eslint/eslint-plugin": "6.8.0", 43 | "@typescript-eslint/parser": "6.8.0", 44 | "autoprefixer": "10.4.17", 45 | "dotenv": "16.4.1", 46 | "drizzle-kit": "0.20.14", 47 | "eslint": "8.51.0", 48 | "eslint-plugin-qwik": "1.4.3", 49 | "postcss": "8.4.33", 50 | "prettier": "3.2.4", 51 | "prettier-plugin-tailwindcss": "0.5.11", 52 | "react": "18.2.0", 53 | "react-dom": "18.2.0", 54 | "tailwindcss": "3.4.1", 55 | "ts-node": "10.9.2", 56 | "typescript": "5.3.3", 57 | "undici": "5.26.3", 58 | "vercel": "33.4.1", 59 | "vite": "4.5.2", 60 | "vite-tsconfig-paths": "4.3.1" 61 | }, 62 | "dependencies": { 63 | "@auth/drizzle-adapter": "0.5.0", 64 | "@builder.io/partytown": "0.9.1", 65 | "@modular-forms/qwik": "0.23.1", 66 | "@planetscale/database": "1.14.0", 67 | "@qwikest/icons": "0.0.13", 68 | "@radix-ui/react-progress": "1.0.3", 69 | "@radix-ui/react-separator": "1.0.3", 70 | "class-variance-authority": "0.7.0", 71 | "clsx": "2.1.0", 72 | "drizzle-orm": "0.29.3", 73 | "drizzle-valibot": "0.1.1", 74 | "mysql2": "3.9.1", 75 | "tailwind-merge": "2.2.1", 76 | "tailwindcss-animate": "1.0.7", 77 | "valibot": "0.27.1" 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /postcss.config.ts: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | } 7 | -------------------------------------------------------------------------------- /prettier.config.ts: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: ["prettier-plugin-tailwindcss"], 3 | }; 4 | -------------------------------------------------------------------------------- /public/.well-known/assetlinks.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "relation": ["delegate_permission/common.handle_all_urls"], 4 | "target": { 5 | "namespace": "android_app", 6 | "package_name": "app.vercel.x_stack.twa", 7 | "sha256_cert_fingerprints": 8 | ["34:BF:9E:E3:08:D8:C8:D8:F6:D0:7A:34:34:E0:FE:75:9F:32:C8:C5:17:BF:BB:74:2A:9A:1A:5E:78:0E:F1:5C"] 9 | } 10 | } 11 | ] -------------------------------------------------------------------------------- /public/fonts/poppins-400.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/x-ploration-of-mars/x-stack/38c4518266f49ef93b1a936efdffde2145e64156/public/fonts/poppins-400.woff2 -------------------------------------------------------------------------------- /public/fonts/poppins-500.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/x-ploration-of-mars/x-stack/38c4518266f49ef93b1a936efdffde2145e64156/public/fonts/poppins-500.woff2 -------------------------------------------------------------------------------- /public/fonts/poppins-700.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/x-ploration-of-mars/x-stack/38c4518266f49ef93b1a936efdffde2145e64156/public/fonts/poppins-700.woff2 -------------------------------------------------------------------------------- /public/icons/X-dark/android-chrome-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/x-ploration-of-mars/x-stack/38c4518266f49ef93b1a936efdffde2145e64156/public/icons/X-dark/android-chrome-192x192.png -------------------------------------------------------------------------------- /public/icons/X-dark/android-chrome-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/x-ploration-of-mars/x-stack/38c4518266f49ef93b1a936efdffde2145e64156/public/icons/X-dark/android-chrome-512x512.png -------------------------------------------------------------------------------- /public/icons/X-dark/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/x-ploration-of-mars/x-stack/38c4518266f49ef93b1a936efdffde2145e64156/public/icons/X-dark/apple-touch-icon.png -------------------------------------------------------------------------------- /public/icons/X-dark/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/x-ploration-of-mars/x-stack/38c4518266f49ef93b1a936efdffde2145e64156/public/icons/X-dark/favicon-16x16.png -------------------------------------------------------------------------------- /public/icons/X-dark/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/x-ploration-of-mars/x-stack/38c4518266f49ef93b1a936efdffde2145e64156/public/icons/X-dark/favicon-32x32.png -------------------------------------------------------------------------------- /public/icons/X-dark/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/x-ploration-of-mars/x-stack/38c4518266f49ef93b1a936efdffde2145e64156/public/icons/X-dark/favicon.ico -------------------------------------------------------------------------------- /public/icons/X-dark/mstile-150x150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/x-ploration-of-mars/x-stack/38c4518266f49ef93b1a936efdffde2145e64156/public/icons/X-dark/mstile-150x150.png -------------------------------------------------------------------------------- /public/icons/X-dark/safari-pinned-tab.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 7 | 8 | Created by potrace 1.14, written by Peter Selinger 2001-2017 9 | 10 | 12 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /public/icons/X-feature-graphic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/x-ploration-of-mars/x-stack/38c4518266f49ef93b1a936efdffde2145e64156/public/icons/X-feature-graphic.png -------------------------------------------------------------------------------- /public/icons/X-icon-transparent-dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/x-ploration-of-mars/x-stack/38c4518266f49ef93b1a936efdffde2145e64156/public/icons/X-icon-transparent-dark.png -------------------------------------------------------------------------------- /public/icons/X-light/android-chrome-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/x-ploration-of-mars/x-stack/38c4518266f49ef93b1a936efdffde2145e64156/public/icons/X-light/android-chrome-192x192.png -------------------------------------------------------------------------------- /public/icons/X-light/android-chrome-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/x-ploration-of-mars/x-stack/38c4518266f49ef93b1a936efdffde2145e64156/public/icons/X-light/android-chrome-512x512.png -------------------------------------------------------------------------------- /public/icons/X-light/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/x-ploration-of-mars/x-stack/38c4518266f49ef93b1a936efdffde2145e64156/public/icons/X-light/apple-touch-icon.png -------------------------------------------------------------------------------- /public/icons/X-light/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/x-ploration-of-mars/x-stack/38c4518266f49ef93b1a936efdffde2145e64156/public/icons/X-light/favicon-16x16.png -------------------------------------------------------------------------------- /public/icons/X-light/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/x-ploration-of-mars/x-stack/38c4518266f49ef93b1a936efdffde2145e64156/public/icons/X-light/favicon-32x32.png -------------------------------------------------------------------------------- /public/icons/X-light/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/x-ploration-of-mars/x-stack/38c4518266f49ef93b1a936efdffde2145e64156/public/icons/X-light/favicon.ico -------------------------------------------------------------------------------- /public/icons/X-light/mstile-150x150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/x-ploration-of-mars/x-stack/38c4518266f49ef93b1a936efdffde2145e64156/public/icons/X-light/mstile-150x150.png -------------------------------------------------------------------------------- /public/icons/X-light/safari-pinned-tab.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 7 | 8 | Created by potrace 1.14, written by Peter Selinger 2001-2017 9 | 10 | 12 | 76 | 77 | 78 | -------------------------------------------------------------------------------- /public/icons/X-og-image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/x-ploration-of-mars/x-stack/38c4518266f49ef93b1a936efdffde2145e64156/public/icons/X-og-image.png -------------------------------------------------------------------------------- /public/icons/X/icon-128x128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/x-ploration-of-mars/x-stack/38c4518266f49ef93b1a936efdffde2145e64156/public/icons/X/icon-128x128.png -------------------------------------------------------------------------------- /public/icons/X/icon-144x144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/x-ploration-of-mars/x-stack/38c4518266f49ef93b1a936efdffde2145e64156/public/icons/X/icon-144x144.png -------------------------------------------------------------------------------- /public/icons/X/icon-152x152.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/x-ploration-of-mars/x-stack/38c4518266f49ef93b1a936efdffde2145e64156/public/icons/X/icon-152x152.png -------------------------------------------------------------------------------- /public/icons/X/icon-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/x-ploration-of-mars/x-stack/38c4518266f49ef93b1a936efdffde2145e64156/public/icons/X/icon-192x192.png -------------------------------------------------------------------------------- /public/icons/X/icon-384x384.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/x-ploration-of-mars/x-stack/38c4518266f49ef93b1a936efdffde2145e64156/public/icons/X/icon-384x384.png -------------------------------------------------------------------------------- /public/icons/X/icon-48x48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/x-ploration-of-mars/x-stack/38c4518266f49ef93b1a936efdffde2145e64156/public/icons/X/icon-48x48.png -------------------------------------------------------------------------------- /public/icons/X/icon-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/x-ploration-of-mars/x-stack/38c4518266f49ef93b1a936efdffde2145e64156/public/icons/X/icon-512x512.png -------------------------------------------------------------------------------- /public/icons/X/icon-72x72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/x-ploration-of-mars/x-stack/38c4518266f49ef93b1a936efdffde2145e64156/public/icons/X/icon-72x72.png -------------------------------------------------------------------------------- /public/icons/X/icon-96x96.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/x-ploration-of-mars/x-stack/38c4518266f49ef93b1a936efdffde2145e64156/public/icons/X/icon-96x96.png -------------------------------------------------------------------------------- /public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/web-manifest-combined.json", 3 | "id": "com.example.xstackdemo", 4 | "name": "X Stack Demo", 5 | "short_name": "X Stack", 6 | "description": "A demo of the X Stack", 7 | "start_url": ".", 8 | "theme_color": "#000", 9 | "background_color": "#fafafa", 10 | "display": "standalone", 11 | "display_override": ["window-controls-overlay", "standalone", "fullscreen"], 12 | "orientation": "portrait", 13 | "icons": [ 14 | { 15 | "src": "/icons/X/icon-48x48.png", 16 | "sizes": "48x48", 17 | "type": "image/png", 18 | "purpose": "maskable any" 19 | }, 20 | { 21 | "src": "/icons/X/icon-72x72.png", 22 | "sizes": "72x72", 23 | "type": "image/png", 24 | "purpose": "maskable any" 25 | }, 26 | { 27 | "src": "/icons/X/icon-96x96.png", 28 | "sizes": "96x96", 29 | "type": "image/png", 30 | "purpose": "maskable any" 31 | }, 32 | { 33 | "src": "/icons/X/icon-128x128.png", 34 | "sizes": "128x128", 35 | "type": "image/png", 36 | "purpose": "maskable any" 37 | }, 38 | { 39 | "src": "/icons/X/icon-144x144.png", 40 | "sizes": "144x144", 41 | "type": "image/png", 42 | "purpose": "maskable any" 43 | }, 44 | { 45 | "src": "/icons/X/icon-152x152.png", 46 | "sizes": "152x152", 47 | "type": "image/png", 48 | "purpose": "maskable any" 49 | }, 50 | { 51 | "src": "/icons/X/icon-192x192.png", 52 | "sizes": "192x192", 53 | "type": "image/png", 54 | "purpose": "maskable any" 55 | }, 56 | { 57 | "src": "/icons/X/icon-384x384.png", 58 | "sizes": "384x384", 59 | "type": "image/png", 60 | "purpose": "maskable any" 61 | }, 62 | { 63 | "src": "/icons/X/icon-512x512.png", 64 | "sizes": "512x512", 65 | "type": "image/png", 66 | "purpose": "any" 67 | } 68 | ], 69 | "edge_side_panel": { 70 | "default": "closed", 71 | "hide_close_button": false 72 | }, 73 | "handle_links": "auto", 74 | "launch_handler": { 75 | "client_mode": "auto" 76 | }, 77 | "screenshots": [ 78 | { 79 | "src": "/screenshots/account.jpg", 80 | "sizes": "1080x1920", 81 | "type": "image/jpg" 82 | }, 83 | { 84 | "src": "/screenshots/profile.jpg", 85 | "sizes": "1080x1920", 86 | "type": "image/jpg" 87 | }, 88 | { 89 | "src": "/screenshots/signin.jpg", 90 | "sizes": "1080x1920", 91 | "type": "image/jpg" 92 | }, 93 | { 94 | "src": "/screenshots/x.jpg", 95 | "sizes": "1080x1920", 96 | "type": "image/jpg" 97 | } 98 | ] 99 | } 100 | -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/x-ploration-of-mars/x-stack/38c4518266f49ef93b1a936efdffde2145e64156/public/robots.txt -------------------------------------------------------------------------------- /public/screenshots/account.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/x-ploration-of-mars/x-stack/38c4518266f49ef93b1a936efdffde2145e64156/public/screenshots/account.jpg -------------------------------------------------------------------------------- /public/screenshots/profile.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/x-ploration-of-mars/x-stack/38c4518266f49ef93b1a936efdffde2145e64156/public/screenshots/profile.jpg -------------------------------------------------------------------------------- /public/screenshots/signin.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/x-ploration-of-mars/x-stack/38c4518266f49ef93b1a936efdffde2145e64156/public/screenshots/signin.jpg -------------------------------------------------------------------------------- /public/screenshots/x.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/x-ploration-of-mars/x-stack/38c4518266f49ef93b1a936efdffde2145e64156/public/screenshots/x.jpg -------------------------------------------------------------------------------- /src/components/auth/signin.tsx: -------------------------------------------------------------------------------- 1 | import { component$ } from "@builder.io/qwik"; 2 | import { Form } from "@builder.io/qwik-city"; 3 | import { useAuthSignin } from "~/routes/plugin@auth"; 4 | 5 | import Button from "../ui/button"; 6 | import { LuGamepad2 } from "@qwikest/icons/lucide"; 7 | 8 | export default component$(() => { 9 | const signIn = useAuthSignin(); 10 | 11 | return ( 12 |
13 | 14 | 15 | 18 |
19 | ); 20 | }); 21 | -------------------------------------------------------------------------------- /src/components/auth/signout.tsx: -------------------------------------------------------------------------------- 1 | import { component$ } from "@builder.io/qwik"; 2 | import { Form } from "@builder.io/qwik-city"; 3 | import { useAuthSignout } from "~/routes/plugin@auth"; 4 | import Button from "../ui/button"; 5 | import { LuLogOut } from "@qwikest/icons/lucide"; 6 | 7 | export default component$(() => { 8 | const signout = useAuthSignout(); 9 | return ( 10 |
11 | 12 | 19 |
20 | ); 21 | }); 22 | -------------------------------------------------------------------------------- /src/components/partytown/partytown.tsx: -------------------------------------------------------------------------------- 1 | import { partytownSnippet, type PartytownConfig } from "@builder.io/partytown/integration"; 2 | 3 | /** 4 | * Props for ``, which extends the Partytown Config. 5 | * 6 | * https://github.com/BuilderIO/partytown#config 7 | * 8 | * @public 9 | */ 10 | export interface PartytownProps extends PartytownConfig {} 11 | 12 | /** 13 | * @public 14 | * You can pass setting with props 15 | */ 16 | export const QwikPartytown = (props: PartytownProps): any => { 17 | return