fukdufydsu commited on
Commit
c00d809
·
verified ·
1 Parent(s): 85a9555

Build a modern, minimalistic website that acts as a directory for AI-generated image prompt components and their corresponding output images.

Browse files

🧱 Style
Aesthetic: raw, cold, futuristic precision — think clean geometry, sharp edges, subtle lighting, and mechanical depth.
Color scheme: monochrome base palette (grays, white, and pure black) with optional dark/light mode toggle.
Typography: Geist font, large headings, tight line spacing, crisp contrast.
Visual motifs: subtle dots, lines, and grid overlays reminiscent of blueprints or schematics.
Layout: layered sections with slight shadows and parallax depth.
Animation: smooth, minimal micro-interactions — fades, slides, button hovers.
Art elements: optional ASCII-style dividers or corner markers for a raw computational vibe.
Responsiveness: fully adaptive for desktop and mobile while maintaining structural clarity.
⚙️ Function
The site reads entries from a CSV file with columns:
prompt: text describing the AI image component.
image: direct URL to the corresponding image.
tags: comma-separated list of keywords in brackets.
Each CSV row is rendered as a directory card:
Displays the image preview, the prompt text, and associated tags.
Includes a “Copy Prompt” button that copies the full prompt to the clipboard.
Option to reload or update the directory dynamically if the CSV changes.
Clean component structure (e.g., Card, Tag, SearchBar, FilterPanel).
🧭 UX / Interactivity
Interface focused on discoverability and speed:
Centralized directory grid with infinite scroll or lazy loading.
Search bar: filter entries by tag or keyword in real-time.
Tag filter chips: toggle tags to refine visible results.
Hover on images to reveal prompt text overlay.
Clear visual hierarchy: directory content is primary; UI chrome is secondary.
No unnecessary decoration — every element serves navigation, clarity, or functionality. ADD DEMO DATA IN PLACE OF THE CSV I WILL ADD THAT LATER THIS IS FOR PROOF OF CONCEPT

Files changed (7) hide show
  1. README.md +8 -5
  2. components/footer.js +92 -0
  3. components/header.js +109 -0
  4. components/searchBar.js +73 -0
  5. index.html +55 -19
  6. script.js +193 -0
  7. style.css +144 -18
README.md CHANGED
@@ -1,10 +1,13 @@
1
  ---
2
- title: Promptforge
3
- emoji: 📚
4
- colorFrom: indigo
5
- colorTo: yellow
6
  sdk: static
7
  pinned: false
 
 
8
  ---
9
 
10
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
1
  ---
2
+ title: PromptForge 🏗️
3
+ colorFrom: yellow
4
+ colorTo: gray
5
+ emoji: 🐳
6
  sdk: static
7
  pinned: false
8
+ tags:
9
+ - deepsite-v3
10
  ---
11
 
