├── .env.example ├── .eslintrc.cjs ├── .gitignore ├── README.md ├── bun.lockb ├── next.config.js ├── package.json ├── postcss.config.cjs ├── prettier.config.js ├── public └── favicon.ico ├── src ├── app │ ├── layout.tsx │ ├── page.tsx │ └── providers.tsx ├── env.js └── styles │ └── globals.css ├── tailwind.config.ts └── tsconfig.json /.env.example: -------------------------------------------------------------------------------- 1 | # Since the ".env" file is gitignored, you can use the ".env.example" file to 2 | # build a new ".env" file when you clone the repo. Keep this file up-to-date 3 | # when you add new variables to `.env`. 4 | 5 | # This file will be committed to version control, so make sure not to have any 6 | # secrets in it. If you are cloning this repo, create a copy of this file named 7 | # ".env" and populate it with your secrets. 8 | 9 | # When adding additional environment variables, the schema in "/src/env.js" 10 | # should be updated accordingly. 11 | 12 | # Example: 13 | # SERVERVAR="foo" 14 | # NEXT_PUBLIC_CLIENTVAR="bar" 15 | -------------------------------------------------------------------------------- /.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | /** @type {import("eslint").Linter.Config} */ 2 | const config = { 3 | parser: "@typescript-eslint/parser", 4 | parserOptions: { 5 | project: true, 6 | }, 7 | plugins: ["@typescript-eslint"], 8 | extends: [ 9 | "next/core-web-vitals", 10 | "plugin:@typescript-eslint/recommended-type-checked", 11 | "plugin:@typescript-eslint/stylistic-type-checked", 12 | ], 13 | rules: { 14 | // These opinionated rules are enabled in stylistic-type-checked above. 15 | // Feel free to reconfigure them to your own preference. 16 | "@typescript-eslint/array-type": "off", 17 | "@typescript-eslint/consistent-type-definitions": "off", 18 | 19 | "@typescript-eslint/consistent-type-imports": [ 20 | "warn", 21 | { 22 | prefer: "type-imports", 23 | fixStyle: "inline-type-imports", 24 | }, 25 | ], 26 | "@typescript-eslint/no-unused-vars": ["warn", { argsIgnorePattern: "^_" }], 27 | "@typescript-eslint/require-await": "off", 28 | "@typescript-eslint/no-misused-promises": [ 29 | "error", 30 | { 31 | checksVoidReturn: { attributes: false }, 32 | }, 33 | ], 34 | }, 35 | }; 36 | 37 | module.exports = config; 38 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # database 12 | /prisma/db.sqlite 13 | /prisma/db.sqlite-journal 14 | 15 | # next.js 16 | /.next/ 17 | /out/ 18 | next-env.d.ts 19 | 20 | # production 21 | /build 22 | 23 | # misc 24 | .DS_Store 25 | *.pem 26 | 27 | # debug 28 | npm-debug.log* 29 | yarn-debug.log* 30 | yarn-error.log* 31 | .pnpm-debug.log* 32 | 33 | # local env files 34 | # do not commit any .env files to git, except for the .env.example file. https://create.t3.gg/en/usage/env-variables#using-environment-variables 35 | .env 36 | .env*.local 37 | 38 | # vercel 39 | .vercel 40 | 41 | # typescript 42 | *.tsbuildinfo 43 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Hi 2 | 3 | Not accepting contributions (unless they're really good) 4 | -------------------------------------------------------------------------------- /bun.lockb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/t3dotgg/darkmode-tax/a4cfc5ce2cfb3d40e6644d7175d231285d0c5792/bun.lockb -------------------------------------------------------------------------------- /next.config.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Run `build` or `dev` with `SKIP_ENV_VALIDATION` to skip env validation. This is especially useful 3 | * for Docker builds. 4 | */ 5 | await import("./src/env.js"); 6 | 7 | import { withPlausibleProxy } from "next-plausible"; 8 | 9 | /** @type {import("next").NextConfig} */ 10 | const config = {}; 11 | 12 | export default withPlausibleProxy()(config); 13 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "darkmode-tax", 3 | "version": "0.1.0", 4 | "private": true, 5 | "type": "module", 6 | "scripts": { 7 | "build": "next build", 8 | "dev": "next dev", 9 | "lint": "next lint", 10 | "start": "next start" 11 | }, 12 | "dependencies": { 13 | "@t3-oss/env-nextjs": "^0.7.1", 14 | "next": "^14.0.4", 15 | "next-plausible": "^3.12.0", 16 | "react": "18.2.0", 17 | "react-dom": "18.2.0", 18 | "zod": "^3.22.4" 19 | }, 20 | "devDependencies": { 21 | "@types/eslint": "^8.44.7", 22 | "@types/node": "^18.17.0", 23 | "@types/react": "^18.2.37", 24 | "@types/react-dom": "^18.2.15", 25 | "@typescript-eslint/eslint-plugin": "^6.11.0", 26 | "@typescript-eslint/parser": "^6.11.0", 27 | "autoprefixer": "^10.4.14", 28 | "eslint": "^8.54.0", 29 | "eslint-config-next": "^14.0.4", 30 | "postcss": "^8.4.31", 31 | "prettier": "^3.1.0", 32 | "prettier-plugin-tailwindcss": "^0.5.7", 33 | "tailwindcss": "^3.3.5", 34 | "typescript": "^5.1.6" 35 | }, 36 | "ct3aMetadata": { 37 | "initVersion": "7.26.0" 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /postcss.config.cjs: -------------------------------------------------------------------------------- 1 | const config = { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | }; 7 | 8 | module.exports = config; 9 | -------------------------------------------------------------------------------- /prettier.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('prettier').Config & import('prettier-plugin-tailwindcss').PluginOptions} */ 2 | const config = { 3 | plugins: ["prettier-plugin-tailwindcss"], 4 | }; 5 | 6 | export default config; 7 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/t3dotgg/darkmode-tax/a4cfc5ce2cfb3d40e6644d7175d231285d0c5792/public/favicon.ico -------------------------------------------------------------------------------- /src/app/layout.tsx: -------------------------------------------------------------------------------- 1 | import "~/styles/globals.css"; 2 | 3 | import { Open_Sans } from "next/font/google"; 4 | import Providers from "./providers"; 5 | 6 | const openSans = Open_Sans({ 7 | subsets: ["latin"], 8 | variable: "--font-sans", 9 | }); 10 | 11 | export const metadata = { 12 | title: "The Dark Mode Wall Of Shame", 13 | description: 14 | "A list of vendors that treat dark mode as a luxury feature, not a core security requirement.", 15 | icons: [{ rel: "icon", url: "/favicon.ico" }], 16 | }; 17 | 18 | export default function RootLayout({ 19 | children, 20 | }: { 21 | children: React.ReactNode; 22 | }) { 23 | return ( 24 | 25 | 26 | {children} 27 | 28 | 29 | ); 30 | } 31 | -------------------------------------------------------------------------------- /src/app/page.tsx: -------------------------------------------------------------------------------- 1 | export default function HomePage() { 2 | return ( 3 | <> 4 |
5 |

