├── pnpm-workspace.yaml ├── www ├── public │ └── images │ │ ├── ao-domain.png │ │ └── dubco-domain.png ├── content │ └── docs │ │ ├── custom-domain.mdx │ │ ├── index.mdx │ │ └── real-world-examples.mdx ├── postcss.config.mjs ├── app │ ├── api │ │ └── search │ │ │ └── route.ts │ ├── (home) │ │ ├── layout.tsx │ │ ├── components.tsx │ │ └── page.tsx │ ├── docs │ │ ├── layout.tsx │ │ ├── custom-domain │ │ │ ├── copy-button.tsx │ │ │ └── page.tsx │ │ └── [[...slug]] │ │ │ └── page.tsx │ ├── layout.tsx │ ├── layout.config.tsx │ ├── providers.tsx │ └── globals.css ├── lib │ ├── utils.ts │ └── source.ts ├── source.config.ts ├── components.json ├── next.config.mjs ├── tsconfig.json ├── components │ ├── ui │ │ ├── label.tsx │ │ ├── textarea.tsx │ │ ├── input.tsx │ │ ├── checkbox.tsx │ │ ├── button.tsx │ │ ├── tabs.tsx │ │ ├── card.tsx │ │ └── form.tsx │ └── domains │ │ ├── actions.ts │ │ └── client.tsx ├── package.json └── tailwind.config.ts ├── package.json ├── kit ├── postcss.config.mjs ├── src │ ├── lib │ │ └── utils.tsx │ ├── components │ │ └── ui │ │ │ ├── label.tsx │ │ │ ├── textarea.tsx │ │ │ ├── input.tsx │ │ │ ├── button.tsx │ │ │ ├── tabs.tsx │ │ │ ├── card.tsx │ │ │ └── form.tsx │ └── domains │ │ ├── actions.ts │ │ └── client.tsx ├── components.json ├── tsconfig.json ├── package.json ├── globals.css └── tailwind.config.ts ├── biome.json ├── .gitignore ├── LICENSE └── README.md /pnpm-workspace.yaml: -------------------------------------------------------------------------------- 1 | packages: 2 | - kit 3 | - www 4 | -------------------------------------------------------------------------------- /www/public/images/ao-domain.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RhysSullivan/tenant-kit/HEAD/www/public/images/ao-domain.png -------------------------------------------------------------------------------- /www/public/images/dubco-domain.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RhysSullivan/tenant-kit/HEAD/www/public/images/dubco-domain.png -------------------------------------------------------------------------------- /www/content/docs/custom-domain.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Custom Domain 3 | description: Set up a custom domain for your tenant 4 | --- 5 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "tenant-kit", 3 | "version": "0.1.0", 4 | "private": true, 5 | "devDependencies": { 6 | "@biomejs/biome": "1.9.4" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /kit/postcss.config.mjs: -------------------------------------------------------------------------------- 1 | /** @type {import('postcss-load-config').Config} */ 2 | const config = { 3 | plugins: { 4 | tailwindcss: {}, 5 | }, 6 | }; 7 | 8 | export default config; 9 | -------------------------------------------------------------------------------- /www/postcss.config.mjs: -------------------------------------------------------------------------------- 1 | /** @type {import('postcss-load-config').Config} */ 2 | const config = { 3 | plugins: { 4 | tailwindcss: {}, 5 | }, 6 | }; 7 | 8 | export default config; 9 | -------------------------------------------------------------------------------- /www/app/api/search/route.ts: -------------------------------------------------------------------------------- 1 | import { source } from "@/lib/source"; 2 | import { createFromSource } from "fumadocs-core/search/server"; 3 | 4 | export const { GET } = createFromSource(source); 5 | -------------------------------------------------------------------------------- /www/lib/utils.ts: -------------------------------------------------------------------------------- 1 | import { type ClassValue, clsx } from "clsx"; 2 | import { twMerge } from "tailwind-merge"; 3 | export function cn(...inputs: ClassValue[]) { 4 | return twMerge(clsx(inputs)); 5 | } 6 | -------------------------------------------------------------------------------- /kit/src/lib/utils.tsx: -------------------------------------------------------------------------------- 1 | import { type ClassValue, clsx } from "clsx"; 2 | import { twMerge } from "tailwind-merge"; 3 | export function cn(...inputs: ClassValue[]) { 4 | return twMerge(clsx(inputs)); 5 | } 6 | -------------------------------------------------------------------------------- /www/source.config.ts: -------------------------------------------------------------------------------- 1 | import { defineDocs, defineConfig } from "fumadocs-mdx/config"; 2 | 3 | export const { docs, meta } = defineDocs({ 4 | dir: "content/docs", 5 | }); 6 | 7 | export default defineConfig(); 8 | -------------------------------------------------------------------------------- /www/content/docs/index.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Introduction 3 | description: Introduction to Tenant Kit 4 | --- 5 | 6 | These are very WIP docs, check out the [Custom Domain Component](/docs/custom-domain) for the first component to get started. -------------------------------------------------------------------------------- /www/lib/source.ts: -------------------------------------------------------------------------------- 1 | import { docs, meta } from "@/.source"; 2 | import { createMDXSource } from "fumadocs-mdx"; 3 | import { loader } from "fumadocs-core/source"; 4 | 5 | export const source = loader({ 6 | baseUrl: "/docs", 7 | source: createMDXSource(docs, meta), 8 | }); 9 | -------------------------------------------------------------------------------- /www/app/(home)/layout.tsx: -------------------------------------------------------------------------------- 1 | import type { ReactNode } from "react"; 2 | import { HomeLayout } from "fumadocs-ui/layouts/home"; 3 | import { baseOptions } from "@/app/layout.config"; 4 | 5 | export default function Layout({ 6 | children, 7 | }: { 8 | children: ReactNode; 9 | }): React.ReactElement { 10 | return {children}; 11 | } 12 | -------------------------------------------------------------------------------- /kit/components.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://ui.shadcn.com/schema.json", 3 | "style": "default", 4 | "rsc": true, 5 | "tsx": true, 6 | "tailwind": { 7 | "config": "tailwind.config.ts", 8 | "css": "./globals.css", 9 | "baseColor": "slate", 10 | "cssVariables": true, 11 | "prefix": "" 12 | }, 13 | "aliases": { 14 | "components": "@/components", 15 | "utils": "@/lib/utils" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /www/components.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://ui.shadcn.com/schema.json", 3 | "style": "default", 4 | "rsc": true, 5 | "tsx": true, 6 | "tailwind": { 7 | "config": "tailwind.config.ts", 8 | "css": "./app/globals.css", 9 | "baseColor": "slate", 10 | "cssVariables": true, 11 | "prefix": "" 12 | }, 13 | "aliases": { 14 | "components": "@/components", 15 | "utils": "@/lib/utils" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /www/app/docs/layout.tsx: -------------------------------------------------------------------------------- 1 | import { DocsLayout } from "fumadocs-ui/layouts/docs"; 2 | import type { ReactNode } from "react"; 3 | import { baseOptions } from "@/app/layout.config"; 4 | import { source } from "@/lib/source"; 5 | 6 | export default function Layout({ children }: { children: ReactNode }) { 7 | return ( 8 | 9 | {children} 10 | 11 | ); 12 | } 13 | -------------------------------------------------------------------------------- /www/next.config.mjs: -------------------------------------------------------------------------------- 1 | import { createMDX } from "fumadocs-mdx/next"; 2 | 3 | const withMDX = createMDX(); 4 | 5 | /** @type {import('next').NextConfig} */ 6 | const config = { 7 | reactStrictMode: true, 8 | skipTrailingSlashRedirect: true, 9 | rewrites: async () => [ 10 | { 11 | source: "/ingest/static/:path*", 12 | destination: "https://us-assets.i.posthog.com/static/:path*", 13 | }, 14 | { 15 | source: "/ingest/:path*", 16 | destination: "https://us.i.posthog.com/:path*", 17 | }, 18 | ], 19 | }; 20 | 21 | export default withMDX(config); 22 | -------------------------------------------------------------------------------- /biome.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://biomejs.dev/schemas/1.9.4/schema.json", 3 | "vcs": { 4 | "enabled": true, 5 | "clientKind": "git", 6 | "useIgnoreFile": true 7 | }, 8 | "files": { 9 | "ignoreUnknown": false, 10 | "ignore": [] 11 | }, 12 | "formatter": { 13 | "enabled": true, 14 | "indentStyle": "tab" 15 | }, 16 | "organizeImports": { 17 | "enabled": true 18 | }, 19 | "linter": { 20 | "enabled": true, 21 | "rules": { 22 | "recommended": true 23 | } 24 | }, 25 | "javascript": { 26 | "formatter": { 27 | "quoteStyle": "double" 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /kit/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "lib": ["dom", "dom.iterable", "esnext"], 4 | "allowJs": true, 5 | "skipLibCheck": true, 6 | "strict": true, 7 | "noEmit": true, 8 | "esModuleInterop": true, 9 | "module": "esnext", 10 | "moduleResolution": "bundler", 11 | "resolveJsonModule": true, 12 | "isolatedModules": true, 13 | "jsx": "preserve", 14 | "incremental": true, 15 | "plugins": [ 16 | { 17 | "name": "next" 18 | } 19 | ], 20 | "paths": { 21 | "@/*": ["./src/*"] 22 | }, 23 | "types": ["node"] 24 | }, 25 | "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], 26 | "exclude": ["node_modules"] 27 | } 28 | -------------------------------------------------------------------------------- /www/app/layout.tsx: -------------------------------------------------------------------------------- 1 | import "./globals.css"; 2 | import { RootProvider } from "fumadocs-ui/provider"; 3 | import { Inter } from "next/font/google"; 4 | import type { ReactNode } from "react"; 5 | import Providers from "./providers"; 6 | 7 | const inter = Inter({ 8 | subsets: ["latin"], 9 | }); 10 | 11 | export default function Layout({ children }: { children: ReactNode }) { 12 | return ( 13 | 14 | 15 | 16 | {children} 17 | 18 | 19 | 20 | ); 21 | } 22 | -------------------------------------------------------------------------------- /www/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "baseUrl": ".", 4 | "target": "ESNext", 5 | "lib": ["dom", "dom.iterable", "esnext"], 6 | "allowJs": true, 7 | "skipLibCheck": true, 8 | "strict": true, 9 | "forceConsistentCasingInFileNames": true, 10 | "noEmit": true, 11 | "esModuleInterop": true, 12 | "module": "esnext", 13 | "moduleResolution": "bundler", 14 | "resolveJsonModule": true, 15 | "isolatedModules": true, 16 | "jsx": "preserve", 17 | "incremental": true, 18 | "paths": { 19 | "@/*": ["./*"], 20 | }, 21 | "plugins": [ 22 | { 23 | "name": "next" 24 | } 25 | ] 26 | }, 27 | "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], 28 | "exclude": ["node_modules"] 29 | } 30 | -------------------------------------------------------------------------------- /www/app/layout.config.tsx: -------------------------------------------------------------------------------- 1 | import type { BaseLayoutProps } from "fumadocs-ui/layouts/shared"; 2 | import { Globe } from "lucide-react"; 3 | 4 | /** 5 | * Shared layout configurations 6 | * 7 | * you can configure layouts individually from: 8 | * Home Layout: app/(home)/layout.tsx 9 | * Docs Layout: app/docs/layout.tsx 10 | */ 11 | export const baseOptions: BaseLayoutProps = { 12 | nav: { 13 | title: ( 14 |
15 | 16 | Tenant Kit 17 |
18 | ), 19 | }, 20 | githubUrl: "https://github.com/rhyssullivan/tenant-kit", 21 | links: [ 22 | { 23 | text: "Documentation", 24 | url: "/docs", 25 | active: "nested-url", 26 | }, 27 | ], 28 | }; 29 | -------------------------------------------------------------------------------- /kit/src/components/ui/label.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import * as React from "react"; 4 | import * as LabelPrimitive from "@radix-ui/react-label"; 5 | import { cva, type VariantProps } from "class-variance-authority"; 6 | 7 | import { cn } from "@/lib/utils"; 8 | 9 | const labelVariants = cva( 10 | "text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70", 11 | ); 12 | 13 | const Label = React.forwardRef< 14 | React.ElementRef, 15 | React.ComponentPropsWithoutRef & 16 | VariantProps 17 | >(({ className, ...props }, ref) => ( 18 | 23 | )); 24 | Label.displayName = LabelPrimitive.Root.displayName; 25 | 26 | export { Label }; 27 | -------------------------------------------------------------------------------- /www/components/ui/label.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import * as React from "react"; 4 | import * as LabelPrimitive from "@radix-ui/react-label"; 5 | import { cva, type VariantProps } from "class-variance-authority"; 6 | 7 | import { cn } from "@/lib/utils"; 8 | 9 | const labelVariants = cva( 10 | "text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70", 11 | ); 12 | 13 | const Label = React.forwardRef< 14 | React.ElementRef, 15 | React.ComponentPropsWithoutRef & 16 | VariantProps 17 | >(({ className, ...props }, ref) => ( 18 | 23 | )); 24 | Label.displayName = LabelPrimitive.Root.displayName; 25 | 26 | export { Label }; 27 | -------------------------------------------------------------------------------- /www/components/ui/textarea.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | 3 | import { cn } from "@/lib/utils"; 4 | 5 | export interface TextareaProps 6 | extends React.TextareaHTMLAttributes {} 7 | 8 | const Textarea = React.forwardRef( 9 | ({ className, ...props }, ref) => { 10 | return ( 11 |