12
+ # Welcome to your new DeepSite project!
13
+ This project was created with [DeepSite](https://huggingface.co/deepsite).
components/footer.js ADDED
@@ -0,0 +1,92 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ class CustomFooter extends HTMLElement {
2
+ connectedCallback() {
3
+ this.attachShadow({ mode: 'open' });
4
+ this.shadowRoot.innerHTML = `
5
+ <style>
6
+ :host {
7
+ display: block;
8
+ margin-top: 4rem;
9
+ }
10
+
11
+ footer {
12
+ background: rgba(255, 255, 255, 0.8);
13
+ backdrop-filter: blur(10px);
14
+ border-top: 1px solid rgba(0, 0, 0, 0.05);
15
+ padding: 2rem 0;
16
+ }
17
+
18
+ .dark footer {
19
+ background: rgba(15, 15, 15, 0.8);
20
+ border-top: 1px solid rgba(255, 255, 255, 0.05);
21
+ }
22
+
23
+ .container {
24
+ max-width: 1200px;
25
+ margin: 0 auto;
26
+ padding: 0 1rem;
27
+ }
28
+
29
+ .footer-content {
30
+ display: flex;
31
+ flex-direction: column;
32
+ align-items: center;
33
+ gap: 1.5rem;
34
+ }
35
+
36
+ .ascii-divider {
37
+ font-family: monospace;
38
+ letter-spacing: -0.2em;
39
+ opacity: 0.3;
40
+ }
41
+
42
+ .footer-links {
43
+ display: flex;
44
+ gap: 1.5rem;
45
+ }
46
+
47
+ .footer-links a {
48
+ color: #6b7280;
49
+ text-decoration: none;
50
+ transition: color 0.2s;
51
+ }
52
+
53
+ .dark .footer-links a {
54
+ color: #9ca3af;
55
+ }
56
+
57
+ .footer-links a:hover {
58
+ color: #111827;
59
+ }
60
+
61
+ .dark .footer-links a:hover {
62
+ color: #f9fafb;
63
+ }
64
+
65
+ .copyright {
66
+ color: #9ca3af;
67
+ font-size: 0.875rem;
68
+ }
69
+
70
+ .dark .copyright {
71
+ color: #6b7280;
72
+ }
73
+ </style>
74
+ <footer>
75
+ <div class="container">
76
+ <div class="footer-content">
77
+ <div class="ascii-divider">+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+</div>
78
+ <div class="footer-links">
79
+ <a href="#">Terms</a>
80
+ <a href="#">Privacy</a>
81
+ <a href="#">Contact</a>
82
+ <a href="#">GitHub</a>
83
+ </div>
84
+ <div class="copyright">© 2023 PromptForge. All rights reserved.</div>
85
+ </div>
86
+ </div>
87
+ </footer>
88
+ `;
89
+ }
90
+ }
91
+
92
+ customElements.define('custom-footer', CustomFooter);
components/header.js ADDED
@@ -0,0 +1,109 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ class CustomHeader extends HTMLElement {
2
+ connectedCallback() {
3
+ this.attachShadow({ mode: 'open' });
4
+ this.shadowRoot.innerHTML = `
5
+ <style>
6
+ :host {
7
+ display: block;
8
+ }
9
+
10
+ header {
11
+ background: rgba(255, 255, 255, 0.8);
12
+ backdrop-filter: blur(10px);
13
+ border-bottom: 1px solid rgba(0, 0, 0, 0.05);
14
+ padding: 1rem 0;
15
+ }
16
+
17
+ .dark header {
18
+ background: rgba(15, 15, 15, 0.8);
19
+ border-bottom: 1px solid rgba(255, 255, 255, 0.05);
20
+ }
21
+
22
+ .container {
23
+ max-width: 1200px;
24
+ margin: 0 auto;
25
+ padding: 0 1rem;
26
+ display: flex;
27
+ justify-content: space-between;
28
+ align-items: center;
29
+ }
30
+
31
+ .logo {
32
+ font-size: 1.5rem;
33
+ font-weight: 700;
34
+ display: flex;
35
+ align-items: center;
36
+ gap: 0.5rem;
37
+ }
38
+
39
+ nav ul {
40
+ display: flex;
41
+ list-style: none;
42
+ gap: 1.5rem;
43
+ }
44
+
45
+ nav a {
46
+ text-decoration: none;
47
+ color: #6b7280;
48
+ font-weight: 500;
49
+ transition: color 0.2s;
50
+ position: relative;
51
+ }
52
+
53
+ .dark nav a {
54
+ color: #9ca3af;
55
+ }
56
+
57
+ nav a:hover {
58
+ color: #111827;
59
+ }
60
+
61
+ .dark nav a:hover {
62
+ color: #f9fafb;
63
+ }
64
+
65
+ nav a::after {
66
+ content: '';
67
+ position: absolute;
68
+ bottom: -5px;
69
+ left: 0;
70
+ width: 0;
71
+ height: 2px;
72
+ background: #111827;
73
+ transition: width 0.3s;
74
+ }
75
+
76
+ .dark nav a::after {
77
+ background: #f9fafb;
78
+ }
79
+
80
+ nav a:hover::after {
81
+ width: 100%;
82
+ }
83
+
84
+ @media (max-width: 768px) {
85
+ nav ul {
86
+ display: none;
87
+ }
88
+ }
89
+ </style>
90
+ <header>
91
+ <div class="container">
92
+ <div class="logo">
93
+ <span>🏗️</span>
94
+ <span>PromptForge</span>
95
+ </div>
96
+ <nav>
97
+ <ul>
98
+ <li><a href="/">Directory</a></li>
99
+ <li><a href="#">Submit</a></li>
100
+ <li><a href="#">About</a></li>
101
+ </ul>
102
+ </nav>
103
+ </div>
104
+ </header>
105
+ `;
106
+ }
107
+ }
108
+
109
+ customElements.define('custom-header', CustomHeader);
components/searchBar.js ADDED
@@ -0,0 +1,73 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ class CustomSearchBar extends HTMLElement {
2
+ connectedCallback() {
3
+ this.attachShadow({ mode: 'open' });
4
+ this.shadowRoot.innerHTML = `
5
+ <style>
6
+ :host {
7
+ display: block;
8
+ }
9
+
10
+ .search-container {
11
+ position: relative;
12
+ max-width: 600px;
13
+ margin: 0 auto;
14
+ }
15
+
16
+ .search-input {
17
+ width: 100%;
18
+ padding: 1rem 1rem 1rem 3rem;
19
+ border-radius: 50px;
20
+ border: 1px solid #e5e7eb;
21
+ background: #fff;
22
+ font-size: 1rem;
23
+ transition: all 0.3s;
24
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
25
+ }
26
+
27
+ .dark .search-input {
28
+ background: #1f2937;
29
+ border: 1px solid #374151;
30
+ color: #f9fafb;
31
+ }
32
+
33
+ .search-input:focus {
34
+ outline: none;
35
+ border-color: #6366f1;
36
+ box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.1);
37
+ }
38
+
39
+ .search-icon {
40
+ position: absolute;
41
+ left: 1rem;
42
+ top: 50%;
43
+ transform: translateY(-50%);
44
+ color: #9ca3af;
45
+ }
46
+
47
+ .dark .search-icon {
48
+ color: #6b7280;
49
+ }
50
+ </style>
51
+ <div class="search-container">
52
+ <i data-feather="search" class="search-icon w-5 h-5"></i>
53
+ <input type="text" class="search-input" placeholder="Search prompts or tags..." id="searchInput">
54
+ </div>
55
+ `;
56
+
57
+ // Add event listener after rendering
58
+ setTimeout(() => {
59
+ const searchInput = this.shadowRoot.getElementById('searchInput');
60
+ searchInput.addEventListener('input', (e) => {
61
+ // Access the global search function
62
+ if (typeof searchPrompts === 'function') {
63
+ searchPrompts(e.target.value);
64
+ }
65
+ });
66
+
67
+ // Initialize feather icons
68
+ feather.replace();
69
+ }, 0);
70
+ }
71
+ }
72
+
73
+ customElements.define('custom-search-bar', CustomSearchBar);
index.html CHANGED
@@ -1,19 +1,55 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
19
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>PromptForge - AI Image Prompt Directory</title>
7
+ <link rel="icon" type="image/x-icon" href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text y=%22.9em%22 font-size=%2290%22>🏗️</text></svg>">
8
+ <link rel="stylesheet" href="style.css">
9
+ <script src="https://cdn.tailwindcss.com"></script>
10
+ <script src="https://cdn.jsdelivr.net/npm/feather-icons/dist/feather.min.js"></script>
11
+ <script src="https://unpkg.com/feather-icons"></script>
12
+ <link href="https://fonts.googleapis.com/css2?family=Geist:wght@100;200;300;400;500;600;700;800;900&display=swap" rel="stylesheet">
13
+ </head>
14
+ <body class="bg-gray-50 dark:bg-gray-900 text-gray-900 dark:text-gray-100 font-['Geist'] transition-colors duration-300">
15
+ <custom-header></custom-header>
16
+
17
+ <main class="container mx-auto px-4 py-8">
18
+ <div class="flex flex-col md:flex-row justify-between items-start md:items-center mb-8 gap-4">
19
+ <div>
20
+ <h1 class="text-3xl md:text-4xl font-bold">AI Image Prompt Directory</h1>
21
+ <p class="text-gray-600 dark:text-gray-400 mt-2">Discover and copy prompts for AI-generated images</p>
22
+ </div>
23
+ <div class="flex gap-2">
24
+ <button id="toggleDarkMode" class="p-2 rounded-lg bg-gray-200 dark:bg-gray-700 hover:bg-gray-300 dark:hover:bg-gray-600 transition-colors">
25
+ <i data-feather="moon" class="w-5 h-5 dark:hidden"></i>
26
+ <i data-feather="sun" class="w-5 h-5 hidden dark:block"></i>
27
+ </button>
28
+ </div>
29
+ </div>
30
+
31
+ <div class="mb-8">
32
+ <custom-search-bar></custom-search-bar>
33
+ </div>
34
+
35
+ <div class="mb-6 flex flex-wrap gap-2" id="tagFilters">
36
+ <!-- Tags will be populated by JS -->
37
+ </div>
38
+
39
+ <div id="promptGrid" class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
40
+ <!-- Cards will be populated by JS -->
41
+ </div>
42
+ </main>
43
+
44
+ <custom-footer></custom-footer>
45
+
46
+ <script src="components/header.js"></script>
47
+ <script src="components/searchBar.js"></script>
48
+ <script src="components/footer.js"></script>
49
+ <script src="script.js"></script>
50
+ <script>
51
+ feather.replace();
52
+ </script>
53
+ <script src="https://huggingface.co/deepsite/deepsite-badge.js"></script>
54
+ </body>
55
+ </html>
script.js ADDED
@@ -0,0 +1,193 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Demo data for proof of concept
2
+ const demoData = [
3
+ {
4
+ prompt: "A futuristic cityscape at night with neon lights reflecting on wet streets, cyberpunk aesthetic, cinematic lighting, 8k resolution",
5
+ image: "http://static.photos/cityscape/640x360/1",
6
+ tags: ["cyberpunk", "futuristic", "night", "urban"]
7
+ },
8
+ {
9
+ prompt: "Minimalist interior design with clean lines, natural light, Scandinavian style, wooden furniture, plants, soft textures",
10
+ image: "http://static.photos/interior/640x360/2",
11
+ tags: ["minimalist", "scandinavian", "interior", "natural"]
12
+ },
13
+ {
14
+ prompt: "Abstract geometric patterns with vibrant colors, digital art, fractal designs, high detail, symmetrical composition",
15
+ image: "http://static.photos/abstract/640x360/3",
16
+ tags: ["abstract", "geometric", "digital", "vibrant"]
17
+ },
18
+ {
19
+ prompt: "Steampunk airship flying over Victorian-era city, brass and copper details, mechanical wings, cloudy sky, detailed machinery",
20
+ image: "http://static.photos/technology/640x360/4",
21
+ tags: ["steampunk", "victorian", "airship", "mechanical"]
22
+ },
23
+ {
24
+ prompt: "Underwater coral reef with bioluminescent creatures, deep sea colors, mysterious atmosphere, high detail, 4k resolution",
25
+ image: "http://static.photos/nature/640x360/5",
26
+ tags: ["underwater", "bioluminescent", "nature", "mysterious"]
27
+ },
28
+ {
29
+ prompt: "Space station orbiting a gas giant planet, futuristic architecture, stars in background, cinematic composition, NASA aesthetic",
30
+ image: "http://static.photos/space/640x360/6",
31
+ tags: ["space", "futuristic", "cinematic", "science"]
32
+ },
33
+ {
34
+ prompt: "Vintage film noir scene with detective in trench coat, rainy street, neon signs, dramatic shadows, black and white with selective color",
35
+ image: "http://static.photos/cityscape/640x360/7",
36
+ tags: ["noir", "vintage", "detective", "dramatic"]
37
+ },
38
+ {
39
+ prompt: "Fantasy forest with glowing mushrooms, magical creatures, ethereal lighting, detailed environment, concept art style",
40
+ image: "http://static.photos/nature/640x360/8",
41
+ tags: ["fantasy", "magical", "forest", "ethereal"]
42
+ },
43
+ {
44
+ prompt: "Industrial robot arm assembling circuit boards, factory setting, metallic textures, sparks, high-tech machinery, detailed mechanics",
45
+ image: "http://static.photos/technology/640x360/9",
46
+ tags: ["industrial", "robotic", "technology", "mechanical"]
47
+ }
48
+ ];
49
+
50
+ let allTags = [];
51
+ let currentFilter = '';
52
+ let filteredData = [...demoData];
53
+
54
+ // Initialize the page
55
+ document.addEventListener('DOMContentLoaded', () => {
56
+ // Extract all unique tags
57
+ demoData.forEach(item => {
58
+ item.tags.forEach(tag => {
59
+ if (!allTags.includes(tag)) {
60
+ allTags.push(tag);
61
+ }
62
+ });
63
+ });
64
+
65
+ renderTagFilters();
66
+ renderPromptCards();
67
+
68
+ // Set up dark mode toggle
69
+ const toggleButton = document.getElementById('toggleDarkMode');
70
+ toggleButton.addEventListener('click', () => {
71
+ document.documentElement.classList.toggle('dark');
72
+ localStorage.setItem('darkMode', document.documentElement.classList.contains('dark'));
73
+ feather.replace();
74
+ });
75
+
76
+ // Check for saved dark mode preference
77
+ if (localStorage.getItem('darkMode') === 'true') {
78
+ document.documentElement.classList.add('dark');
79
+ }
80
+
81
+ // Add grid overlay
82
+ const gridOverlay = document.createElement('div');
83
+ gridOverlay.className = 'grid-overlay';
84
+ document.body.appendChild(gridOverlay);
85
+ });
86
+
87
+ // Render tag filter chips
88
+ function renderTagFilters() {
89
+ const container = document.getElementById('tagFilters');
90
+ container.innerHTML = '<button class="tag px-3 py-1 bg-gray-200 dark:bg-gray-700 rounded-full text-sm hover:bg-gray-300 dark:hover:bg-gray-600 transition-colors" data-tag="">All</button>';
91
+
92
+ allTags.forEach(tag => {
93
+ const tagButton = document.createElement('button');
94
+ tagButton.className = 'tag px-3 py-1 bg-gray-200 dark:bg-gray-700 rounded-full text-sm hover:bg-gray-300 dark:hover:bg-gray-600 transition-colors';
95
+ tagButton.textContent = tag;
96
+ tagButton.dataset.tag = tag;
97
+ tagButton.addEventListener('click', () => {
98
+ document.querySelectorAll('.tag').forEach(btn => btn.classList.remove('bg-blue-500', 'dark:bg-blue-600', 'text-white'));
99
+ tagButton.classList.add('bg-blue-500', 'dark:bg-blue-600', 'text-white');
100
+ currentFilter = tag;
101
+ filterPrompts();
102
+ });
103
+ container.appendChild(tagButton);
104
+ });
105
+ }
106
+
107
+ // Render prompt cards
108
+ function renderPromptCards() {
109
+ const container = document.getElementById('promptGrid');
110
+ container.innerHTML = '';
111
+
112
+ filteredData.forEach(item => {
113
+ const card = document.createElement('div');
114
+ card.className = 'prompt-card bg-white dark:bg-gray-800 rounded-xl overflow-hidden shadow-md hover:shadow-xl transition-shadow duration-300';
115
+ card.innerHTML = `
116
+ <div class="relative">
117
+ <img src="${item.image}" alt="AI-generated image" class="w-full h-48 object-cover">
118
+ <div class="prompt-overlay absolute inset-0 flex items-center justify-center opacity-0 hover:opacity-100 p-4">
119
+ <p class="text-white text-center text-sm">${item.prompt}</p>
120
+ </div>
121
+ <div class="absolute top-2 right-2">
122
+ <button class="copy-btn bg-white dark:bg-gray-700 p-2 rounded-full shadow-md" data-prompt="${item.prompt.replace(/"/g, '&quot;')}">
123
+ <i data-feather="copy" class="w-4 h-4"></i>
124
+ </button>
125
+ </div>
126
+ </div>
127
+ <div class="p-4">
128
+ <div class="flex flex-wrap gap-2 mb-3">
129
+ ${item.tags.map(tag => `<span class="px-2 py-1 bg-gray-100 dark:bg-gray-700 text-xs rounded">${tag}</span>`).join('')}
130
+ </div>
131
+ <button class="copy-btn w-full py-2 bg-gray-100 dark:bg-gray-700 rounded-lg text-sm flex items-center justify-center gap-2 hover:bg-gray-200 dark:hover:bg-gray-600 transition-colors" data-prompt="${item.prompt.replace(/"/g, '&quot;')}">
132
+ <i data-feather="copy" class="w-4 h-4"></i>
133
+ Copy Prompt
134
+ </button>
135
+ </div>
136
+ `;
137
+ container.appendChild(card);
138
+ });
139
+
140
+ // Initialize feather icons
141
+ feather.replace();
142
+
143
+ // Add event listeners to copy buttons
144
+ document.querySelectorAll('.copy-btn').forEach(button => {
145
+ button.addEventListener('click', (e) => {
146
+ const prompt = e.currentTarget.dataset.prompt;
147
+ navigator.clipboard.writeText(prompt).then(() => {
148
+ // Show feedback
149
+ const originalHTML = e.currentTarget.innerHTML;
150
+ e.currentTarget.innerHTML = '<i data-feather="check" class="w-4 h-4"></i> Copied!';
151
+ feather.replace();
152
+
153
+ setTimeout(() => {
154
+ e.currentTarget.innerHTML = originalHTML;
155
+ feather.replace();
156
+ }, 2000);
157
+ });
158
+ });
159
+ });
160
+ }
161
+
162
+ // Filter prompts based on current filter
163
+ function filterPrompts() {
164
+ if (currentFilter === '') {
165
+ filteredData = [...demoData];
166
+ } else {
167
+ filteredData = demoData.filter(item =>
168
+ item.tags.includes(currentFilter)
169
+ );
170
+ }
171
+
172
+ renderPromptCards();
173
+ }
174
+
175
+ // Search functionality (to be implemented with real search bar)
176
+ function searchPrompts(query) {
177
+ if (!query) {
178
+ filteredData = currentFilter ? demoData.filter(item => item.tags.includes(currentFilter)) : [...demoData];
179
+ } else {
180
+ const lowerQuery = query.toLowerCase();
181
+ filteredData = demoData.filter(item =>
182
+ item.prompt.toLowerCase().includes(lowerQuery) ||
183
+ item.tags.some(tag => tag.toLowerCase().includes(lowerQuery))
184
+ );
185
+
186
+ // If we have a tag filter, apply it as well
187
+ if (currentFilter) {
188
+ filteredData = filteredData.filter(item => item.tags.includes(currentFilter));
189
+ }
190
+ }
191
+
192
+ renderPromptCards();
193
+ }
style.css CHANGED
@@ -1,28 +1,154 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
  body {
2
- padding: 2rem;
3
- font-family: -apple-system, BlinkMacSystemFont, "Arial", sans-serif;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4
  }
5
 
6
- h1 {
7
- font-size: 16px;
8
- margin-top: 0;
9
  }
10
 
11
- p {
12
- color: rgb(107, 114, 128);
13
- font-size: 15px;
14
- margin-bottom: 10px;
15
- margin-top: 5px;
16
  }
17
 
18
- .card {
19
- max-width: 620px;
20
- margin: 0 auto;
21
- padding: 16px;
22
- border: 1px solid lightgray;
23
- border-radius: 16px;
24
  }
25
 
26
- .card p:last-child {
27
- margin-bottom: 0;
 
28
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ @import url('https://fonts.googleapis.com/css2?family=Geist:wght@100;200;300;400;500;600;700;800;900&display=swap');
2
+
3
+ :root {
4
+ --grid-color: rgba(0, 0, 0, 0.05);
5
+ --dot-size: 1px;
6
+ --dot-space: 20px;
7
+ }
8
+
9
+ .dark {
10
+ --grid-color: rgba(255, 255, 255, 0.05);
11
+ }
12
+
13
  body {
14
+ font-family: 'Geist', sans-serif;
15
+ background-color: #fafafa;
16
+ background-image: radial-gradient(var(--grid-color) var(--dot-size), transparent var(--dot-size)),
17
+ radial-gradient(var(--grid-color) var(--dot-size), transparent var(--dot-size));
18
+ background-position: 0 0, calc(var(--dot-space) / 2) calc(var(--dot-space) / 2);
19
+ background-size: var(--dot-space) var(--dot-space);
20
+ min-height: 100vh;
21
+ }
22
+
23
+ .dark body {
24
+ background-color: #0a0a0a;
25
+ }
26
+
27
+ .prompt-card {
28
+ transition: transform 0.3s ease, box-shadow 0.3s ease;
29
+ box-shadow: 0 4px 6px rgba(0, 0, 0, 0.05);
30
+ border: 1px solid rgba(0, 0, 0, 0.05);
31
+ }
32
+
33
+ .prompt-card:hover {
34
+ transform: translateY(-5px);
35
+ box-shadow: 0 10px 15px rgba(0, 0, 0, 0.1);
36
+ }
37
+
38
+ .dark .prompt-card {
39
+ border: 1px solid rgba(255, 255, 255, 0.05);
40
+ box-shadow: 0 4px 6px rgba(0, 0, 0, 0.2);
41
+ }
42
+
43
+ .dark .prompt-card:hover {
44
+ box-shadow: 0 10px 15px rgba(0, 0, 0, 0.3);
45
+ }
46
+
47
+ .tag {
48
+ transition: all 0.2s ease;
49
+ }
50
+
51
+ .tag:hover {
52
+ transform: scale(1.05);
53
+ }
54
+
55
+ .copy-btn {
56
+ transition: all 0.2s ease;
57
  }
58
 
59
+ .copy-btn:hover {
60
+ background-color: #e5e7eb;
 
61
  }
62
 
63
+ .dark .copy-btn:hover {
64
+ background-color: #374151;
 
 
 
65
  }
66
 
67
+ .prompt-overlay {
68
+ background: rgba(0, 0, 0, 0.7);
69
+ backdrop-filter: blur(4px);
70
+ transition: opacity 0.3s ease;
 
 
71
  }
72
 
73
+ /* Custom scrollbar */
74
+ ::-webkit-scrollbar {
75
+ width: 8px;
76
  }
77
+
78
+ ::-webkit-scrollbar-track {
79
+ background: transparent;
80
+ }
81
+
82
+ ::-webkit-scrollbar-thumb {
83
+ background: #d1d5db;
84
+ border-radius: 4px;
85
+ }
86
+
87
+ .dark ::-webkit-scrollbar-thumb {
88
+ background: #4b5563;
89
+ }
90
+
91
+ /* ASCII-style divider */
92
+ .ascii-divider {
93
+ font-family: monospace;
94
+ letter-spacing: -0.2em;
95
+ opacity: 0.3;
96
+ margin: 2rem 0;
97
+ }
98
+
99
+ /* Blueprint grid overlay */
100
+ .grid-overlay {
101
+ position: fixed;
102
+ top: 0;
103
+ left: 0;
104
+ width: 100%;
105
+ height: 100%;
106
+ pointer-events: none;
107
+ background-image:
108
+ linear-gradient(rgba(0, 0, 0, 0.03) 1px, transparent 1px),
109
+ linear-gradient(90deg, rgba(0, 0, 0, 0.03) 1px, transparent 1px);
110
+ background-size: 20px 20px;
111
+ z-index: -1;
112
+ }
113
+
114
+ .dark .grid-overlay {
115
+ background-image:
116
+ linear-gradient(rgba(255, 255, 255, 0.03) 1px, transparent 1px),
117
+ linear-gradient(90deg, rgba(255, 255, 255, 0.03) 1px, transparent 1px);
118
+ }
119
+
120
+ /* Corner markers */
121
+ .corner-marker {
122
+ position: absolute;
123
+ width: 20px;
124
+ height: 20px;
125
+ border: 1px solid currentColor;
126
+ }
127
+
128
+ .corner-marker.top-left {
129
+ top: 0;
130
+ left: 0;
131
+ border-right: none;
132
+ border-bottom: none;
133
+ }
134
+
135
+ .corner-marker.top-right {
136
+ top: 0;
137
+ right: 0;
138
+ border-left: none;
139
+ border-bottom: none;
140
+ }
141
+
142
+ .corner-marker.bottom-left {
143
+ bottom: 0;
144
+ left: 0;
145
+ border-right: none;
146
+ border-top: none;
147
+ }
148
+
149
+ .corner-marker.bottom-right {
150
+ bottom: 0;
151
+ right: 0;
152
+ border-left: none;
153
+ border-top: none;
154
+ }