Dark Mode Wall Of Shame

6 |

7 | A list of vendors that treat dark mode as a luxury feature, not a core 8 | security requirement. 9 |

10 |
11 |
12 | 13 | It's literally just{" "} 14 | 18 | UploadThing 19 | 20 | 21 | 22 | (btw, dark mode is{" "} 23 | 27 | not an accessibility feature 28 | 29 | ) 30 | 31 |
32 | 33 | ); 34 | } 35 | -------------------------------------------------------------------------------- /src/app/providers.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import PlausibleProvider from "next-plausible"; 4 | 5 | export default function Providers({ children }: { children: React.ReactNode }) { 6 | return ( 7 | {children} 8 | ); 9 | } 10 | -------------------------------------------------------------------------------- /src/env.js: -------------------------------------------------------------------------------- 1 | import { createEnv } from "@t3-oss/env-nextjs"; 2 | import { z } from "zod"; 3 | 4 | export const env = createEnv({ 5 | /** 6 | * Specify your server-side environment variables schema here. This way you can ensure the app 7 | * isn't built with invalid env vars. 8 | */ 9 | server: { 10 | NODE_ENV: z.enum(["development", "test", "production"]), 11 | }, 12 | 13 | /** 14 | * Specify your client-side environment variables schema here. This way you can ensure the app 15 | * isn't built with invalid env vars. To expose them to the client, prefix them with 16 | * `NEXT_PUBLIC_`. 17 | */ 18 | client: { 19 | // NEXT_PUBLIC_CLIENTVAR: z.string(), 20 | }, 21 | 22 | /** 23 | * You can't destruct `process.env` as a regular object in the Next.js edge runtimes (e.g. 24 | * middlewares) or client-side so we need to destruct manually. 25 | */ 26 | runtimeEnv: { 27 | NODE_ENV: process.env.NODE_ENV, 28 | // NEXT_PUBLIC_CLIENTVAR: process.env.NEXT_PUBLIC_CLIENTVAR, 29 | }, 30 | /** 31 | * Run `build` or `dev` with `SKIP_ENV_VALIDATION` to skip env validation. This is especially 32 | * useful for Docker builds. 33 | */ 34 | skipValidation: !!process.env.SKIP_ENV_VALIDATION, 35 | /** 36 | * Makes it so that empty strings are treated as undefined. `SOME_VAR: z.string()` and 37 | * `SOME_VAR=''` will throw an error. 38 | */ 39 | emptyStringAsUndefined: true, 40 | }); 41 | -------------------------------------------------------------------------------- /src/styles/globals.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | 5 | body { 6 | @apply bg-black text-white; 7 | 8 | min-height: 100lvh; 9 | } 10 | 11 | .page-header { 12 | color: #fff; 13 | text-align: center; 14 | background-color: #159957; 15 | background-image: linear-gradient(120deg, #155799, #159957); 16 | } 17 | -------------------------------------------------------------------------------- /tailwind.config.ts: -------------------------------------------------------------------------------- 1 | import { type Config } from "tailwindcss"; 2 | import { fontFamily } from "tailwindcss/defaultTheme"; 3 | 4 | export default { 5 | content: ["./src/**/*.tsx"], 6 | theme: { 7 | extend: { 8 | fontFamily: { 9 | sans: ["var(--font-sans)", ...fontFamily.sans], 10 | }, 11 | }, 12 | }, 13 | plugins: [], 14 | } satisfies Config; 15 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | /* Base Options: */ 4 | "esModuleInterop": true, 5 | "skipLibCheck": true, 6 | "target": "es2022", 7 | "allowJs": true, 8 | "resolveJsonModule": true, 9 | "moduleDetection": "force", 10 | "isolatedModules": true, 11 | 12 | /* Strictness */ 13 | "strict": true, 14 | "noUncheckedIndexedAccess": true, 15 | "checkJs": true, 16 | 17 | /* Bundled projects */ 18 | "lib": ["dom", "dom.iterable", "ES2022"], 19 | "noEmit": true, 20 | "module": "ESNext", 21 | "moduleResolution": "Bundler", 22 | "jsx": "preserve", 23 | "plugins": [{ "name": "next" }], 24 | "incremental": true, 25 | 26 | /* Path Aliases */ 27 | "baseUrl": ".", 28 | "paths": { 29 | "~/*": ["./src/*"] 30 | } 31 | }, 32 | "include": [ 33 | ".eslintrc.cjs", 34 | "next-env.d.ts", 35 | "**/*.ts", 36 | "**/*.tsx", 37 | "**/*.cjs", 38 | "**/*.js", 39 | ".next/types/**/*.ts" 40 | ], 41 | "exclude": ["node_modules"] 42 | } 43 | --------------------------------------------------------------------------------