├── public ├── robots.txt └── logo.svg ├── src ├── vite-env.d.ts ├── lib │ ├── result.ts │ ├── utils.ts │ ├── openai.ts │ └── frameworks.ts ├── hooks │ ├── useQueryParams.ts │ └── useViewportHeight.ts ├── main.tsx ├── pages │ ├── _app.tsx │ ├── outline.tsx │ └── index.tsx ├── router.ts ├── components │ ├── footer.tsx │ ├── ui │ │ ├── label.tsx │ │ ├── textarea.tsx │ │ ├── separator.tsx │ │ ├── input.tsx │ │ ├── slider.tsx │ │ ├── badge.tsx │ │ ├── popover.tsx │ │ ├── button.tsx │ │ ├── table.tsx │ │ ├── autosize-textarea.tsx │ │ ├── dialog.tsx │ │ ├── select.tsx │ │ ├── command.tsx │ │ └── multiple-selector.tsx │ ├── select-model.tsx │ ├── github-icon.tsx │ ├── header.tsx │ ├── select-tone.tsx │ ├── table-title.tsx │ ├── editor.tsx │ └── select-frameworks.tsx ├── index.css ├── assets │ └── react.svg └── stores │ └── config-store.ts ├── bun.lockb ├── demo-app.png ├── vercel.json ├── postcss.config.js ├── tsconfig.node.json ├── .gitignore ├── vite.config.ts ├── components.json ├── index.html ├── .eslintrc.cjs ├── tsconfig.json ├── README.md ├── LICENSE ├── package.json └── tailwind.config.js /public/robots.txt: -------------------------------------------------------------------------------- 1 | User-agent: * 2 | Disallow: /_next -------------------------------------------------------------------------------- /src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /bun.lockb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ahmadrosid/TitleCrafters/HEAD/bun.lockb -------------------------------------------------------------------------------- /demo-app.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ahmadrosid/TitleCrafters/HEAD/demo-app.png -------------------------------------------------------------------------------- /vercel.json: -------------------------------------------------------------------------------- 1 | { 2 | "rewrites": [{ "source": "/(.*)", "destination": "/index.html" }] 3 | } -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | export default { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | } 7 | -------------------------------------------------------------------------------- /src/lib/result.ts: -------------------------------------------------------------------------------- 1 | export type Result = Error | T; 2 | 3 | export function isError(result: Result): result is Error { 4 | return result instanceof Error; 5 | } 6 | -------------------------------------------------------------------------------- /tsconfig.node.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "composite": true, 4 | "skipLibCheck": true, 5 | "module": "ESNext", 6 | "moduleResolution": "bundler", 7 | "allowSyntheticDefaultImports": true 8 | }, 9 | "include": ["vite.config.ts"] 10 | } 11 | -------------------------------------------------------------------------------- /src/hooks/useQueryParams.ts: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | import { useLocation } from "react-router-dom"; 4 | 5 | export function useQueryParams() { 6 | const { search } = useLocation(); 7 | 8 | return React.useMemo(() => new URLSearchParams(search), [search]); 9 | } 10 | -------------------------------------------------------------------------------- /public/logo.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/main.tsx: -------------------------------------------------------------------------------- 1 | import "./index.css"; 2 | import { enableMapSet } from "immer"; 3 | import { createRoot } from "react-dom/client"; 4 | import { Routes } from "@generouted/react-router/lazy"; 5 | enableMapSet(); 6 | 7 | const root = document.getElementById("root"); 8 | if (!root) throw new Error("No root element found"); 9 | createRoot(root).render(); 10 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | -------------------------------------------------------------------------------- /src/pages/_app.tsx: -------------------------------------------------------------------------------- 1 | import { Outlet } from "react-router-dom"; 2 | import { Toaster } from "react-hot-toast"; 3 | import { Header } from "@/components/header"; 4 | 5 | export default function App() { 6 | return ( 7 | <> 8 |
9 |
10 | 11 |
12 | 13 | 14 | ); 15 | } 16 | -------------------------------------------------------------------------------- /vite.config.ts: -------------------------------------------------------------------------------- 1 | import path from "path"; 2 | import react from "@vitejs/plugin-react"; 3 | import { defineConfig } from "vite"; 4 | import generouted from "@generouted/react-router/plugin"; 5 | 6 | export default defineConfig({ 7 | plugins: [react(), generouted()], 8 | resolve: { 9 | alias: { 10 | "@": path.resolve(__dirname, "./src"), 11 | }, 12 | }, 13 | }); 14 | -------------------------------------------------------------------------------- /components.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://ui.shadcn.com/schema.json", 3 | "style": "new-york", 4 | "rsc": false, 5 | "tsx": true, 6 | "tailwind": { 7 | "config": "tailwind.config.js", 8 | "css": "src/index.css", 9 | "baseColor": "gray", 10 | "cssVariables": true 11 | }, 12 | "aliases": { 13 | "components": "@/components", 14 | "utils": "@/lib/utils" 15 | } 16 | } -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Title Crafters - Craft the best title or headline for your article. 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /src/hooks/useViewportHeight.ts: -------------------------------------------------------------------------------- 1 | import { useEffect } from "react"; 2 | 3 | const useViewportHeight = () => { 4 | useEffect(() => { 5 | const handleResize = () => { 6 | const vh = window.innerHeight * 0.01; 7 | document.documentElement.style.setProperty("--vh", `${vh}px`); 8 | }; 9 | handleResize(); 10 | 11 | window.addEventListener("resize", handleResize); 12 | return () => window.removeEventListener("resize", handleResize); 13 | }, []); 14 | }; 15 | 16 | export default useViewportHeight; 17 | -------------------------------------------------------------------------------- /src/router.ts: -------------------------------------------------------------------------------- 1 | // Generouted, changes to this file will be overriden 2 | /* eslint-disable */ 3 | 4 | import { components, hooks, utils } from '@generouted/react-router/client' 5 | 6 | export type Path = 7 | | `/` 8 | | `/outline` 9 | 10 | export type Params = { 11 | 12 | } 13 | 14 | export type ModalPath = never 15 | 16 | export const { Link, Navigate } = components() 17 | export const { useModals, useNavigate, useParams } = hooks() 18 | export const { redirect } = utils() 19 | -------------------------------------------------------------------------------- /.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | env: { browser: true, es2020: true }, 4 | extends: [ 5 | "eslint:recommended", 6 | "plugin:@typescript-eslint/recommended", 7 | "plugin:react-hooks/recommended", 8 | ], 9 | ignorePatterns: ["dist", ".eslintrc.cjs"], 10 | parser: "@typescript-eslint/parser", 11 | plugins: ["react-refresh"], 12 | rules: { 13 | "react-refresh/only-export-components": [ 14 | "warn", 15 | { allowConstantExport: true }, 16 | ], 17 | "@typescript-eslint/no-explicit-any": "off", 18 | }, 19 | }; 20 | -------------------------------------------------------------------------------- /src/components/footer.tsx: -------------------------------------------------------------------------------- 1 | export function Footer() { 2 | return ( 3 | 26 | ); 27 | } 28 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2020", 4 | "useDefineForClassFields": true, 5 | "lib": ["ES2020", "DOM", "DOM.Iterable"], 6 | "module": "ESNext", 7 | "skipLibCheck": true, 8 | 9 | /* Bundler mode */ 10 | "moduleResolution": "bundler", 11 | "allowImportingTsExtensions": true, 12 | "resolveJsonModule": true, 13 | "isolatedModules": true, 14 | "noEmit": true, 15 | "jsx": "react-jsx", 16 | 17 | /* Linting */ 18 | "strict": true, 19 | "noUnusedLocals": true, 20 | "noUnusedParameters": true, 21 | "noFallthroughCasesInSwitch": true, 22 | 23 | "baseUrl": ".", 24 | "paths": { 25 | "@/*": ["./src/*"] 26 | } 27 | }, 28 | "include": ["src"], 29 | "references": [{ "path": "./tsconfig.node.json" }] 30 | } 31 | -------------------------------------------------------------------------------- /src/components/ui/label.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react" 2 | import * as LabelPrimitive from "@radix-ui/react-label" 3 | import { cva, type VariantProps } from "class-variance-authority" 4 | 5 | import { cn } from "@/lib/utils" 6 | 7 | const labelVariants = cva( 8 | "text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70" 9 | ) 10 | 11 | const Label = React.forwardRef< 12 | React.ElementRef, 13 | React.ComponentPropsWithoutRef & 14 | VariantProps 15 | >(({ className, ...props }, ref) => ( 16 | 21 | )) 22 | Label.displayName = LabelPrimitive.Root.displayName 23 | 24 | export { Label } 25 | -------------------------------------------------------------------------------- /src/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 |