├── .env.example ├── .eslintignore ├── .eslintrc.cjs ├── .gitignore ├── LICENSE ├── README.md ├── bun.lockb ├── components.json ├── content ├── ai-powered-diagrams.md ├── how-autodiagram-is-better.md └── intro-to-autodiagram.md ├── mdx-components.tsx ├── next.config.js ├── package.json ├── postcss.config.js ├── prettier.config.js ├── prisma ├── migrations │ ├── 20250206055701_dev │ │ └── migration.sql │ ├── 20250206201442_update │ │ └── migration.sql │ ├── 20250207092714_add_anonymous_id │ │ └── migration.sql │ ├── 20250208141523_credits │ │ └── migration.sql │ └── migration_lock.toml └── schema.prisma ├── public ├── Launch_SVG_Light.svg ├── about │ ├── ZenUML.svg │ ├── architecture.svg │ ├── block.svg │ ├── mindmap.svg │ ├── packet.svg │ ├── sankey.svg │ ├── timeline.svg │ └── xydiagram.svg ├── android-chrome-192x192.png ├── android-chrome-512x512.png ├── apple-touch-icon.png ├── blog │ ├── ai-powered-diagrams.png │ ├── android-chrome-512x512.png │ ├── authors │ │ └── autodiagram.png │ ├── how-autodiagram-is-better.png │ ├── intro-to-autodiagram.png │ ├── nextjs-guide.jpg │ └── og-image.png ├── favicon-16x16.png ├── favicon-32x32.png ├── favicon.ico ├── google-logo.svg ├── google.svg ├── landing │ ├── Group-998-1-(1).png │ ├── amazon.png │ ├── contact.png │ ├── cta.png │ ├── facebook.png │ ├── feature1.svg │ ├── feature2.png │ ├── google.png │ ├── microsoft.webp │ └── netflix.png ├── logo.png ├── site.webmanifest ├── vercel-logo.svg ├── video.mp4 └── videos │ ├── feature-2.mp4 │ └── feature-3.mp4 ├── src ├── app │ ├── (landing) │ │ ├── about │ │ │ └── page.tsx │ │ ├── blog │ │ │ ├── [slug] │ │ │ │ └── page.tsx │ │ │ ├── not-found.tsx │ │ │ └── page.tsx │ │ ├── contact │ │ │ └── page.tsx │ │ ├── features │ │ │ └── page.tsx │ │ ├── layout.tsx │ │ ├── page.tsx │ │ ├── pricing │ │ │ └── page.tsx │ │ ├── privacy │ │ │ └── page.tsx │ │ └── terms │ │ │ └── page.tsx │ ├── _components │ │ ├── auth-button.tsx │ │ ├── blogs │ │ │ ├── avatar.tsx │ │ │ ├── container.tsx │ │ │ ├── cover-image.tsx │ │ │ ├── date-formatter.tsx │ │ │ ├── header.tsx │ │ │ ├── hero-post.tsx │ │ │ ├── intro.tsx │ │ │ ├── markdown-styles.module.css │ │ │ ├── more-stories.tsx │ │ │ ├── post-body.tsx │ │ │ ├── post-header.tsx │ │ │ ├── post-preview.tsx │ │ │ ├── post-title.tsx │ │ │ └── post.tsx │ │ ├── diagram-download-button.tsx │ │ ├── diagram-generator.tsx │ │ ├── diagram-history.tsx │ │ ├── diagram-preview-card.tsx │ │ ├── diagram │ │ │ ├── diagram-controls.tsx │ │ │ ├── diagram-editor.tsx │ │ │ ├── diagram-generator-form.tsx │ │ │ ├── diagram-history-item.tsx │ │ │ ├── diagram-preview-modal.tsx │ │ │ └── diagram-preview.tsx │ │ ├── login-dialog.tsx │ │ ├── onboarding-steps.tsx │ │ ├── posthog-provider.tsx │ │ └── session-provider.tsx │ ├── actions │ │ └── checkout.ts │ ├── api │ │ ├── anonymous │ │ │ └── route.ts │ │ ├── auth │ │ │ └── [...nextauth] │ │ │ │ └── route.ts │ │ ├── export │ │ │ └── route.ts │ │ ├── trpc │ │ │ └── [trpc] │ │ │ │ └── route.ts │ │ └── webhooks │ │ │ └── lemonsqueezy │ │ │ └── route.ts │ ├── generate │ │ └── page.tsx │ ├── layout.tsx │ ├── not-found.tsx │ └── settings │ │ └── page.tsx ├── components │ ├── landing │ │ ├── cta-button.tsx │ │ ├── cta-section.tsx │ │ ├── diagram-types-slider.tsx │ │ ├── faq-item.tsx │ │ ├── faq.tsx │ │ ├── feature-item.tsx │ │ ├── features-section.tsx │ │ ├── features-section2.tsx │ │ ├── features-section3.tsx │ │ ├── footer.tsx │ │ ├── header.tsx │ │ ├── hero.tsx │ │ ├── login-dialog.tsx │ │ ├── logo.tsx │ │ ├── mobile-nav.tsx │ │ ├── mobile-navbar.tsx │ │ ├── nav-item.tsx │ │ ├── pricing-card.tsx │ │ ├── pricing-feature-item.tsx │ │ ├── pricing.tsx │ │ ├── social-proof-logo.tsx │ │ └── stat-item.tsx │ └── ui │ │ ├── accordion.tsx │ │ ├── alert-dialog.tsx │ │ ├── alert.tsx │ │ ├── animated-counter.tsx │ │ ├── aspect-ratio.tsx │ │ ├── avatar.tsx │ │ ├── badge.tsx │ │ ├── banner.tsx │ │ ├── breadcrumb.tsx │ │ ├── button.tsx │ │ ├── calendar.tsx │ │ ├── card.tsx │ │ ├── carousel.tsx │ │ ├── chart.tsx │ │ ├── checkbox.tsx │ │ ├── collapsible.tsx │ │ ├── command.tsx │ │ ├── context-menu.tsx │ │ ├── dialog.tsx │ │ ├── drawer.tsx │ │ ├── dropdown-menu.tsx │ │ ├── form.tsx │ │ ├── hover-card.tsx │ │ ├── input-otp.tsx │ │ ├── input.tsx │ │ ├── intro-disclosure.tsx │ │ ├── label.tsx │ │ ├── menubar.tsx │ │ ├── minimal-card.tsx │ │ ├── navigation-menu.tsx │ │ ├── pagination.tsx │ │ ├── popover.tsx │ │ ├── progress.tsx │ │ ├── radio-group.tsx │ │ ├── resizable.tsx │ │ ├── scroll-area.tsx │ │ ├── select.tsx │ │ ├── separator.tsx │ │ ├── sheet.tsx │ │ ├── sidebar.tsx │ │ ├── skeleton.tsx │ │ ├── slider.tsx │ │ ├── sonner.tsx │ │ ├── switch.tsx │ │ ├── table.tsx │ │ ├── tabs.tsx │ │ ├── textarea.tsx │ │ ├── texturebutton.tsx │ │ ├── toast.tsx │ │ ├── toaster.tsx │ │ ├── toggle-group.tsx │ │ ├── toggle.tsx │ │ └── tooltip.tsx ├── env.js ├── hooks │ ├── use-diagram-preview.ts │ ├── use-mobile.tsx │ └── use-toast.ts ├── interfaces │ ├── author.ts │ └── post.ts ├── lib │ ├── ai-utils.ts │ ├── ai │ │ ├── diagram-generator.ts │ │ ├── diagram-utils.ts │ │ ├── gemini-client.ts │ │ ├── queue.ts │ │ └── types.ts │ ├── anonymous-user.ts │ ├── api.ts │ ├── blog.ts │ ├── constants.ts │ ├── lemonsqueezy.ts │ ├── markdownToHtml.ts │ ├── mermaid-config.ts │ └── utils.ts ├── mdx-components.tsx ├── server │ ├── api │ │ ├── root.ts │ │ ├── routers │ │ │ ├── ai.ts │ │ │ ├── diagram.ts │ │ │ └── post.ts │ │ └── trpc.ts │ ├── auth │ │ ├── config.ts │ │ └── index.ts │ ├── db.ts │ └── services │ │ ├── credits.service.ts │ │ └── mermaid-validation.service.ts ├── store │ └── diagram-store.ts ├── styles │ └── globals.css ├── syntax │ ├── architecture.md │ ├── c4.md │ ├── classDiagram.md │ ├── erDiagram.md │ ├── examples.md │ ├── flowchart.md │ ├── gantt.md │ ├── gitgraph.md │ ├── journey.md │ ├── kanban.md │ ├── mindmap.md │ ├── packet.md │ ├── pie.md │ ├── quadrant.md │ ├── requirementDiagram.md │ ├── sankey.md │ ├── sequenceDiagram.md │ ├── stateDiagram.md │ ├── timeline.md │ ├── xy.md │ └── zenuml.md ├── trpc │ ├── query-client.ts │ ├── react.tsx │ └── server.ts └── types │ ├── blog.ts │ ├── diagram-prompts.ts │ ├── diagram-types.ts │ ├── diagram.ts │ └── mermaid.ts ├── start-database.sh ├── tailwind.config.ts └── tsconfig.json /.env.example: -------------------------------------------------------------------------------- 1 | AUTH_SECRET="your auth secret" 2 | 3 | AUTH_GOOGLE_ID="your google client id" 4 | AUTH_GOOGLE_SECRET="your google client secret" 5 | 6 | DB_URL="your database url" 7 | 8 | # Gemini 9 | GEMINI_API_KEY="your gemini api key" 10 | 11 | # PostHog 12 | NEXT_PUBLIC_POSTHOG_KEY="your posthog key" 13 | NEXT_PUBLIC_POSTHOG_HOST="your posthog host" 14 | 15 | NEXT_PUBLIC_APP_URL="your app url" 16 | 17 | SKIP_ENV_VALIDATION=true 18 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | src/components/ui 2 | src/hooks 3 | *.d.ts 4 | *.config.js 5 | *.config.ts 6 | -------------------------------------------------------------------------------- /.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | /** @type {import("eslint").Linter.Config} */ 2 | const config = { 3 | "parser": "@typescript-eslint/parser", 4 | "parserOptions": { 5 | "project": true 6 | }, 7 | "plugins": [ 8 | "@typescript-eslint" 9 | ], 10 | "extends": [ 11 | "next/core-web-vitals", 12 | "plugin:@typescript-eslint/recommended-type-checked", 13 | "plugin:@typescript-eslint/stylistic-type-checked" 14 | ], 15 | "rules": { 16 | "@typescript-eslint/array-type": "off", 17 | "@typescript-eslint/consistent-type-definitions": "off", 18 | "@typescript-eslint/consistent-type-imports": [ 19 | "warn", 20 | { 21 | "prefer": "type-imports", 22 | "fixStyle": "inline-type-imports" 23 | } 24 | ], 25 | "@typescript-eslint/no-unused-vars": [ 26 | "warn", 27 | { 28 | "argsIgnorePattern": "^_" 29 | } 30 | ], 31 | "@typescript-eslint/require-await": "off", 32 | "@typescript-eslint/no-misused-promises": [ 33 | "error", 34 | { 35 | "checksVoidReturn": { 36 | "attributes": false 37 | } 38 | } 39 | ] 40 | } 41 | } 42 | module.exports = config; -------------------------------------------------------------------------------- /.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 | db.sqlite 15 | 16 | # next.js 17 | /.next/ 18 | /out/ 19 | next-env.d.ts 20 | 21 | # production 22 | /build 23 | 24 | # misc 25 | .DS_Store 26 | *.pem 27 | 28 | # debug 29 | npm-debug.log* 30 | yarn-debug.log* 31 | yarn-error.log* 32 | .pnpm-debug.log* 33 | 34 | # local env files 35 | # 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 36 | .env 37 | .env*.local 38 | 39 | # vercel 40 | .vercel 41 | 42 | # typescript 43 | *.tsbuildinfo 44 | 45 | # idea files 46 | .idea 47 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2025 Aniruddh Dubge 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 | # Diagram Generator 2 | 3 | An AI-powered diagram generation tool that uses Gemini and Mermaid.js to create beautiful, accurate diagrams from natural language descriptions. 4 | 5 | ## 🌟 Features 6 | 7 | - **AI-Powered Diagram Generation**: Leverages Gemini AI to understand natural language descriptions and convert them into diagrams 8 | - **Multiple Diagram Types**: Supports 20+ different diagram types including: 9 | - Flowcharts 10 | - Sequence Diagrams 11 | - Class Diagrams 12 | - Entity Relationship Diagrams 13 | - State Diagrams 14 | - Gantt Charts 15 | - Git Graphs 16 | - And more! 17 | - **Smart Type Detection**: Automatically determines the most suitable diagram type for your description 18 | - **Validation & Error Handling**: Ensures generated diagrams are syntactically correct and renders properly 19 | - **Modern UI/UX**: Beautiful and responsive interface built with Next.js and Tailwind CSS 20 | - **Real-time Preview**: Instant visualization of generated diagrams 21 | - **Export Options**: Save diagrams in various formats 22 | 23 | ## 🚀 Tech Stack 24 | 25 | - **Frontend**: Next.js, React, TypeScript, Tailwind CSS 26 | - **AI Integration**: Google Gemini AI 27 | - **Diagram Rendering**: Mermaid.js 28 | - **Database**: Prisma with PostgreSQL 29 | - **Authentication**: NextAuth.js 30 | - **Styling**: Radix UI, Tailwind CSS 31 | - **Development**: ESLint, Prettier, TypeScript 32 | 33 | ## 📋 Prerequisites 34 | 35 | - Node.js (v18 or higher) 36 | - PostgreSQL 37 | - Google Cloud API Key (for Gemini AI) 38 | 39 | ## 🛠️ Setup 40 | 41 | 1. Clone the repository: 42 | ```bash 43 | git clone https://github.com/icantcodefyi/diagram.git 44 | cd diagram 45 | ``` 46 | 47 | 2. Install dependencies: 48 | ```bash 49 | bun install 50 | ``` 51 | 52 | 3. Set up environment variables: 53 | ```bash 54 | cp .env.example .env 55 | ``` 56 | Edit `.env` with your configuration: 57 | - Database URL 58 | - Google Cloud API Key 59 | - Other necessary credentials 60 | 61 | 4. Set up the database: 62 | ```bash 63 | bun db:generate 64 | bun db:push 65 | ``` 66 | 67 | 5. Start the development server: 68 | ```bash 69 | bun dev 70 | ``` 71 | 72 | The application will be available at `http://localhost:3000` 73 | 74 | ## 🎯 Usage 75 | 76 | 1. Visit the application in your browser 77 | 2. Enter a natural language description of the diagram you want to create 78 | 3. The AI will automatically determine the best diagram type and generate the appropriate Mermaid.js code 79 | 4. Preview the diagram in real-time 80 | 5. Export or share your diagram as needed 81 | 82 | ## 🤝 Contributing 83 | 84 | Contributions are welcome! Please feel free to submit a Pull Request. 85 | 86 | ## 📝 License 87 | 88 | This project is licensed under the MIT License - see the LICENSE file for details. 89 | 90 | ## Star History 91 | 92 | [![Star History Chart](https://api.star-history.com/svg?repos=icantcodefyi/diagram&type=Date)](https://star-history.com/#icantcodefyi/diagram&Date) -------------------------------------------------------------------------------- /bun.lockb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icantcodefyi/diagram/da4dd00f6eebf43d6aabb715547e868f2c7b6b4b/bun.lockb -------------------------------------------------------------------------------- /components.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://ui.shadcn.com/schema.json", 3 | "style": "new-york", 4 | "rsc": true, 5 | "tsx": true, 6 | "tailwind": { 7 | "config": "tailwind.config.ts", 8 | "css": "src/styles/globals.css", 9 | "baseColor": "neutral", 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 | "iconLibrary": "lucide" 21 | } -------------------------------------------------------------------------------- /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 | import "./src/env.js"; 6 | 7 | /** @type {import("next").NextConfig} */ 8 | const config = {}; 9 | 10 | export default config; 11 | -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | export default { 2 | plugins: { 3 | tailwindcss: {}, 4 | }, 5 | }; 6 | -------------------------------------------------------------------------------- /prettier.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('prettier').Config & import('prettier-plugin-tailwindcss').PluginOptions} */ 2 | export default { 3 | plugins: ["prettier-plugin-tailwindcss"], 4 | }; 5 | -------------------------------------------------------------------------------- /prisma/migrations/20250206055701_dev/migration.sql: -------------------------------------------------------------------------------- 1 | -- CreateTable 2 | CREATE TABLE "Post" ( 3 | "id" SERIAL NOT NULL, 4 | "name" TEXT NOT NULL, 5 | "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, 6 | "updatedAt" TIMESTAMP(3) NOT NULL, 7 | "createdById" TEXT NOT NULL, 8 | 9 | CONSTRAINT "Post_pkey" PRIMARY KEY ("id") 10 | ); 11 | 12 | -- CreateTable 13 | CREATE TABLE "Account" ( 14 | "id" TEXT NOT NULL, 15 | "userId" TEXT NOT NULL, 16 | "type" TEXT NOT NULL, 17 | "provider" TEXT NOT NULL, 18 | "providerAccountId" TEXT NOT NULL, 19 | "refresh_token" TEXT, 20 | "access_token" TEXT, 21 | "expires_at" INTEGER, 22 | "token_type" TEXT, 23 | "scope" TEXT, 24 | "id_token" TEXT, 25 | "session_state" TEXT, 26 | "refresh_token_expires_in" INTEGER, 27 | 28 | CONSTRAINT "Account_pkey" PRIMARY KEY ("id") 29 | ); 30 | 31 | -- CreateTable 32 | CREATE TABLE "Session" ( 33 | "id" TEXT NOT NULL, 34 | "sessionToken" TEXT NOT NULL, 35 | "userId" TEXT NOT NULL, 36 | "expires" TIMESTAMP(3) NOT NULL, 37 | 38 | CONSTRAINT "Session_pkey" PRIMARY KEY ("id") 39 | ); 40 | 41 | -- CreateTable 42 | CREATE TABLE "User" ( 43 | "id" TEXT NOT NULL, 44 | "name" TEXT, 45 | "email" TEXT, 46 | "emailVerified" TIMESTAMP(3), 47 | "image" TEXT, 48 | 49 | CONSTRAINT "User_pkey" PRIMARY KEY ("id") 50 | ); 51 | 52 | -- CreateTable 53 | CREATE TABLE "VerificationToken" ( 54 | "identifier" TEXT NOT NULL, 55 | "token" TEXT NOT NULL, 56 | "expires" TIMESTAMP(3) NOT NULL 57 | ); 58 | 59 | -- CreateIndex 60 | CREATE INDEX "Post_name_idx" ON "Post"("name"); 61 | 62 | -- CreateIndex 63 | CREATE UNIQUE INDEX "Account_provider_providerAccountId_key" ON "Account"("provider", "providerAccountId"); 64 | 65 | -- CreateIndex 66 | CREATE UNIQUE INDEX "Session_sessionToken_key" ON "Session"("sessionToken"); 67 | 68 | -- CreateIndex 69 | CREATE UNIQUE INDEX "User_email_key" ON "User"("email"); 70 | 71 | -- CreateIndex 72 | CREATE UNIQUE INDEX "VerificationToken_token_key" ON "VerificationToken"("token"); 73 | 74 | -- CreateIndex 75 | CREATE UNIQUE INDEX "VerificationToken_identifier_token_key" ON "VerificationToken"("identifier", "token"); 76 | 77 | -- AddForeignKey 78 | ALTER TABLE "Post" ADD CONSTRAINT "Post_createdById_fkey" FOREIGN KEY ("createdById") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE; 79 | 80 | -- AddForeignKey 81 | ALTER TABLE "Account" ADD CONSTRAINT "Account_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE; 82 | 83 | -- AddForeignKey 84 | ALTER TABLE "Session" ADD CONSTRAINT "Session_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE; 85 | -------------------------------------------------------------------------------- /prisma/migrations/20250206201442_update/migration.sql: -------------------------------------------------------------------------------- 1 | -- CreateTable 2 | CREATE TABLE "Diagram" ( 3 | "id" TEXT NOT NULL, 4 | "content" TEXT NOT NULL, 5 | "type" TEXT NOT NULL, 6 | "name" TEXT, 7 | "isComplex" BOOLEAN NOT NULL DEFAULT false, 8 | "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, 9 | "updatedAt" TIMESTAMP(3) NOT NULL, 10 | "userId" TEXT, 11 | 12 | CONSTRAINT "Diagram_pkey" PRIMARY KEY ("id") 13 | ); 14 | 15 | -- CreateTable 16 | CREATE TABLE "UserCredits" ( 17 | "id" TEXT NOT NULL, 18 | "userId" TEXT NOT NULL, 19 | "credits" INTEGER NOT NULL DEFAULT 10, 20 | "lastCreditReset" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, 21 | 22 | CONSTRAINT "UserCredits_pkey" PRIMARY KEY ("id") 23 | ); 24 | 25 | -- CreateIndex 26 | CREATE INDEX "Diagram_userId_idx" ON "Diagram"("userId"); 27 | 28 | -- CreateIndex 29 | CREATE UNIQUE INDEX "UserCredits_userId_key" ON "UserCredits"("userId"); 30 | 31 | -- CreateIndex 32 | CREATE INDEX "UserCredits_userId_idx" ON "UserCredits"("userId"); 33 | 34 | -- AddForeignKey 35 | ALTER TABLE "Diagram" ADD CONSTRAINT "Diagram_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE SET NULL ON UPDATE CASCADE; 36 | 37 | -- AddForeignKey 38 | ALTER TABLE "UserCredits" ADD CONSTRAINT "UserCredits_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE; 39 | -------------------------------------------------------------------------------- /prisma/migrations/20250207092714_add_anonymous_id/migration.sql: -------------------------------------------------------------------------------- 1 | -- AlterTable 2 | ALTER TABLE "Diagram" ADD COLUMN "anonymousId" TEXT; 3 | 4 | -- CreateIndex 5 | CREATE INDEX "Diagram_anonymousId_idx" ON "Diagram"("anonymousId"); 6 | -------------------------------------------------------------------------------- /prisma/migrations/20250208141523_credits/migration.sql: -------------------------------------------------------------------------------- 1 | -- AlterTable 2 | ALTER TABLE "UserCredits" ADD COLUMN "lastMonthlyReset" TIMESTAMP(3), 3 | ADD COLUMN "monthlyCredits" INTEGER NOT NULL DEFAULT 0, 4 | ALTER COLUMN "credits" SET DEFAULT 20; 5 | 6 | -- CreateTable 7 | CREATE TABLE "Subscription" ( 8 | "id" TEXT NOT NULL, 9 | "userId" TEXT NOT NULL, 10 | "status" TEXT NOT NULL, 11 | "lemonSqueezyId" TEXT NOT NULL, 12 | "currentPeriodEnd" TIMESTAMP(3) NOT NULL, 13 | "cancelAtPeriodEnd" BOOLEAN NOT NULL DEFAULT false, 14 | "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, 15 | "updatedAt" TIMESTAMP(3) NOT NULL, 16 | 17 | CONSTRAINT "Subscription_pkey" PRIMARY KEY ("id") 18 | ); 19 | 20 | -- CreateIndex 21 | CREATE UNIQUE INDEX "Subscription_userId_key" ON "Subscription"("userId"); 22 | 23 | -- CreateIndex 24 | CREATE UNIQUE INDEX "Subscription_lemonSqueezyId_key" ON "Subscription"("lemonSqueezyId"); 25 | 26 | -- CreateIndex 27 | CREATE INDEX "Subscription_userId_idx" ON "Subscription"("userId"); 28 | 29 | -- CreateIndex 30 | CREATE INDEX "Subscription_lemonSqueezyId_idx" ON "Subscription"("lemonSqueezyId"); 31 | 32 | -- AddForeignKey 33 | ALTER TABLE "Subscription" ADD CONSTRAINT "Subscription_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE; 34 | -------------------------------------------------------------------------------- /prisma/migrations/migration_lock.toml: -------------------------------------------------------------------------------- 1 | # Please do not edit this file manually 2 | # It should be added in your version-control system (i.e. Git) 3 | provider = "postgresql" -------------------------------------------------------------------------------- /public/android-chrome-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icantcodefyi/diagram/da4dd00f6eebf43d6aabb715547e868f2c7b6b4b/public/android-chrome-192x192.png -------------------------------------------------------------------------------- /public/android-chrome-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icantcodefyi/diagram/da4dd00f6eebf43d6aabb715547e868f2c7b6b4b/public/android-chrome-512x512.png -------------------------------------------------------------------------------- /public/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icantcodefyi/diagram/da4dd00f6eebf43d6aabb715547e868f2c7b6b4b/public/apple-touch-icon.png -------------------------------------------------------------------------------- /public/blog/ai-powered-diagrams.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icantcodefyi/diagram/da4dd00f6eebf43d6aabb715547e868f2c7b6b4b/public/blog/ai-powered-diagrams.png -------------------------------------------------------------------------------- /public/blog/android-chrome-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icantcodefyi/diagram/da4dd00f6eebf43d6aabb715547e868f2c7b6b4b/public/blog/android-chrome-512x512.png -------------------------------------------------------------------------------- /public/blog/authors/autodiagram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icantcodefyi/diagram/da4dd00f6eebf43d6aabb715547e868f2c7b6b4b/public/blog/authors/autodiagram.png -------------------------------------------------------------------------------- /public/blog/how-autodiagram-is-better.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icantcodefyi/diagram/da4dd00f6eebf43d6aabb715547e868f2c7b6b4b/public/blog/how-autodiagram-is-better.png -------------------------------------------------------------------------------- /public/blog/intro-to-autodiagram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icantcodefyi/diagram/da4dd00f6eebf43d6aabb715547e868f2c7b6b4b/public/blog/intro-to-autodiagram.png -------------------------------------------------------------------------------- /public/blog/nextjs-guide.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icantcodefyi/diagram/da4dd00f6eebf43d6aabb715547e868f2c7b6b4b/public/blog/nextjs-guide.jpg -------------------------------------------------------------------------------- /public/blog/og-image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icantcodefyi/diagram/da4dd00f6eebf43d6aabb715547e868f2c7b6b4b/public/blog/og-image.png -------------------------------------------------------------------------------- /public/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icantcodefyi/diagram/da4dd00f6eebf43d6aabb715547e868f2c7b6b4b/public/favicon-16x16.png -------------------------------------------------------------------------------- /public/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icantcodefyi/diagram/da4dd00f6eebf43d6aabb715547e868f2c7b6b4b/public/favicon-32x32.png -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icantcodefyi/diagram/da4dd00f6eebf43d6aabb715547e868f2c7b6b4b/public/favicon.ico -------------------------------------------------------------------------------- /public/google-logo.svg: -------------------------------------------------------------------------------- 1 | Gemini -------------------------------------------------------------------------------- /public/google.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/landing/Group-998-1-(1).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icantcodefyi/diagram/da4dd00f6eebf43d6aabb715547e868f2c7b6b4b/public/landing/Group-998-1-(1).png -------------------------------------------------------------------------------- /public/landing/amazon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icantcodefyi/diagram/da4dd00f6eebf43d6aabb715547e868f2c7b6b4b/public/landing/amazon.png -------------------------------------------------------------------------------- /public/landing/contact.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icantcodefyi/diagram/da4dd00f6eebf43d6aabb715547e868f2c7b6b4b/public/landing/contact.png -------------------------------------------------------------------------------- /public/landing/cta.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icantcodefyi/diagram/da4dd00f6eebf43d6aabb715547e868f2c7b6b4b/public/landing/cta.png -------------------------------------------------------------------------------- /public/landing/facebook.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icantcodefyi/diagram/da4dd00f6eebf43d6aabb715547e868f2c7b6b4b/public/landing/facebook.png -------------------------------------------------------------------------------- /public/landing/feature2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icantcodefyi/diagram/da4dd00f6eebf43d6aabb715547e868f2c7b6b4b/public/landing/feature2.png -------------------------------------------------------------------------------- /public/landing/google.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icantcodefyi/diagram/da4dd00f6eebf43d6aabb715547e868f2c7b6b4b/public/landing/google.png -------------------------------------------------------------------------------- /public/landing/microsoft.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icantcodefyi/diagram/da4dd00f6eebf43d6aabb715547e868f2c7b6b4b/public/landing/microsoft.webp -------------------------------------------------------------------------------- /public/landing/netflix.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icantcodefyi/diagram/da4dd00f6eebf43d6aabb715547e868f2c7b6b4b/public/landing/netflix.png -------------------------------------------------------------------------------- /public/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icantcodefyi/diagram/da4dd00f6eebf43d6aabb715547e868f2c7b6b4b/public/logo.png -------------------------------------------------------------------------------- /public/site.webmanifest: -------------------------------------------------------------------------------- 1 | {"name":"","short_name":"","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"} -------------------------------------------------------------------------------- /public/vercel-logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /public/video.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icantcodefyi/diagram/da4dd00f6eebf43d6aabb715547e868f2c7b6b4b/public/video.mp4 -------------------------------------------------------------------------------- /public/videos/feature-2.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icantcodefyi/diagram/da4dd00f6eebf43d6aabb715547e868f2c7b6b4b/public/videos/feature-2.mp4 -------------------------------------------------------------------------------- /public/videos/feature-3.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icantcodefyi/diagram/da4dd00f6eebf43d6aabb715547e868f2c7b6b4b/public/videos/feature-3.mp4 -------------------------------------------------------------------------------- /src/app/(landing)/blog/[slug]/page.tsx: -------------------------------------------------------------------------------- 1 | import { type Metadata } from "next"; 2 | import { notFound } from "next/navigation"; 3 | import { getAllPosts, getPostBySlug } from "@/lib/api"; 4 | import { CMS_NAME } from "@/lib/constants"; 5 | import markdownToHtml from "@/lib/markdownToHtml"; 6 | import Container from "@/app/_components/blogs/container"; 7 | import Header from "@/app/_components/blogs/header"; 8 | import { PostBody } from "@/app/_components/blogs/post-body"; 9 | import { PostHeader } from "@/app/_components/blogs/post-header"; 10 | import { CtaButton } from "@/components/landing/cta-button"; 11 | 12 | type Params = { 13 | params: Promise<{ 14 | slug: string; 15 | }>; 16 | }; 17 | 18 | export default async function Post(props: Params) { 19 | const params = await props.params; 20 | const post = getPostBySlug(params.slug); 21 | 22 | if (!post) { 23 | return notFound(); 24 | } 25 | 26 | try { 27 | const content = await markdownToHtml(post.content || ""); 28 | 29 | return ( 30 |
31 | 32 |
33 |
34 | 40 | 41 |
42 | 43 |
44 | 48 |
49 |
50 | ); 51 | } catch (error) { 52 | console.error('Error rendering blog post:', error); 53 | return notFound(); 54 | } 55 | } 56 | 57 | export async function generateMetadata(props: Params): Promise { 58 | const params = await props.params; 59 | const post = getPostBySlug(params.slug); 60 | 61 | if (!post) { 62 | return notFound(); 63 | } 64 | 65 | const title = `${post.title} | ${CMS_NAME}`; 66 | 67 | return { 68 | title, 69 | openGraph: { 70 | title, 71 | images: [post.ogImage.url], 72 | }, 73 | }; 74 | } 75 | 76 | export async function generateStaticParams() { 77 | const posts = getAllPosts(); 78 | 79 | return posts.map((post) => ({ 80 | slug: post.slug, 81 | })); 82 | } 83 | -------------------------------------------------------------------------------- /src/app/(landing)/blog/not-found.tsx: -------------------------------------------------------------------------------- 1 | import Link from "next/link"; 2 | 3 | export default function NotFound() { 4 | return ( 5 |
6 |
7 |

8 | 404 9 |

10 |

11 | Page Not Found 12 |

13 |

14 | Oops! The page you're looking for doesn't exist or has been moved. 15 |

16 | 20 | Return Home 21 | 22 |
23 |
24 | ); 25 | } -------------------------------------------------------------------------------- /src/app/(landing)/blog/page.tsx: -------------------------------------------------------------------------------- 1 | import Container from "@/app/_components/blogs/container"; 2 | import { HeroPost } from "@/app/_components/blogs/hero-post"; 3 | import { Intro } from "@/app/_components/blogs/intro"; 4 | import { MoreStories } from "@/app/_components/blogs/more-stories"; 5 | import { getAllPosts } from "@/lib/api"; 6 | 7 | export default function Index() { 8 | const allPosts = getAllPosts(); 9 | 10 | const heroPost = allPosts[0]; 11 | 12 | const morePosts = allPosts.slice(1); 13 | 14 | return ( 15 |
16 | 17 | 18 | {heroPost && ( 19 | 27 | )} 28 | {morePosts.length > 0 && } 29 | 30 |
31 | ); 32 | } 33 | -------------------------------------------------------------------------------- /src/app/(landing)/contact/page.tsx: -------------------------------------------------------------------------------- 1 | import { Mail, Twitter, MessageCircle } from "lucide-react"; 2 | import Image from "next/image"; 3 | import Link from "next/link"; 4 | export default function Contact() { 5 | return ( 6 |
7 |
8 |
9 |

Contact Us

10 |

11 | We're here to help and answer any question you might have. We look forward to 12 | hearing from you! 13 |

14 |
15 |
16 |
17 | 18 |
19 |
20 | 21 |

Email

22 |

venti.sillly@gmail.com

23 | 24 |
25 |
26 |
27 |
28 | 29 |
30 |
31 | 32 |

Twitter

33 |

@icantcodefyi

34 | 35 |
36 |
37 |
38 |
39 | 40 |
41 |
42 |

Discord

43 |

@venti2

44 |
45 |
46 |
47 |
48 |
49 |
50 | Contact Us 57 |
58 |
59 |
60 |
61 | ); 62 | } 63 | -------------------------------------------------------------------------------- /src/app/(landing)/features/page.tsx: -------------------------------------------------------------------------------- 1 | import { FeaturesSection } from "@/components/landing/features-section"; 2 | import { FeaturesSection2 } from "@/components/landing/features-section2"; 3 | import { FeaturesSection3 } from "@/components/landing/features-section3"; 4 | 5 | export default function FeaturesPage() { 6 | return ( 7 | <> 8 | 9 | 10 | 11 | 12 | ); 13 | } -------------------------------------------------------------------------------- /src/app/(landing)/layout.tsx: -------------------------------------------------------------------------------- 1 | import { Header } from "@/components/landing/header"; 2 | import { Footer } from "@/components/landing/footer"; 3 | 4 | export default function LandingLayout({ 5 | children, 6 | }: { 7 | children: React.ReactNode; 8 | }) { 9 | return ( 10 | <> 11 |
12 | {children} 13 |