Skip to content

Commit 69469a3

Browse files
gkamradtclaude
andcommitted
feat: add image copy functionality and OG meta tags
- Add "Copy Image" button to ASCII typer page alongside existing text copy - Implement html2canvas integration for high-quality image capture - Add clipboard API support with fallback to download - Set OG image to /og.png and description to "10x vibe for .1x work" - Update UI to clearly distinguish between text and image copy options 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent c925e43 commit 69469a3

File tree

5 files changed

+115
-8
lines changed

5 files changed

+115
-8
lines changed

index.html

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,21 @@
55
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
66
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
77
<title>I Vibe More Than You</title>
8+
9+
<!-- Open Graph / Facebook -->
10+
<meta property="og:type" content="website" />
11+
<meta property="og:title" content="I Vibe More Than You" />
12+
<meta property="og:description" content="10x vibe for .1x work" />
13+
<meta property="og:image" content="/og.png" />
14+
15+
<!-- Twitter -->
16+
<meta property="twitter:card" content="summary_large_image" />
17+
<meta property="twitter:title" content="I Vibe More Than You" />
18+
<meta property="twitter:description" content="10x vibe for .1x work" />
19+
<meta property="twitter:image" content="/og.png" />
20+
21+
<!-- General -->
22+
<meta name="description" content="10x vibe for .1x work" />
823
</head>
924
<body>
1025
<div id="root"></div>

package-lock.json

Lines changed: 45 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
},
1616
"dependencies": {
1717
"@vercel/analytics": "^1.5.0",
18+
"html2canvas": "^1.4.1",
1819
"react": "^18.2.0",
1920
"react-dom": "^18.2.0",
2021
"react-draggable": "^4.4.6",

public/og.png

54.2 KB
Loading

src/pages/AsciiTyper.tsx

Lines changed: 54 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { useState } from 'react';
1+
import { useState, useRef } from 'react';
22
import { generateAsciiArt } from '../utils/asciiArt';
33

44
interface TextLine {
@@ -27,6 +27,7 @@ export function AsciiTyper() {
2727
]);
2828
const [backgroundColor, setBackgroundColor] = useState('#000000');
2929
const [textColor, setTextColor] = useState('#22c55e');
30+
const previewRef = useRef<HTMLDivElement>(null);
3031

3132
const addNewLine = () => {
3233
const newId = Date.now().toString();
@@ -73,6 +74,42 @@ export function AsciiTyper() {
7374
navigator.clipboard.writeText(asciiText);
7475
};
7576

77+
const copyImageToClipboard = async () => {
78+
if (!previewRef.current) return;
79+
80+
try {
81+
// Use html2canvas to capture the preview area
82+
const html2canvas = (await import('html2canvas')).default;
83+
const canvas = await html2canvas(previewRef.current, {
84+
backgroundColor: backgroundColor,
85+
scale: 2, // Higher resolution
86+
useCORS: true,
87+
});
88+
89+
// Convert canvas to blob
90+
canvas.toBlob(async (blob) => {
91+
if (!blob) return;
92+
93+
try {
94+
await navigator.clipboard.write([
95+
new ClipboardItem({ 'image/png': blob })
96+
]);
97+
} catch (error) {
98+
console.error('Failed to copy image to clipboard:', error);
99+
// Fallback: create download link
100+
const url = URL.createObjectURL(blob);
101+
const a = document.createElement('a');
102+
a.href = url;
103+
a.download = 'ascii-art.png';
104+
a.click();
105+
URL.revokeObjectURL(url);
106+
}
107+
}, 'image/png');
108+
} catch (error) {
109+
console.error('Failed to capture image:', error);
110+
}
111+
};
112+
76113
return (
77114
<div
78115
className="h-screen overflow-y-auto p-8 transition-colors duration-300"
@@ -95,15 +132,24 @@ export function AsciiTyper() {
95132
<h3 className="text-lg font-semibold" style={{ color: textColor }}>
96133
ASCII Preview
97134
</h3>
98-
<button
99-
onClick={copyToClipboard}
100-
className="px-4 py-2 bg-green-600 hover:bg-green-700 text-white rounded transition-colors"
101-
>
102-
Copy to Clipboard
103-
</button>
135+
<div className="flex gap-2">
136+
<button
137+
onClick={copyToClipboard}
138+
className="px-4 py-2 bg-green-600 hover:bg-green-700 text-white rounded transition-colors"
139+
>
140+
Copy Text
141+
</button>
142+
<button
143+
onClick={copyImageToClipboard}
144+
className="px-4 py-2 bg-purple-600 hover:bg-purple-700 text-white rounded transition-colors"
145+
>
146+
Copy Image
147+
</button>
148+
</div>
104149
</div>
105150

106151
<div
152+
ref={previewRef}
107153
className="p-6 rounded-lg border-2 font-mono text-xs leading-tight overflow-auto"
108154
style={{
109155
backgroundColor: backgroundColor,
@@ -222,7 +268,7 @@ export function AsciiTyper() {
222268
<p>• Type in the text fields above to see ASCII art generated in real-time</p>
223269
<p>• Use the + button to add new lines</p>
224270
<p>• Customize colors using the color pickers or preset swatches</p>
225-
<p>• Copy the generated ASCII art to use elsewhere</p>
271+
<p>• Copy the generated ASCII art as text or image to use elsewhere</p>
226272
</div>
227273
</div>
228274
</div>

0 commit comments

Comments
 (0)