├── .husky ├── pre-commit └── pre-push ├── src ├── App.css ├── components │ ├── ui │ │ ├── aspect-ratio.tsx │ │ ├── skeleton.tsx │ │ ├── collapsible.tsx │ │ ├── kbd.tsx │ │ ├── textarea.tsx │ │ ├── label.tsx │ │ ├── input.tsx │ │ ├── progress.tsx │ │ ├── separator.tsx │ │ ├── toaster.tsx │ │ ├── sonner.tsx │ │ ├── checkbox.tsx │ │ ├── slider.tsx │ │ ├── switch.tsx │ │ ├── badge.tsx │ │ ├── hover-card.tsx │ │ ├── popover.tsx │ │ ├── tooltip.tsx │ │ ├── popover-with-arrow.tsx │ │ ├── toggle.tsx │ │ ├── avatar.tsx │ │ ├── radio-group.tsx │ │ ├── scroll-area.tsx │ │ ├── alert.tsx │ │ ├── resizable.tsx │ │ ├── toggle-group.tsx │ │ ├── tabs.tsx │ │ ├── button.tsx │ │ ├── accordion.tsx │ │ ├── card.tsx │ │ ├── input-otp.tsx │ │ ├── calendar.tsx │ │ ├── breadcrumb.tsx │ │ ├── pagination.tsx │ │ ├── table.tsx │ │ └── drawer.tsx │ ├── icons │ │ ├── MySQLIcon.tsx │ │ ├── MSSQLIcon.tsx │ │ ├── SQLiteIcon.tsx │ │ ├── PostgreSQLIcon.tsx │ │ ├── DatabaseTypeIcon.tsx │ │ ├── PostgreSQL-Logo.wine.svg │ │ ├── DjangoIcon.tsx │ │ ├── TypeOrmIcon.tsx │ │ └── Django.svg │ ├── theme-provider.tsx │ ├── StoreInitializer.tsx │ ├── LoadingSpinner.tsx │ ├── AppIntro.tsx │ ├── theme-toggle.tsx │ ├── PWAStatus.tsx │ ├── Features.tsx │ ├── WhatsNewDialog.tsx │ ├── PWAUpdateNotification.tsx │ ├── AboutDialog.tsx │ ├── AddNoteDialog.tsx │ ├── AddTableDialog.tsx │ ├── EditNoteDialog.tsx │ ├── ColorPicker.tsx │ ├── ShortcutsDialog.tsx │ ├── RenameDiagramDialog.tsx │ ├── AddElementDialog.tsx │ ├── LoadProjectDialog.tsx │ ├── DiagramLayout.tsx │ ├── PWAInstallPrompt.tsx │ ├── NoteNode.tsx │ └── AddZoneDialog.tsx ├── vite-env.d.ts ├── pages │ ├── Index.tsx │ └── NotFound.tsx ├── utils │ ├── toast.ts │ └── pwaUtils.ts ├── hooks │ ├── use-mobile.tsx │ ├── use-sidebar-state.ts │ └── usePWA.ts ├── lib │ ├── importer.ts │ ├── constants.ts │ ├── db-types.ts │ ├── colors.ts │ ├── mermaid.ts │ ├── codegen │ │ ├── typeorm │ │ │ └── typeorm-helpers.ts │ │ └── laravel │ │ │ └── laravel-helpers.ts │ ├── db.ts │ ├── backup.ts │ └── types.ts ├── main.tsx ├── App.tsx └── globals.css ├── image1.png ├── image2.png ├── public ├── favicon.ico ├── apple-touch-icon.png ├── ThothBlueprint-icon.png ├── android-chrome-192x192.png ├── android-chrome-512x512.png ├── robots.txt ├── browserconfig.xml ├── offline.html ├── ThothBlueprint-icon.svg ├── placeholder.svg └── whats-new.md ├── postcss.config.js ├── docker-compose.yml ├── vercel.json ├── .gitignore ├── components.json ├── tsconfig.node.json ├── tsconfig.json ├── .dockerignore ├── .github ├── pull_request_template.md ├── workflows │ └── build_test.yml └── ISSUE_TEMPLATE │ ├── feature_request.yml │ └── bug_report.yml ├── Dockerfile ├── AI_RULES.md ├── tsconfig.app.json ├── eslint.config.js ├── index.html ├── nginx.conf ├── docs └── VERSIONING.md ├── tailwind.config.ts ├── vite.config.ts ├── CONTRIBUTING.md └── package.json /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | pnpm lint -------------------------------------------------------------------------------- /.husky/pre-push: -------------------------------------------------------------------------------- 1 | pnpm build -------------------------------------------------------------------------------- /src/App.css: -------------------------------------------------------------------------------- 1 | /* Default styles removed for full-screen layout */ -------------------------------------------------------------------------------- /image1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AHS12/thoth-blueprint/HEAD/image1.png -------------------------------------------------------------------------------- /image2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AHS12/thoth-blueprint/HEAD/image2.png -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AHS12/thoth-blueprint/HEAD/public/favicon.ico -------------------------------------------------------------------------------- /public/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AHS12/thoth-blueprint/HEAD/public/apple-touch-icon.png -------------------------------------------------------------------------------- /public/ThothBlueprint-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AHS12/thoth-blueprint/HEAD/public/ThothBlueprint-icon.png -------------------------------------------------------------------------------- /public/android-chrome-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AHS12/thoth-blueprint/HEAD/public/android-chrome-192x192.png -------------------------------------------------------------------------------- /public/android-chrome-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AHS12/thoth-blueprint/HEAD/public/android-chrome-512x512.png -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | export default { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | }; 7 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | services: 2 | thothblueprint: 3 | build: . 4 | ports: 5 | - "8080:80" 6 | restart: unless-stopped 7 | environment: 8 | - NODE_ENV=production -------------------------------------------------------------------------------- /src/components/ui/aspect-ratio.tsx: -------------------------------------------------------------------------------- 1 | import * as AspectRatioPrimitive from "@radix-ui/react-aspect-ratio"; 2 | 3 | const AspectRatio = AspectRatioPrimitive.Root; 4 | 5 | export { AspectRatio }; 6 | -------------------------------------------------------------------------------- /vercel.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://openapi.vercel.sh/vercel.json", 3 | "rewrites": [ 4 | { 5 | "source": "/(.*)", 6 | "destination": "/index.html" 7 | } 8 | ] 9 | } 10 | -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | User-agent: Googlebot 2 | Allow: / 3 | 4 | User-agent: Bingbot 5 | Allow: / 6 | 7 | User-agent: Twitterbot 8 | Allow: / 9 | 10 | User-agent: facebookexternalhit 11 | Allow: / 12 | 13 | User-agent: * 14 | Allow: / 15 | -------------------------------------------------------------------------------- /public/browserconfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | #ffffff 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/components/icons/MySQLIcon.tsx: -------------------------------------------------------------------------------- 1 | interface MySQLIconProps { 2 | className?: string; 3 | } 4 | 5 | import MySQLLogo from "./MySQL-Logo.wine.svg"; 6 | 7 | export function MySQLIcon({ className = "h-6 w-auto" }: MySQLIconProps) { 8 | return MySQL; 9 | } -------------------------------------------------------------------------------- /src/components/icons/MSSQLIcon.tsx: -------------------------------------------------------------------------------- 1 | interface MSSQLIconProps { 2 | className?: string; 3 | } 4 | 5 | import MSSQLLogo from "./mssql.svg"; 6 | 7 | export function MSSQLIcon({ className = "h-6 w-auto" }: MSSQLIconProps) { 8 | return Microsoft SQL Server; 9 | } -------------------------------------------------------------------------------- /src/components/icons/SQLiteIcon.tsx: -------------------------------------------------------------------------------- 1 | interface SQLiteIconProps { 2 | className?: string; 3 | } 4 | 5 | import SQLiteLogo from "./SQLite-Logo.wine.svg"; 6 | 7 | export function SQLiteIcon({ className = "h-6 w-auto" }: SQLiteIconProps) { 8 | return SQLite; 9 | } -------------------------------------------------------------------------------- /src/components/theme-provider.tsx: -------------------------------------------------------------------------------- 1 | import { ThemeProvider as NextThemesProvider } from "next-themes" 2 | import { type ThemeProviderProps } from "next-themes/dist/types" 3 | 4 | export function ThemeProvider({ children, ...props }: ThemeProviderProps) { 5 | return {children} 6 | } -------------------------------------------------------------------------------- /src/components/icons/PostgreSQLIcon.tsx: -------------------------------------------------------------------------------- 1 | interface PostgreSQLIconProps { 2 | className?: string; 3 | } 4 | 5 | import PostgresLogo from "./PostgreSQL-Logo.wine.svg"; 6 | 7 | export function PostgreSQLIcon({ className = "h-6 w-auto" }: PostgreSQLIconProps) { 8 | return PostgreSQL; 9 | } -------------------------------------------------------------------------------- /src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | 4 | declare const __APP_VERSION__: string; 5 | declare const __GIT_HASH__: string; 6 | 7 | interface Window { 8 | updateSW: (reloadPage?: boolean) => Promise; 9 | } 10 | 11 | interface Navigator { 12 | standalone?: boolean; 13 | } -------------------------------------------------------------------------------- /src/components/ui/skeleton.tsx: -------------------------------------------------------------------------------- 1 | import { cn } from "@/lib/utils"; 2 | 3 | function Skeleton({ 4 | className, 5 | ...props 6 | }: React.HTMLAttributes) { 7 | return ( 8 |
12 | ); 13 | } 14 | 15 | export { Skeleton }; 16 | -------------------------------------------------------------------------------- /src/components/ui/collapsible.tsx: -------------------------------------------------------------------------------- 1 | import * as CollapsiblePrimitive from "@radix-ui/react-collapsible"; 2 | 3 | const Collapsible = CollapsiblePrimitive.Root; 4 | 5 | const CollapsibleTrigger = CollapsiblePrimitive.CollapsibleTrigger; 6 | 7 | const CollapsibleContent = CollapsiblePrimitive.CollapsibleContent; 8 | 9 | export { Collapsible, CollapsibleTrigger, CollapsibleContent }; 10 | -------------------------------------------------------------------------------- /src/pages/Index.tsx: -------------------------------------------------------------------------------- 1 | import Layout from "@/components/Layout"; 2 | 3 | interface IndexProps { 4 | onInstallAppRequest: () => void; 5 | } 6 | 7 | const Index = ({ onInstallAppRequest }: IndexProps) => { 8 | return ( 9 |
10 | 11 |
12 | ); 13 | }; 14 | 15 | export default Index; -------------------------------------------------------------------------------- /.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 | 25 | 26 | *.sw? 27 | dev-dist 28 | .qwen 29 | -------------------------------------------------------------------------------- /src/utils/toast.ts: -------------------------------------------------------------------------------- 1 | import { toast } from "sonner"; 2 | 3 | export const showSuccess = (message: string) => { 4 | toast.success(message); 5 | }; 6 | 7 | export const showError = (message: string) => { 8 | toast.error(message); 9 | }; 10 | 11 | export const showLoading = (message: string) => { 12 | return toast.loading(message); 13 | }; 14 | 15 | export const dismissToast = (toastId: string) => { 16 | toast.dismiss(toastId); 17 | }; 18 | -------------------------------------------------------------------------------- /src/components/StoreInitializer.tsx: -------------------------------------------------------------------------------- 1 | import { useStore } from "@/store/store"; 2 | import { useEffect, useState } from "react"; 3 | 4 | export function StoreInitializer() { 5 | const [initialized, setInitialized] = useState(false); 6 | const loadInitialData = useStore((s) => s.loadInitialData); 7 | 8 | useEffect(() => { 9 | if (!initialized) { 10 | loadInitialData(); 11 | setInitialized(true); 12 | } 13 | }, [initialized, loadInitialData]); 14 | 15 | return null; 16 | } -------------------------------------------------------------------------------- /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.ts", 8 | "css": "src/index.css", 9 | "baseColor": "slate", 10 | "cssVariables": true, 11 | "prefix": "" 12 | }, 13 | "aliases": { 14 | "components": "@/components", 15 | "utils": "@/lib/utils", 16 | "ui": "@/components/ui", 17 | "lib": "@/lib", 18 | "hooks": "@/hooks" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /tsconfig.node.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2022", 4 | "lib": ["ES2023"], 5 | "module": "ESNext", 6 | "skipLibCheck": true, 7 | 8 | /* Bundler mode */ 9 | "moduleResolution": "bundler", 10 | "allowImportingTsExtensions": true, 11 | "isolatedModules": true, 12 | "moduleDetection": "force", 13 | "noEmit": true, 14 | 15 | /* Linting */ 16 | "strict": true, 17 | "noUnusedLocals": false, 18 | "noUnusedParameters": false, 19 | "noFallthroughCasesInSwitch": true 20 | }, 21 | "include": ["vite.config.ts"] 22 | } 23 | -------------------------------------------------------------------------------- /src/components/icons/DatabaseTypeIcon.tsx: -------------------------------------------------------------------------------- 1 | import { type DatabaseType } from "@/lib/types"; 2 | import { MySQLIcon } from "./MySQLIcon"; 3 | import { PostgreSQLIcon } from "./PostgreSQLIcon"; 4 | 5 | interface DatabaseTypeIconProps { 6 | dbType: DatabaseType; 7 | className?: string; 8 | } 9 | 10 | export function DatabaseTypeIcon({ dbType, className = "h-4 w-auto" }: DatabaseTypeIconProps) { 11 | switch (dbType) { 12 | case "mysql": 13 | return ; 14 | case "postgres": 15 | return ; 16 | default: 17 | return null; 18 | } 19 | } -------------------------------------------------------------------------------- /src/components/ui/kbd.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react" 2 | import { cn } from "@/lib/utils" 3 | 4 | const Kbd = React.forwardRef>( 5 | ({ className, ...props }, ref) => { 6 | return ( 7 | 15 | ) 16 | } 17 | ) 18 | Kbd.displayName = "Kbd" 19 | 20 | export { Kbd } -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "files": [], 3 | "references": [ 4 | { "path": "./tsconfig.app.json" }, 5 | { "path": "./tsconfig.node.json" } 6 | ], 7 | "compilerOptions": { 8 | "baseUrl": ".", 9 | "paths": { 10 | "@/*": ["./src/*"] 11 | }, 12 | "strict": true, 13 | "noImplicitAny": true, 14 | "noUnusedParameters": true, 15 | "skipLibCheck": true, 16 | "allowJs": false, 17 | "noUnusedLocals": true, 18 | "strictNullChecks": true, 19 | "noImplicitReturns": true, 20 | "noFallthroughCasesInSwitch": true, 21 | "noUncheckedIndexedAccess": true 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | # Dependencies 2 | node_modules 3 | 4 | # Build outputs 5 | dist 6 | build 7 | 8 | # Environment files 9 | .env 10 | .env.local 11 | .env.production.local 12 | 13 | # Logs 14 | logs 15 | *.log 16 | 17 | # Runtime data 18 | pids 19 | *.pid 20 | 21 | # IDE and editor files 22 | .idea 23 | .vscode 24 | *.swp 25 | *.swo 26 | *~ 27 | .DS_Store 28 | 29 | # Git files 30 | .git 31 | .gitignore 32 | 33 | # Testing 34 | coverage 35 | 36 | # Package lock files 37 | package-lock.json 38 | yarn.lock 39 | 40 | # Docker files (optional - uncomment if you want to exclude them) 41 | # Dockerfile 42 | # docker-compose.yml 43 | # .dockerignore 44 | 45 | # OS generated files 46 | Thumbs.db -------------------------------------------------------------------------------- /src/hooks/use-mobile.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | 3 | const MOBILE_BREAKPOINT = 768; 4 | 5 | export function useIsMobile() { 6 | const [isMobile, setIsMobile] = React.useState( 7 | undefined, 8 | ); 9 | 10 | React.useEffect(() => { 11 | const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`); 12 | const onChange = () => { 13 | setIsMobile(window.innerWidth < MOBILE_BREAKPOINT); 14 | }; 15 | mql.addEventListener("change", onChange); 16 | setIsMobile(window.innerWidth < MOBILE_BREAKPOINT); 17 | return () => mql.removeEventListener("change", onChange); 18 | }, []); 19 | 20 | return !!isMobile; 21 | } 22 | -------------------------------------------------------------------------------- /src/components/LoadingSpinner.tsx: -------------------------------------------------------------------------------- 1 | import { Loader2 } from 'lucide-react'; 2 | 3 | export const LoadingSpinner = () => { 4 | return ( 5 |
6 |
7 |
8 | ThothBlueprint Logo 13 | 14 |
15 |

LOADING

16 |
17 |
18 | ); 19 | }; -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | ## Description 2 | 3 | Brief summary of changes and motivation. 4 | 5 | Fixes # (issue) 6 | 7 | ## Type of Change 8 | 9 | - [ ] Bug fix 10 | - [ ] New feature 11 | - [ ] Breaking change 12 | - [ ] Documentation update 13 | 14 | ## Testing 15 | 16 | - [ ] Tests added/updated 17 | - [ ] All tests pass locally 18 | - [ ] Tested on multiple browsers (Chrome, Firefox, Safari, Edge) 19 | 20 | **Test Environment:** 21 | - Browser: 22 | - OS: 23 | 24 | ## Checklist 25 | 26 | - [ ] Code follows project style 27 | - [ ] Self-reviewed code 28 | - [ ] Updated documentation 29 | - [ ] Backward compatible (or breaking change documented) 30 | - [ ] No new warnings/errors 31 | 32 | ## Additional Notes 33 | 34 | Any extra context or screenshots. -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # Multi-stage Dockerfile for ThothBlueprint 2 | 3 | # Build stage 4 | FROM node:20-alpine AS builder 5 | 6 | # Set working directory 7 | WORKDIR /app 8 | 9 | # Copy package files 10 | COPY package.json pnpm-lock.yaml ./ 11 | 12 | # Install pnpm globally and dependencies 13 | RUN npm install -g pnpm && \ 14 | pnpm install --frozen-lockfile 15 | 16 | # Copy all source code 17 | COPY . . 18 | 19 | # Build the application 20 | RUN pnpm run build 21 | 22 | # Production stage 23 | FROM nginx:alpine AS production 24 | 25 | # Copy built files from builder stage 26 | COPY --from=builder /app/dist /usr/share/nginx/html 27 | 28 | # Copy custom nginx configuration 29 | COPY nginx.conf /etc/nginx/nginx.conf 30 | 31 | # Expose port 32 | EXPOSE 80 33 | 34 | # Start nginx 35 | CMD ["nginx", "-g", "daemon off;"] -------------------------------------------------------------------------------- /src/components/AppIntro.tsx: -------------------------------------------------------------------------------- 1 | export const AppIntro = () => { 2 | return ( 3 |
4 |

ThothBlueprint

5 |
6 | ThothBlueprint Logo 7 |

8 | Visualize your database schema with our intuitive drag-and-drop editor. When you're done, export your design to SQL, DBML, JSON, SVG, or generate migration files for frameworks like Laravel, TypeORM, and Django. Get started by creating a new diagram. 9 |

10 |
11 |
12 | ); 13 | }; -------------------------------------------------------------------------------- /src/components/ui/textarea.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | 3 | import { cn } from "@/lib/utils"; 4 | 5 | const Textarea = React.forwardRef>( 6 | ({ className, ...props }, ref) => { 7 | return ( 8 |