Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 55 additions & 1 deletion apps/site/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,71 @@
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="theme-color" content="#0E7C6B" />
<meta name="color-scheme" content="light" />

<title>Visimer · Edit Mermaid diagrams by hand</title>
<meta
name="description"
content="A WYSIWYG editor for Mermaid. Click a node to rename or reshape it. The source rewrites itself."
content="Visimer is an open-source WYSIWYG editor for Mermaid diagrams. Click a node to rename or reshape it and the source rewrites itself. React and vanilla bindings, MIT licensed."
/>
<meta
name="keywords"
content="mermaid, mermaid editor, wysiwyg, diagram editor, flowchart editor, sequence diagram, mermaid js, visual editing, react component, open source"
/>
<meta name="author" content="Inkeep" />
<meta name="robots" content="index, follow, max-image-preview:large" />
<link rel="canonical" href="https://visimer.com/" />

<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<link rel="mask-icon" href="/favicon.svg" color="#0E7C6B" />
<link rel="apple-touch-icon" href="/favicon.svg" />

<meta property="og:site_name" content="Visimer" />
<meta property="og:title" content="Visimer · Edit Mermaid diagrams by hand" />
<meta
property="og:description"
content="An open-source WYSIWYG editor for Mermaid. Click a node to rename or reshape it and the source rewrites itself."
/>
<meta property="og:type" content="website" />
<meta property="og:url" content="https://visimer.com/" />
<meta property="og:image" content="https://visimer.com/og-image.png" />
<meta property="og:image:width" content="1200" />
<meta property="og:image:height" content="630" />
<meta property="og:image:alt" content="Visimer: edit Mermaid diagrams by hand." />
<meta property="og:locale" content="en_US" />

<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:title" content="Visimer · Edit Mermaid diagrams by hand" />
<meta
name="twitter:description"
content="An open-source WYSIWYG editor for Mermaid. Click a node to rename or reshape it and the source rewrites itself."
/>
<meta name="twitter:image" content="https://visimer.com/og-image.png" />
<meta name="twitter:image:alt" content="Visimer: edit Mermaid diagrams by hand." />

<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
href="https://fonts.googleapis.com/css2?family=Inter:ital,wght@0,400;0,500;0,600;0,700;1,400;1,600&family=Caveat:wght@600&family=JetBrains+Mono:wght@400;500;600&display=swap"
rel="stylesheet"
/>

<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "SoftwareApplication",
"name": "Visimer",
"url": "https://visimer.com/",
"description": "An open-source WYSIWYG editor for Mermaid diagrams. Click a node to rename or reshape it and the source rewrites itself.",
"applicationCategory": "DeveloperApplication",
"operatingSystem": "Web",
"license": "https://opensource.org/licenses/MIT",
"author": { "@type": "Organization", "name": "Inkeep", "url": "https://inkeep.com" },
"offers": { "@type": "Offer", "price": "0", "priceCurrency": "USD" },
"sameAs": ["https://github.com/inkeep/visimer", "https://www.npmjs.com/package/@visimer/react"]
}
</script>
</head>
<body>
<div id="root"></div>
Expand Down
10 changes: 10 additions & 0 deletions apps/site/public/favicon.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added apps/site/public/og-image.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions apps/site/public/robots.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
User-agent: *
Allow: /

Sitemap: https://visimer.com/sitemap.xml
8 changes: 8 additions & 0 deletions apps/site/public/sitemap.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<url>
<loc>https://visimer.com/</loc>
<changefreq>weekly</changefreq>
<priority>1.0</priority>
</url>
</urlset>
29 changes: 23 additions & 6 deletions apps/site/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -276,14 +276,22 @@ export default function App() {
const badge = badgeRef.current
if (!badge) return
const navBottom = 80
const startTop = badge.getBoundingClientRect().top + window.scrollY - navBottom
const onScroll = () => {
const distance = badge.getBoundingClientRect().top - navBottom
setStarHintOpacity(Math.max(0, Math.min(1, distance / startTop)))
const compute = () => {
const rect = badge.getBoundingClientRect()
// Re-derive the fade origin every tick so a late web-font layout
// shift or viewport resize doesn't leave the ratio stale.
const startTop = rect.top + window.scrollY - navBottom
if (startTop <= 0) return 0
return Math.max(0, Math.min(1, (rect.top - navBottom) / startTop))
}
const onScroll = () => setStarHintOpacity(compute())
onScroll()
window.addEventListener('scroll', onScroll, { passive: true })
return () => window.removeEventListener('scroll', onScroll)
window.addEventListener('resize', onScroll, { passive: true })
return () => {
window.removeEventListener('scroll', onScroll)
window.removeEventListener('resize', onScroll)
}
}, [])

const switchType = (next: string) => {
Expand Down Expand Up @@ -541,7 +549,16 @@ export default function App() {
href="#demo"
onClick={(e) => {
e.preventDefault()
document.getElementById('demo')?.scrollIntoView({ behavior: 'smooth' })
// Park the page at the demo section BEFORE expanding, so that
// when the user exits fullscreen they land on the playground
// instead of back at the hero. scrollTo is synchronous;
// scrollIntoView({smooth}) would be frozen mid-animation by
// the body.overflow=hidden expand triggers.
const demo = document.getElementById('demo')
// `behavior: 'instant'` overrides the html { scroll-behavior:
// smooth } rule; a smooth scroll here gets frozen mid-way by
// the body.overflow=hidden the useEffect triggers on expand.
if (demo) window.scrollTo({ top: demo.offsetTop - 20, behavior: 'instant' })
setExpandedAnimated(true)
}}
style={{
Expand Down