@@ -77,92 +473,53 @@ export default function About() {
{/* Bring Your Own Key */}
- Bring Your Own API Key
+ {t.byok.title}
- You can also use your own API key with any
- supported provider. Click the Settings icon
- in the chat panel to configure your provider
- and API key.
+ {t.byok.body}
- Your key is stored locally in your browser
- and is never stored on the server.
+ {t.byok.note}
-
- A Next.js web application that integrates AI
- capabilities with draw.io diagrams. Create, modify, and
- enhance diagrams through natural language commands and
- AI-assisted visualization.
-
+
{t.intro}
{/* Features */}
- Features
+ {t.featuresHeading}
-
- LLM-Powered Diagram Creation:
- Leverage Large Language Models to create and
- manipulate draw.io diagrams directly through natural
- language commands
-
-
- Image-Based Diagram Replication:
- Upload existing diagrams or images and have the AI
- replicate and enhance them automatically
-
-
- Versions and Undo: Every AI change
- becomes a version in the chat that you can compare,
- restore or undo; Ctrl+Z on the canvas takes it back
- too
-
-
- Interactive Chat Interface:
- Communicate with AI to refine your diagrams in
- real-time
-
-
- AWS Architecture Diagram Support:
- Specialized support for generating AWS architecture
- diagrams
-
-
- Animated Connectors: Create dynamic
- and animated connectors between diagram elements for
- better visualization
-
+ {t.features.map((feature) => (
+
+ {feature.title}
+ {t.colon}
+ {feature.text}
+
+ ))}
{/* Examples */}
- Examples
+ {t.examplesHeading}
-
- Here are some example prompts and their generated
- diagrams:
-
+
{t.examplesIntro}
- {/* ResNet50 Architecture */}
+ {/* First example on its own */}
- Animated ResNet50 Model Architecture
+ {t.examples[hero.id].title}
- Prompt: Give me an{" "}
- animated architecture diagram
- of the ResNet50 model.
+ Prompt: {hero.prompt}
-
-
- RAG Technique Diagram
-
-
- Prompt: Generate a RAG
- architecture diagram for{" "}
- chat application. Use
- connected diagram for data ingestion
-
-
-
+ {grid.map((example) => (
+
+
+ {t.examples[example.id].title}
+
+
+ Prompt:{" "}
+ {example.prompt}
+
+
+
+
-
-
-
- Authentication using React and AWS
-
-
- Prompt: Generate
- authentication process using React with{" "}
- AWS. Use Serverless
- architecture.
-
-
-
-
-
-
-
- Agile Scrum Process
-
-
- Prompt: Generate agile
- scrum workflow diagram for software
- development team.
-
-
-
-
-
-
-
- Open Innovation
-
-
- Prompt: Create
- visualization of Henry Chesbrough's
- Open Innovation model.
-
-
-
-
-
+ ))}
{/* How It Works */}
- How It Works
+ {t.howHeading}
-
- The application uses the following technologies:
-
+
{t.howIntro}
- Next.js: For the frontend framework
- and routing
+ Next.js
+ {t.colon}
+ {t.tech.nextjs}
- Vercel AI SDK (ai +{" "}
- @ai-sdk/*): For streaming AI responses
- and multi-provider support
+ Vercel AI SDK
+ {t.parenOpen}
+ ai + @ai-sdk/*
+ {t.parenClose}
+ {t.colon}
+ {t.tech.aiSdk}
- draw.io: The editor, bundled with
- the app so it can be driven directly
+ draw.io
+ {t.colon}
+ {t.tech.drawio}
-
- Diagrams are represented as XML that can be rendered in
- draw.io. The AI processes your commands and generates or
- modifies this XML accordingly.
-
@@ -303,48 +602,47 @@ export default function About() {
ModelScope
- Note that claude-sonnet-4-5 has trained on
- draw.io diagrams with AWS logos, so if you want to
- create AWS architecture diagrams, this is the best
- choice.
+ {t.modelNote.before}
+ claude-sonnet-4-5
+ {t.modelNote.after}
{/* Support */}
- Support & Contact
+ {t.supportHeading}
- If you find this project useful, please consider{" "}
+ {t.sponsor.before}{" "}
- sponsoring
+ {t.sponsor.link}
{" "}
- to help host the live demo site!
+ {t.sponsor.after}
- For support or inquiries, please open an issue on the{" "}
+ {t.contact.before}{" "}
- GitHub repository
+ {t.contact.link}
{" "}
- or contact: me[at]jiang.jp
+ {t.contact.after}
{/* CTA */}
- Open Editor
+ {t.openEditor}
@@ -354,8 +652,7 @@ export default function About() {
diff --git a/app/[lang]/layout.tsx b/app/[lang]/layout.tsx
index bc2fd112..05470c14 100644
--- a/app/[lang]/layout.tsx
+++ b/app/[lang]/layout.tsx
@@ -40,6 +40,13 @@ export async function generateStaticParams() {
return i18n.locales.map((locale) => ({ lang: locale }))
}
+const OG_LOCALE: Record = {
+ en: "en_US",
+ zh: "zh_CN",
+ ja: "ja_JP",
+ "zh-Hant": "zh_HK",
+}
+
// Generate metadata per locale
export async function generateMetadata({
params,
@@ -47,22 +54,19 @@ export async function generateMetadata({
params: Promise<{ lang: string }>
}): Promise {
const { lang: rawLang } = await params
- const lang = (
- rawLang in { en: 1, zh: 1, ja: 1, "zh-Hant": 1 } ? rawLang : "en"
- ) as Locale
+ const lang: Locale = hasLocale(rawLang) ? rawLang : i18n.defaultLocale
- // Default to English metadata
const titles: Record = {
en: "Next AI Draw.io - AI-Powered Diagram Generator",
- zh: "Next AI Draw.io - AI powered diagram generator",
- ja: "Next AI Draw.io - AI-powered diagram generator",
+ zh: "Next AI Draw.io - AI 驱动的图表生成器",
+ ja: "Next AI Draw.io - AI 搭載ダイアグラム生成ツール",
"zh-Hant": "Next AI Draw.io - AI 驅動的圖表產生器",
}
const descriptions: Record = {
en: "Create AWS architecture diagrams, flowcharts, and technical diagrams using AI. Free online tool integrating draw.io with AI assistance for professional diagram creation.",
- zh: "Use AI to create AWS architecture diagrams, flowcharts, and technical diagrams. Free online tool integrated with draw.io and AI assistance for professional diagram creation.",
- ja: "Create AWS architecture diagrams, flowcharts, and technical diagrams using AI. Create professional diagrams with a free online tool that integrates draw.io with an AI assistant.",
+ zh: "使用 AI 创建 AWS 架构图、流程图和技术图表。免费在线工具,整合 draw.io 与 AI 辅助,轻松创建专业图表。",
+ ja: "AI で AWS アーキテクチャ図、フローチャート、技術図を作成。draw.io と AI アシスタントを統合した無料オンラインツールで、プロ品質の図を簡単に作成できます。",
"zh-Hant":
"使用 AI 建立 AWS 架構圖、流程圖和技術圖表。免費線上工具整合 draw.io 與 AI 輔助,輕鬆建立專業圖表。",
}
@@ -91,14 +95,7 @@ export async function generateMetadata({
type: "website",
url: "https://next-ai-drawio.jiang.jp",
siteName: "Next AI Draw.io",
- locale:
- lang === "zh"
- ? "zh_CN"
- : lang === "zh-Hant"
- ? "zh_HK"
- : lang === "ja"
- ? "ja_JP"
- : "en_US",
+ locale: OG_LOCALE[lang],
images: [
{
url: "/architecture.png",
diff --git a/components/icons/github.tsx b/components/icons/github.tsx
new file mode 100644
index 00000000..8f751843
--- /dev/null
+++ b/components/icons/github.tsx
@@ -0,0 +1,13 @@
+// GitHub mark as an inline SVG, so no icon package is needed for one icon
+export function GitHubIcon({ className }: { className?: string }) {
+ return (
+
+ )
+}
diff --git a/components/quota-limit-toast.tsx b/components/quota-limit-toast.tsx
index 458c892a..f699b742 100644
--- a/components/quota-limit-toast.tsx
+++ b/components/quota-limit-toast.tsx
@@ -2,7 +2,7 @@
import { Coffee, Settings, X } from "lucide-react"
import type React from "react"
-import { FaGithub } from "react-icons/fa"
+import { GitHubIcon } from "@/components/icons/github"
import { useDictionary } from "@/hooks/use-dictionary"
import { formatMessage } from "@/lib/i18n/utils"
@@ -28,16 +28,10 @@ export function QuotaLimitToast({
n >= 1000 ? `${(n / 1000).toFixed(1)}k` : n.toString()
const quotaMessage = isTokenLimit
- ? isSelfHosted
- ? (dict.quota.messageTokenSelfHosted ?? dict.quota.messageToken)
- : dict.quota.messageToken
- : isSelfHosted
- ? (dict.quota.messageApiSelfHosted ?? dict.quota.messageApi)
- : dict.quota.messageApi
+ ? dict.quota.messageToken
+ : dict.quota.messageApi
- const tipHtml = isSelfHosted
- ? (dict.quota.tipSelfHosted ?? dict.quota.tip)
- : dict.quota.tip
+ const tipHtml = isSelfHosted ? dict.quota.tipSelfHosted : dict.quota.tip
const handleKeyDown = (e: React.KeyboardEvent) => {
if (e.key === "Escape") {
@@ -52,7 +46,7 @@ export function QuotaLimitToast({
aria-live="polite"
tabIndex={0}
onKeyDown={handleKeyDown}
- className="relative w-[400px] overflow-hidden rounded-xl border border-border/50 bg-card p-5 shadow-soft animate-message-in"
+ className="relative w-[400px] overflow-hidden rounded-xl border border-border/50 bg-card p-5 shadow-float animate-message-in"
>
{/* Close button */}