flitrx commited on
Commit
b644d60
·
verified ·
1 Parent(s): a2fefe3

Design a neomorphic AI art gallery website using GraphQL with progressive web app. Provide detailed specifications for user experience, technical architecture, and monetization strategy.

Browse files
Files changed (11) hide show
  1. README.md +8 -5
  2. components/artwork-card.js +209 -0
  3. components/footer.js +143 -0
  4. components/navbar.js +199 -0
  5. gallery.html +85 -0
  6. index.html +122 -19
  7. manifest.json +68 -0
  8. script.js +225 -0
  9. style.css +99 -18
  10. sw.js +92 -0
  11. upload.html +208 -0
README.md CHANGED
@@ -1,10 +1,13 @@
1
  ---
2
- title: Neuromorph Gallery
3
- emoji: 🔥
4
- colorFrom: green
5
- colorTo: gray
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: NeuroMorph Gallery 🧠
3
+ colorFrom: yellow
4
+ colorTo: red
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://deepsite.hf.co).
components/artwork-card.js ADDED
@@ -0,0 +1,209 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ class ArtworkCard extends HTMLElement {
2
+ connectedCallback() {
3
+ const artworkData = JSON.parse(this.getAttribute('data-artwork'));
4
+ this.attachShadow({ mode: 'open' });
5
+ this.shadowRoot.innerHTML = `
6
+ <style>
7
+ .artwork-card {
8
+ background: linear-gradient(145deg, #ffffff, #e6e6e6);
9
+ border-radius: 20px;
10
+ padding: 1.5rem;
11
+ transition: all 0.3s ease;
12
+ cursor: pointer;
13
+ position: relative;
14
+ overflow: hidden;
15
+ }
16
+
17
+ .artwork-card:hover {
18
+ transform: translateY(-8px);
19
+ box-shadow: 15px 15px 30px #c9c9c9, -15px -15px 30px #ffffff;
20
+ }
21
+
22
+ .artwork-image {
23
+ width: 100%;
24
+ height: 250px;
25
+ object-fit: cover;
26
+ border-radius: 15px;
27
+ margin-bottom: 1rem;
28
+ transition: transform 0.3s ease;
29
+ }
30
+
31
+ .artwork-card:hover .artwork-image {
32
+ transform: scale(1.05);
33
+ }
34
+
35
+ .artwork-title {
36
+ font-size: 1.25rem;
37
+ font-weight: 700;
38
+ color: #1f2937;
39
+ margin-bottom: 0.5rem;
40
+ }
41
+
42
+ .artwork-description {
43
+ color: #6b7280;
44
+ font-size: 0.875rem;
45
+ margin-bottom: 1rem;
46
+ display: -webkit-box;
47
+ -webkit-line-clamp: 2;
48
+ -webkit-box-orient: vertical;
49
+ overflow: hidden;
50
+ }
51
+
52
+ .artist-info {
53
+ display: flex;
54
+ align-items: center;
55
+ gap: 0.75rem;
56
+ margin-bottom: 1rem;
57
+ }
58
+
59
+ .artist-avatar {
60
+ width: 40px;
61
+ height: 40px;
62
+ border-radius: 50%;
63
+ object-fit: cover;
64
+ }
65
+
66
+ .artist-name {
67
+ color: #4b5563;
68
+ font-weight: 500;
69
+ }
70
+
71
+ .artwork-stats {
72
+ display: flex;
73
+ justify-content: space-between;
74
+ align-items: center;
75
+ margin-top: 1rem;
76
+ }
77
+
78
+ .stat {
79
+ display: flex;
80
+ align-items: center;
81
+ gap: 0.25rem;
82
+ color: #6b7280;
83
+ font-size: 0.875rem;
84
+ }
85
+
86
+ .tags {
87
+ display: flex;
88
+ flex-wrap: wrap;
89
+ gap: 0.5rem;
90
+ margin-top: 1rem;
91
+ }
92
+
93
+ .tag {
94
+ background: linear-gradient(135deg, #f97316, #fb923c);
95
+ color: white;
96
+ padding: 0.25rem 0.75rem;
97
+ border-radius: 15px;
98
+ font-size: 0.75rem;
99
+ font-weight: 500;
100
+ }
101
+
102
+ .like-btn {
103
+ background: none;
104
+ border: none;
105
+ color: #ef4444;
106
+ cursor: pointer;
107
+ transition: transform 0.2s ease;
108
+ }
109
+
110
+ .like-btn:hover {
111
+ transform: scale(1.1);
112
+ }
113
+
114
+ .premium-badge {
115
+ position: absolute;
116
+ top: 1rem;
117
+ right: 1rem;
118
+ background: linear-gradient(135deg, #fbbf24, #f59e0b);
119
+ color: #1f2937;
120
+ padding: 0.25rem 0.75rem;
121
+ border-radius: 12px;
122
+ font-size: 0.75rem;
123
+ font-weight: 600;
124
+ }
125
+ </style>
126
+
127
+ <div class="artwork-card neomorphic-card">
128
+ ${artworkData.premium ? '<div class="premium-badge">Premium</div>' : ''}
129
+
130
+ <img
131
+ src="${artworkData.imageUrl}"
132
+ alt="${artworkData.title}"
133
+ class="artwork-image"
134
+ loading="lazy"
135
+ >
136
+
137
+ <h3 class="artwork-title">${artworkData.title}</h3>
138
+
139
+ <p class="artwork-description">${artworkData.description}</p>
140
+
141
+ <div class="artist-info">
142
+ <img
143
+ src="${artworkData.artist.avatar}"
144
+ alt="${artworkData.artist.name}"
145
+ class="artist-avatar"
146
+ >
147
+ <span class="artist-name">${artworkData.artist.name}</span>
148
+ </div>
149
+
150
+ <div class="tags">
151
+ ${artworkData.tags.map(tag => `<span class="tag">${tag}</span>`).join('')}
152
+
153
+ <div class="artwork-stats">
154
+ <div class="stat">
155
+ <i data-feather="eye"></i>
156
+ <span>${artworkData.views.toLocaleString()}</span>
157
+ </div>
158
+
159
+ <button class="like-btn">
160
+ <i data-feather="heart"></i>
161
+ <span>${artworkData.likes.toLocaleString()}</span>
162
+ </div>
163
+ </div>
164
+ </div>
165
+ `;
166
+
167
+ this.setupInteractions();
168
+ }
169
+
170
+ setupInteractions() {
171
+ const likeBtn = this.shadowRoot.querySelector('.like-btn');
172
+ const card = this.shadowRoot.querySelector('.artwork-card');
173
+
174
+ likeBtn.addEventListener('click', (e) => {
175
+ e.stopPropagation();
176
+ this.toggleLike();
177
+ });
178
+
179
+ card.addEventListener('click', () => {
180
+ this.viewArtworkDetails();
181
+ });
182
+ }
183
+
184
+ toggleLike() {
185
+ const heartIcon = this.shadowRoot.querySelector('.like-btn i');
186
+ const likesCount = this.shadowRoot.querySelector('.like-btn span');
187
+
188
+ let currentLikes = parseInt(likesCount.textContent.replace(/,/g, '')) || 0;
189
+
190
+ if (heartIcon.getAttribute('data-feather') === 'heart') {
191
+ heartIcon.setAttribute('data-feather', 'heart');
192
+ likesCount.textContent = (currentLikes + 1).toLocaleString();
193
+ } else {
194
+ heartIcon.setAttribute('data-feather', 'heart');
195
+ likesCount.textContent = (currentLikes - 1).toLocaleString();
196
+ }
197
+
198
+ feather.replace();
199
+ }
200
+
201
+ viewArtworkDetails() {
202
+ const artworkData = JSON.parse(this.getAttribute('data-artwork'));
203
+
204
+ // Navigate to artwork details page
205
+ window.location.href = `/artwork.html?id=${artworkData.id}`;
206
+ }
207
+ }
208
+
209
+ customElements.define('artwork-card', ArtworkCard);
components/footer.js ADDED
@@ -0,0 +1,143 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ class CustomFooter extends HTMLElement {
2
+ connectedCallback() {
3
+ this.attachShadow({ mode: 'open' });
4
+ this.shadowRoot.innerHTML = `
5
+ <style>
6
+ footer {
7
+ background: linear-gradient(135deg, #111827 0%, #1f2937 100%);
8
+ color: white;
9
+ padding: 3rem 2rem;
10
+ margin-top: auto;
11
+ }
12
+
13
+ .footer-content {
14
+ max-width: 7xl;
15
+ margin: 0 auto;
16
+ display: grid;
17
+ grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
18
+ gap: 2rem;
19
+ }
20
+
21
+ .footer-section h3 {
22
+ color: #f97316;
23
+ margin-bottom: 1rem;
24
+ font-weight: 600;
25
+ }
26
+
27
+ .footer-links {
28
+ list-style: none;
29
+ padding: 0;
30
+ margin: 0;
31
+ }
32
+
33
+ .footer-links li {
34
+ margin-bottom: 0.5rem;
35
+ }
36
+
37
+ .footer-links a {
38
+ color: #d1d5db;
39
+ text-decoration: none;
40
+ transition: color 0.3s ease;
41
+ }
42
+
43
+ .footer-links a:hover {
44
+ color: #f97316;
45
+ }
46
+
47
+ .social-links {
48
+ display: flex;
49
+ gap: 1rem;
50
+ margin-top: 1rem;
51
+ }
52
+
53
+ .social-links a {
54
+ color: #d1d5db;
55
+ transition: color 0.3s ease;
56
+ }
57
+
58
+ .social-links a:hover {
59
+ color: #0ea5e9;
60
+ }
61
+
62
+ .footer-bottom {
63
+ border-top: 1px solid #374151;
64
+ padding-top: 2rem;
65
+ margin-top: 2rem;
66
+ text-align: center;
67
+ }
68
+
69
+ .newsletter-input {
70
+ background: rgba(255, 255, 255, 0.1);
71
+ border: 1px solid rgba(255, 255, 255, 0.2);
72
+ border-radius: 8px;
73
+ padding: 0.75rem 1rem;
74
+ color: white;
75
+ width: 100%;
76
+ margin-bottom: 1rem;
77
+ }
78
+
79
+ .newsletter-input:focus {
80
+ outline: none;
81
+ border-color: #0ea5e9;
82
+ }
83
+
84
+ @media (max-width: 768px) {
85
+ footer {
86
+ padding: 2rem 1rem;
87
+ }
88
+ }
89
+ </style>
90
+ <footer>
91
+ <div class="footer-content">
92
+ <div class="footer-section">
93
+ <h3>NeuroMorph Gallery</h3>
94
+ <p>Where artificial intelligence meets artistic expression in a neomorphic digital realm.</p>
95
+ <div class="social-links">
96
+ <a href="#"><i data-feather="twitter"></i></a>
97
+ <a href="#"><i data-feather="instagram"></i></a>
98
+ <a href="#"><i data-feather="github"></i></a>
99
+ <a href="#"><i data-feather="discord"></i></a>
100
+ </div>
101
+ </div>
102
+
103
+ <div class="footer-section">
104
+ <h3>Explore</h3>
105
+ <ul class="footer-links">
106
+ <li><a href="/gallery.html">Featured Artworks</a></li>
107
+ <li><a href="/artists.html">AI Artists</a></li>
108
+ <li><a href="/collections.html">Collections</a></li>
109
+ <li><a href="/trending.html">Trending</a></li>
110
+ <li><a href="/new.html">New Arrivals</a></li>
111
+ </ul>
112
+ </div>
113
+
114
+ <div class="footer-section">
115
+ <h3>Community</h3>
116
+ <ul class="footer-links">
117
+ <li><a href="/events.html">Events</a></li>
118
+ <li><a href="/forum.html">Forum</a></li>
119
+ <li><a href="/competitions.html">Competitions</a></li>
120
+ <li><a href="/blog.html">Blog</a></li>
121
+ <li><a href="/support.html">Support</a></li>
122
+ </ul>
123
+ </div>
124
+
125
+ <div class="footer-section">
126
+ <h3>Newsletter</h3>
127
+ <p>Stay updated with the latest AI art trends and featured artists.</p>
128
+ <input type="email" placeholder="Enter your email" class="newsletter-input">
129
+ <button class="bg-primary hover:bg-orange-600 text-white px-6 py-2 rounded-lg font-semibold transition-colors duration-300">
130
+ Subscribe
131
+ </button>
132
+ </div>
133
+ </div>
134
+
135
+ <div class="footer-bottom">
136
+ <p>&copy; 2024 NeuroMorph Gallery. All rights reserved. | <a href="/privacy.html" class="text-secondary hover:text-sky-400">Privacy Policy</a> | <a href="/terms.html" class="text-secondary hover:text-sky-400">Terms of Service</a></p>
137
+ </div>
138
+ </footer>
139
+ `;
140
+ }
141
+ }
142
+
143
+ customElements.define('custom-footer', CustomFooter);
components/navbar.js ADDED
@@ -0,0 +1,199 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ class CustomNavbar extends HTMLElement {
2
+ connectedCallback() {
3
+ this.attachShadow({ mode: 'open' });
4
+ this.shadowRoot.innerHTML = `
5
+ <style>
6
+ :host {
7
+ display: block;
8
+ position: sticky;
9
+ top: 0;
10
+ z-index: 50;
11
+ }
12
+
13
+ nav {
14
+ background: linear-gradient(135deg, #111827 0%, #1f2937 100%);
15
+ padding: 1rem 2rem;
16
+ display: flex;
17
+ justify-content: space-between;
18
+ align-items: center;
19
+ backdrop-filter: blur(10px);
20
+ }
21
+
22
+ .logo {
23
+ color: white;
24
+ font-weight: 800;
25
+ font-size: 1.5rem;
26
+ background: linear-gradient(135deg, #f97316, #fb923c);
27
+ -webkit-background-clip: text;
28
+ -webkit-text-fill-color: transparent;
29
+ background-clip: text;
30
+ }
31
+
32
+ .nav-links {
33
+ display: flex;
34
+ gap: 2rem;
35
+ list-style: none;
36
+ margin: 0;
37
+ padding: 0;
38
+ align-items: center;
39
+ }
40
+
41
+ .nav-link {
42
+ color: white;
43
+ text-decoration: none;
44
+ font-weight: 500;
45
+ transition: all 0.3s ease;
46
+ display: flex;
47
+ align-items: center;
48
+ gap: 0.5rem;
49
+ }
50
+
51
+ .nav-link:hover {
52
+ color: #f97316;
53
+ transform: translateY(-1px);
54
+ }
55
+
56
+ .search-container {
57
+ position: relative;
58
+ display: flex;
59
+ align-items: center;
60
+ }
61
+
62
+ .search-input {
63
+ background: rgba(255, 255, 255, 0.1);
64
+ border: 1px solid rgba(255, 255, 255, 0.2);
65
+ border-radius: 25px;
66
+ padding: 0.5rem 1rem 0.5rem 2.5rem;
67
+ color: white;
68
+ transition: all 0.3s ease;
69
+ }
70
+
71
+ .search-input:focus {
72
+ outline: none;
73
+ border-color: #f97316;
74
+ box-shadow: 0 0 0 2px rgba(249, 115, 22, 0.2);
75
+ }
76
+
77
+ .search-icon {
78
+ position: absolute;
79
+ left: 1rem;
80
+ color: #9ca3af;
81
+ }
82
+
83
+ .mobile-menu-btn {
84
+ display: none;
85
+ background: none;
86
+ border: none;
87
+ color: white;
88
+ cursor: pointer;
89
+ }
90
+
91
+ @media (max-width: 768px) {
92
+ nav {
93
+ padding: 1rem;
94
+ }
95
+
96
+ .nav-links {
97
+ display: none;
98
+ position: absolute;
99
+ top: 100%;
100
+ left: 0;
101
+ right: 0;
102
+ background: #111827;
103
+ flex-direction: column;
104
+ padding: 1rem;
105
+ gap: 1rem;
106
+ }
107
+
108
+ .nav-links.active {
109
+ display: flex;
110
+ }
111
+
112
+ .mobile-menu-btn {
113
+ display: block;
114
+ }
115
+ }
116
+ </style>
117
+ <nav>
118
+ <div class="logo">NeuroMorph</div>
119
+
120
+ <ul class="nav-links">
121
+ <li>
122
+ <a href="/" class="nav-link">
123
+ <i data-feather="home"></i>
124
+ Home
125
+ </a>
126
+ </li>
127
+ <li>
128
+ <a href="/gallery.html" class="nav-link">
129
+ <i data-feather="image"></i>
130
+ Gallery
131
+ </a>
132
+ </li>
133
+ <li>
134
+ <a href="/upload.html" class="nav-link">
135
+ <i data-feather="upload"></i>
136
+ Upload
137
+ </a>
138
+ </li>
139
+ <li>
140
+ <a href="/artists.html" class="nav-link">
141
+ <i data-feather="users"></i>
142
+ Artists
143
+ </a>
144
+ </li>
145
+ <li>
146
+ <a href="/about.html" class="nav-link">
147
+ <i data-feather="info"></i>
148
+ About
149
+ </a>
150
+ </li>
151
+ <li class="search-container">
152
+ <i data-feather="search" class="search-icon"></i>
153
+ <input type="search" placeholder="Search artworks..." class="search-input">
154
+ </li>
155
+ <li>
156
+ <a href="/profile.html" class="nav-link">
157
+ <i data-feather="user"></i>
158
+ Profile
159
+ </a>
160
+ </li>
161
+ </ul>
162
+
163
+ <button class="mobile-menu-btn">
164
+ <i data-feather="menu"></i>
165
+ </button>
166
+ </nav>
167
+ `;
168
+
169
+ this.setupMobileMenu();
170
+ this.setupSearch();
171
+ }
172
+
173
+ setupMobileMenu() {
174
+ const menuBtn = this.shadowRoot.querySelector('.mobile-menu-btn');
175
+ const navLinks = this.shadowRoot.querySelector('.nav-links');
176
+
177
+ menuBtn.addEventListener('click', () => {
178
+ navLinks.classList.toggle('active');
179
+ const icon = menuBtn.querySelector('i');
180
+ if (navLinks.classList.contains('active')) {
181
+ icon.setAttribute('data-feather', 'x');
182
+ } else {
183
+ icon.setAttribute('data-feather', 'menu');
184
+ }
185
+ feather.replace();
186
+ });
187
+ }
188
+
189
+ setupSearch() {
190
+ const searchInput = this.shadowRoot.querySelector('.search-input');
191
+
192
+ searchInput.addEventListener('input', (e) => {
193
+ const query = e.target.value;
194
+ // Search functionality will be handled by main script
195
+ });
196
+ }
197
+ }
198
+
199
+ customElements.define('custom-navbar', CustomNavbar);
gallery.html ADDED
@@ -0,0 +1,85 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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>Gallery - NeuroMorph Gallery</title>
7
+ <meta name="description" content="Browse our complete collection of AI-generated artworks">
8
+ <link rel="manifest" href="manifest.json">
9
+ <link rel="icon" type="image/x-icon" href="/static/favicon.ico">
10
+ <link rel="stylesheet" href="style.css">
11
+ <script src="https://cdn.tailwindcss.com"></script>
12
+ <script src="https://cdn.jsdelivr.net/npm/feather-icons/dist/feather.min.js"></script>
13
+ <script src="https://unpkg.com/feather-icons"></script>
14
+ <script>
15
+ tailwind.config = {
16
+ theme: {
17
+ extend: {
18
+ colors: {
19
+ primary: '#f97316',
20
+ secondary: '#0ea5e9'
21
+ }
22
+ }
23
+ }
24
+ }
25
+ </script>
26
+ </head>
27
+ <body class="bg-gray-100 min-h-screen flex flex-col">
28
+ <custom-navbar></custom-navbar>
29
+
30
+ <main class="flex-grow py-12 px-4">
31
+ <div class="max-w-7xl mx-auto">
32
+ <div class="flex flex-col md:flex-row justify-between items-start md:items-center mb-12">
33
+ <h1 class="text-4xl font-bold text-gray-800 mb-4 md:mb-0">Complete Gallery</h1>
34
+
35
+ <div class="flex flex-col sm:flex-row gap-4 w-full md:w-auto">
36
+ <select class="neomorphic-input">
37
+ <option value="">All Categories</option>
38
+ <option value="abstract">Abstract</option>
39
+ <option value="portrait">Portrait</option>
40
+ <option value="landscape">Landscape</option>
41
+ <option value="surreal">Surreal</option>
42
+ <option value="futuristic">Futuristic</option>
43
+ </select>
44
+
45
+ <select class="neomorphic-input">
46
+ <option value="newest">Newest First</option>
47
+ <option value="popular">Most Popular</option>
48
+ <option value="trending">Trending</option>
49
+ </select>
50
+ </div>
51
+ </div>
52
+
53
+ <div id="gallery-grid" class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
54
+ <!-- Gallery items will be loaded here -->
55
+ </div>
56
+
57
+ <div class="flex justify-center mt-12">
58
+ <div class="flex gap-2">
59
+ <button class="bg-primary text-white px-4 py-2 rounded-lg">1</button>
60
+ <button class="neomorphic-button px-4 py-2">2</button>
61
+ <button class="neomorphic-button px-4 py-2">3</button>
62
+ <button class="neomorphic-button px-4 py-2">Next</button>
63
+ </div>
64
+ </div>
65
+ </div>
66
+ </div>
67
+ </main>
68
+
69
+ <custom-footer></custom-footer>
70
+
71
+ <script src="components/navbar.js"></script>
72
+ <script src="components/footer.js"></script>
73
+ <script src="components/artwork-card.js"></script>
74
+ <script src="script.js"></script>
75
+ <script>
76
+ feather.replace();
77
+
78
+ // Load gallery items
79
+ document.addEventListener('DOMContentLoaded', async () => {
80
+ const gallery = new NeuroMorphGallery();
81
+ await gallery.loadGalleryItems();
82
+ });
83
+ </script>
84
+ </body>
85
+ </html>
index.html CHANGED
@@ -1,19 +1,122 @@
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>NeuroMorph Gallery - AI Art Showcase</title>
7
+ <meta name="description" content="Discover stunning AI-generated art in our neomorphic gallery">
8
+ <link rel="manifest" href="manifest.json">
9
+ <link rel="icon" type="image/x-icon" href="/static/favicon.ico">
10
+ <link rel="stylesheet" href="style.css">
11
+ <script src="https://cdn.tailwindcss.com"></script>
12
+ <script src="https://cdn.jsdelivr.net/npm/feather-icons/dist/feather.min.js"></script>
13
+ <script src="https://unpkg.com/feather-icons"></script>
14
+ <script src="https://cdn.jsdelivr.net/npm/vanta@latest/dist/vanta.globe.min.js"></script>
15
+ <script>
16
+ tailwind.config = {
17
+ theme: {
18
+ extend: {
19
+ colors: {
20
+ primary: '#f97316',
21
+ secondary: '#0ea5e9'
22
+ }
23
+ }
24
+ }
25
+ }
26
+ </script>
27
+ </head>
28
+ <body class="bg-gray-100 min-h-screen flex flex-col">
29
+ <custom-navbar></custom-navbar>
30
+
31
+ <main class="flex-grow">
32
+ <!-- Hero Section with Vanta.js Background -->
33
+ <section id="hero" class="relative h-screen flex items-center justify-center overflow-hidden">
34
+ <div class="absolute inset-0 z-0" id="vanta-bg"></div>
35
+ <div class="relative z-10 text-center text-white px-4">
36
+ <h1 class="text-5xl md:text-7xl font-bold mb-6 drop-shadow-2xl">
37
+ NeuroMorph Gallery
38
+ </h1>
39
+ <p class="text-xl md:text-2xl mb-8 max-w-2xl mx-auto">
40
+ Where artificial intelligence meets artistic expression in a neomorphic digital realm
41
+ </p>
42
+ <div class="flex flex-col sm:flex-row gap-4 justify-center">
43
+ <a href="#gallery" class="bg-primary hover:bg-orange-600 text-white px-8 py-4 rounded-2xl font-semibold transition-all duration-300 transform hover:scale-105 shadow-2xl">
44
+ Explore Gallery
45
+ </a>
46
+ <a href="/upload.html" class="bg-secondary hover:bg-sky-600 text-white px-8 py-4 rounded-2xl font-semibold transition-all duration-300 transform hover:scale-105 shadow-2xl">
47
+ Upload Art
48
+ </a>
49
+ </div>
50
+ </div>
51
+ </section>
52
+
53
+ <!-- Featured Gallery Section -->
54
+ <section id="gallery" class="py-20 px-4">
55
+ <div class="max-w-7xl mx-auto">
56
+ <h2 class="text-4xl font-bold text-center mb-4 text-gray-800">Featured AI Artworks</h2>
57
+ <p class="text-xl text-center mb-12 text-gray-600">Curated collection of machine-generated masterpieces</p>
58
+
59
+ <div id="artworks-grid" class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
60
+ <!-- Artworks will be dynamically loaded here -->
61
+ </div>
62
+
63
+ <div class="text-center mt-12">
64
+ <button id="load-more" class="bg-primary hover:bg-orange-600 text-white px-8 py-3 rounded-xl font-semibold transition-all duration-300">
65
+ <i data-feather="plus" class="inline mr-2"></i>
66
+ Load More Artworks
67
+ </button>
68
+ </div>
69
+ </div>
70
+ </section>
71
+
72
+ <!-- Stats Section -->
73
+ <section class="bg-gray-800 text-white py-16">
74
+ <div class="max-w-7xl mx-auto px-4">
75
+ <div class="grid grid-cols-1 md:grid-cols-3 gap-8 text-center">
76
+ <div class="p-6 rounded-2xl bg-gray-700 shadow-2xl">
77
+ <div class="text-4xl font-bold text-primary mb-2" id="total-artworks">1,247</div>
78
+ <div class="text-lg">AI Artworks</div>
79
+ </div>
80
+ <div class="p-6 rounded-2xl bg-gray-700 shadow-2xl">
81
+ <div class="text-4xl font-bold text-secondary mb-2" id="active-artists">356</div>
82
+ <div class="text-lg">AI Artists</div>
83
+ </div>
84
+ <div class="p-6 rounded-2xl bg-gray-700 shadow-2xl">
85
+ <div class="text-4xl font-bold text-primary mb-2" id="monthly-views">89.2K</div>
86
+ <div class="text-lg">Monthly Views</div>
87
+ </div>
88
+ </div>
89
+ </section>
90
+ </main>
91
+
92
+ <custom-footer></custom-footer>
93
+
94
+ <!-- Component Scripts -->
95
+ <script src="components/navbar.js"></script>
96
+ <script src="components/footer.js"></script>
97
+ <script src="components/artwork-card.js"></script>
98
+
99
+ <!-- Main Script -->
100
+ <script src="script.js"></script>
101
+
102
+ <script>
103
+ feather.replace();
104
+
105
+ // Initialize Vanta.js background
106
+ VANTA.GLOBE({
107
+ el: "#vanta-bg",
108
+ mouseControls: true,
109
+ touchControls: true,
110
+ gyroControls: false,
111
+ minHeight: 200.00,
112
+ minWidth: 200.00,
113
+ scale: 1.00,
114
+ scaleMobile: 1.00,
115
+ color: 0xf97316,
116
+ backgroundColor: 0x111827,
117
+ size: 1.00
118
+ });
119
+ </script>
120
+ <script src="https://deepsite.hf.co/deepsite-badge.js"></script>
121
+ </body>
122
+ </html>
manifest.json ADDED
@@ -0,0 +1,68 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ json
2
+ {
3
+ "name": "NeuroMorph Gallery",
4
+ "short_name": "NeuroMorph",
5
+ "description": "AI Art Gallery showcasing machine-generated masterpieces",
6
+ "start_url": "/",
7
+ "display": "standalone",
8
+ "background_color": "#111827",
9
+ "theme_color": "#f97316",
10
+ "orientation": "portrait",
11
+ "start_url": "/",
12
+ "icons": [
13
+ {
14
+ "src": "/static/icons/icon-72x72.png",
15
+ "sizes": "72x72",
16
+ "type": "image/png"
17
+ },
18
+ {
19
+ "src": "/static/icons/icon-96x96.png",
20
+ "sizes": "96x96",
21
+ "type": "image/png"
22
+ },
23
+ {
24
+ "src": "/static/icons/icon-128x128.png",
25
+ "sizes": "128x128",
26
+ "type": "image/png"
27
+ },
28
+ {
29
+ "src": "/static/icons/icon-128x128.png",
30
+ "sizes": "128x128",
31
+ "type": "image/png"
32
+ },
33
+ {
34
+ "src": "/static/icons/icon-144x144.png",
35
+ "sizes": "144x144",
36
+ "type": "image/png"
37
+ },
38
+ {
39
+ "src": "/static/icons/icon-152x152.png",
40
+ "sizes": "152x152",
41
+ "type": "image/png"
42
+ },
43
+ {
44
+ "src": "/static/icons/icon-192x192.png",
45
+ "sizes": "192x192",
46
+ "type": "image/png"
47
+ },
48
+ {
49
+ "src": "/static/icons/icon-384x384.png",
50
+ "sizes": "384x384",
51
+ "type": "image/png"
52
+ },
53
+ {
54
+ "src": "/static/icons/icon-512x512.png",
55
+ "sizes": "512x512",
56
+ "type": "image/png"
57
+ },
58
+ {
59
+ "src": "/static/icons/icon-512x512.png",
60
+ "sizes": "512x512",
61
+ "type": "image/png"
62
+ }
63
+ ],
64
+ "categories": ["art", "entertainment", "technology"],
65
+ "lang": "en-US"
66
+ }
67
+
68
+ </html>
script.js ADDED
@@ -0,0 +1,225 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // NeuroMorph Gallery - Shared JavaScript
2
+ class NeuroMorphGallery {
3
+ constructor() {
4
+ this.artworks = [];
5
+ this.currentPage = 1;
6
+ this.artworksPerPage = 9;
7
+ this.init();
8
+ }
9
+
10
+ async init() {
11
+ await this.registerServiceWorker();
12
+ this.setupEventListeners();
13
+ await this.loadArtworks();
14
+ this.updateStats();
15
+ this.setupOfflineDetection();
16
+ }
17
+
18
+ // PWA Service Worker Registration
19
+ async registerServiceWorker() {
20
+ if ('serviceWorker' in navigator) {
21
+ try {
22
+ await navigator.serviceWorker.register('/sw.js');
23
+ console.log('Service Worker registered successfully');
24
+ } catch (error) {
25
+ console.error('Service Worker registration failed:', error);
26
+ }
27
+ }
28
+ }
29
+
30
+ // GraphQL API Integration
31
+ async fetchArtworks(page = 1) {
32
+ const query = `
33
+ query GetArtworks($page: Int!, $limit: Int!) {
34
+ artworks(page: $page, limit: $limit) {
35
+ id
36
+ title
37
+ description
38
+ imageUrl
39
+ artist {
40
+ name
41
+ avatar
42
+ }
43
+ likes
44
+ views
45
+ createdAt
46
+ tags
47
+ }
48
+ }
49
+ `;
50
+
51
+ try {
52
+ const response = await fetch('/graphql', {
53
+ method: 'POST',
54
+ headers: {
55
+ 'Content-Type': 'application/json',
56
+ },
57
+ body: JSON.stringify({
58
+ query,
59
+ variables: { page, limit: this.artworksPerPage }
60
+ })
61
+ });
62
+
63
+ const result = await response.json();
64
+ return result.data?.artworks || [];
65
+ } catch (error) {
66
+ console.error('Error fetching artworks:', error);
67
+
68
+ // Fallback to mock data if API is unavailable
69
+ return this.getMockArtworks(page);
70
+ }
71
+ }
72
+
73
+ // Mock data for demonstration
74
+ getMockArtworks(page) {
75
+ const mockArtworks = [];
76
+ const startIndex = (page - 1) * this.artworksPerPage;
77
+
78
+ for (let i = 0; i < this.artworksPerPage; i++) {
79
+ mockArtworks.push({
80
+ id: `artwork-${startIndex + i + 1}`,
81
+ title: `AI Dreamscape ${startIndex + i + 1}`,
82
+ description: 'A stunning AI-generated artwork showcasing the intersection of technology and creativity.',
83
+ imageUrl: `http://static.photos/abstract/640x360/${startIndex + i + 1}`,
84
+ artist: {
85
+ name: `NeuralArtist${startIndex + i + 1}`,
86
+ avatar: `http://static.photos/people/200x200/${startIndex + i + 1}`
87
+ },
88
+ likes: Math.floor(Math.random() * 1000),
89
+ views: Math.floor(Math.random() * 5000),
90
+ createdAt: new Date().toISOString(),
91
+ tags: ['AI', 'Digital Art', 'Abstract', 'Modern']
92
+ });
93
+ }
94
+
95
+ return mockArtworks;
96
+ }
97
+
98
+ // Load and display artworks
99
+ async loadArtworks() {
100
+ const artworks = await this.fetchArtworks(this.currentPage);
101
+ this.artworks = [...this.artworks, ...artworks];
102
+ this.renderArtworks(artworks);
103
+ }
104
+
105
+ renderArtworks(artworks) {
106
+ const grid = document.getElementById('artworks-grid');
107
+
108
+ artworks.forEach(artwork => {
109
+ const artworkCard = document.createElement('artwork-card');
110
+ artworkCard.setAttribute('data-artwork', JSON.stringify(artwork));
111
+ grid.appendChild(artworkCard);
112
+ });
113
+ }
114
+
115
+ // Update statistics
116
+ updateStats() {
117
+ // Simulate real-time stats updates
118
+ setInterval(() => {
119
+ document.getElementById('total-artworks').textContent =
120
+ (1247 + Math.floor(Math.random() * 10)).toLocaleString();
121
+
122
+ document.getElementById('active-artists').textContent =
123
+ (356 + Math.floor(Math.random() * 5)).toLocaleString();
124
+
125
+ document.getElementById('monthly-views').textContent =
126
+ (89200 + Math.floor(Math.random() * 1000)).toLocaleString();
127
+ }, 5000);
128
+ }
129
+
130
+ // Event listeners setup
131
+ setupEventListeners() {
132
+ // Load more artworks
133
+ const loadMoreBtn = document.getElementById('load-more');
134
+ if (loadMoreBtn) {
135
+ loadMoreBtn.addEventListener('click', () => {
136
+ this.currentPage++;
137
+ this.loadArtworks();
138
+ });
139
+ }
140
+
141
+ // Search functionality
142
+ const searchInput = document.querySelector('input[type="search"]');
143
+ if (searchInput) {
144
+ searchInput.addEventListener('input', (e) => {
145
+ this.searchArtworks(e.target.value);
146
+ });
147
+ }
148
+ }
149
+
150
+ // Search artworks
151
+ searchArtworks(query) {
152
+ const filtered = this.artworks.filter(artwork =>
153
+ artwork.title.toLowerCase().includes(query.toLowerCase()) ||
154
+ artwork.description.toLowerCase().includes(query.toLowerCase()) ||
155
+ artwork.tags.some(tag => tag.toLowerCase().includes(query.toLowerCase()))
156
+ );
157
+
158
+ this.renderSearchResults(filtered);
159
+ }
160
+
161
+ renderSearchResults(artworks) {
162
+ const grid = document.getElementById('artworks-grid');
163
+ grid.innerHTML = '';
164
+
165
+ artworks.forEach(artwork => {
166
+ const artworkCard = document.createElement('artwork-card');
167
+ artworkCard.setAttribute('data-artwork', JSON.stringify(artwork));
168
+ grid.appendChild(artworkCard);
169
+ });
170
+ }
171
+
172
+ // Offline detection
173
+ setupOfflineDetection() {
174
+ window.addEventListener('online', () => {
175
+ this.hideOfflineIndicator();
176
+ console.log('App is online');
177
+ });
178
+
179
+ window.addEventListener('offline', () => {
180
+ this.showOfflineIndicator();
181
+ console.log('App is offline');
182
+ });
183
+ }
184
+
185
+ showOfflineIndicator() {
186
+ const indicator = document.createElement('div');
187
+ indicator.className = 'offline-indicator';
188
+ indicator.textContent = 'You are currently offline. Some features may be limited.';
189
+ indicator.style.display = 'block';
190
+ document.body.appendChild(indicator);
191
+ }
192
+
193
+ hideOfflineIndicator() {
194
+ const indicator = document.querySelector('.offline-indicator');
195
+ if (indicator) {
196
+ indicator.style.display = 'none';
197
+ }
198
+ }
199
+
200
+ // Image optimization and lazy loading
201
+ optimizeImages() {
202
+ const images = document.querySelectorAll('img[data-src]');
203
+
204
+ const imageObserver = new IntersectionObserver((entries, observer) => {
205
+ entries.forEach(entry => {
206
+ if (entry.isIntersecting) {
207
+ const img = entry.target;
208
+ img.src = img.dataset.src;
209
+ img.removeAttribute('data-src');
210
+ observer.unobserve(img);
211
+ }
212
+ });
213
+ });
214
+
215
+ images.forEach(img => imageObserver.observe(img));
216
+ }
217
+ }
218
+
219
+ // Initialize the gallery when DOM is loaded
220
+ document.addEventListener('DOMContentLoaded', () => {
221
+ new NeuroMorphGallery();
222
+ });
223
+
224
+ // Export for use in other modules
225
+ window.NeuroMorphGallery = NeuroMorphGallery;
style.css CHANGED
@@ -1,28 +1,109 @@
 
 
 
 
 
 
 
 
 
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
+ /* NeuroMorph Gallery - Shared Styles */
2
+ @import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&display=swap');
3
+
4
+ * {
5
+ margin: 0;
6
+ padding: 0;
7
+ box-sizing: border-box;
8
+ }
9
+
10
  body {
11
+ font-family: 'Inter', sans-serif;
12
+ background: linear-gradient(135deg, #f8fafc 0%, #e2e8f0 100%);
13
+ min-height: 100vh;
14
+ }
15
+
16
+ /* Neomorphic Design Elements */
17
+ .neomorphic-card {
18
+ background: linear-gradient(145deg, #ffffff, #e6e6e6);
19
+ border-radius: 20px;
20
+ box-shadow: 8px 8px 16px #d1d1d1, -8px -8px 16px #ffffff;
21
+ transition: all 0.3s ease;
22
+ }
23
+
24
+ .neomorphic-card:hover {
25
+ transform: translateY(-5px);
26
+ box-shadow: 12px 12px 24px #c9c9c9, -12px -12px 24px #ffffff;
27
+ }
28
+
29
+ .neomorphic-button {
30
+ background: linear-gradient(145deg, #ffffff, #e6e6e6);
31
+ border-radius: 15px;
32
+ box-shadow: 5px 5px 10px #d1d1d1, -5px -5px 10px #ffffff;
33
+ transition: all 0.3s ease;
34
+ }
35
+
36
+ .neomorphic-button:hover {
37
+ box-shadow: 3px 3px 6px #c9c9c9, -3px -3px 6px #ffffff;
38
+ transform: translateY(2px);
39
  }
40
 
41
+ .neomorphic-input {
42
+ background: linear-gradient(145deg, #ffffff, #e6e6e6);
43
+ border: none;
44
+ border-radius: 15px;
45
+ box-shadow: inset 5px 5px 10px #d1d1d1, inset -5px -5px 10px #ffffff;
46
+ padding: 12px 20px;
47
+ font-size: 16px;
48
+ transition: all 0.3s ease;
49
  }
50
 
51
+ .neomorphic-input:focus {
52
+ outline: none;
53
+ box-shadow: inset 3px 3px 6px #c9c9c9, inset -3px -3px 6px #ffffff;
 
 
54
  }
55
 
56
+ /* Custom scrollbar */
57
+ ::-webkit-scrollbar {
58
+ width: 8px;
 
 
 
59
  }
60
 
61
+ ::-webkit-scrollbar-track {
62
+ background: #f1f1f1;
63
+ border-radius: 10px;
64
  }
65
+
66
+ ::-webkit-scrollbar-thumb {
67
+ background: linear-gradient(135deg, #f97316, #fb923c);
68
+ border-radius: 10px;
69
+ }
70
+
71
+ ::-webkit-scrollbar-thumb:hover {
72
+ background: linear-gradient(135deg, #ea580c, #f97316);
73
+ }
74
+
75
+ /* Loading animation */
76
+ @keyframes pulse {
77
+ 0%, 100% {
78
+ opacity: 1;
79
+ }
80
+ 50% {
81
+ opacity: 0.5;
82
+ }
83
+ }
84
+
85
+ .loading {
86
+ animation: pulse 2s infinite;
87
+ }
88
+
89
+ /* Mobile optimizations */
90
+ @media (max-width: 768px) {
91
+ .neomorphic-card {
92
+ border-radius: 15px;
93
+ box-shadow: 5px 5px 10px #d1d1d1, -5px -5px 10px #ffffff;
94
+ }
95
+ }
96
+
97
+ /* PWA offline indicator */
98
+ .offline-indicator {
99
+ position: fixed;
100
+ top: 0;
101
+ left: 0;
102
+ right: 0;
103
+ background: #ef4444;
104
+ color: white;
105
+ text-align: center;
106
+ padding: 10px;
107
+ z-index: 1000;
108
+ display: none;
109
+ }
sw.js ADDED
@@ -0,0 +1,92 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Service Worker for NeuroMorph Gallery PWA
2
+ const CACHE_NAME = 'neuromorph-gallery-v1.0.0';
3
+ const urlsToCache = [
4
+ '/',
5
+ '/style.css',
6
+ '/script.js',
7
+ '/components/navbar.js',
8
+ '/components/footer.js',
9
+ '/components/artwork-card.js',
10
+ '/gallery.html',
11
+ '/upload.html',
12
+ '/manifest.json'
13
+ ];
14
+
15
+ // Install event
16
+ self.addEventListener('install', (event) => {
17
+ event.waitUntil(
18
+ caches.open(CACHE_NAME)
19
+ .then((cache) => {
20
+ return cache.addAll(urlsToCache);
21
+ })
22
+ );
23
+ });
24
+
25
+ // Activate event
26
+ self.addEventListener('activate', (event) => {
27
+ event.waitUntil(
28
+ caches.keys().then((cacheNames) => {
29
+ return Promise.all(
30
+ cacheNames.map((cacheName) => {
31
+ if (cacheName !== CACHE_NAME) {
32
+ return caches.delete(cacheName);
33
+ }
34
+ })
35
+ );
36
+ });
37
+
38
+ // Fetch event
39
+ self.addEventListener('fetch', (event) => {
40
+ event.respondWith(
41
+ caches.match(event.request)
42
+ .then((response) => {
43
+ // Return cached version or fetch from network
44
+ return response || fetch(event.request);
45
+ })
46
+ );
47
+ });
48
+
49
+ // Background sync for offline uploads
50
+ self.addEventListener('sync', (event) => {
51
+ if (event.tag === 'background-upload') {
52
+ event.waitUntil(doBackgroundUpload());
53
+ }
54
+ });
55
+
56
+ async function doBackgroundUpload() {
57
+ // Handle background uploads when connection is restored
58
+ const db = await openDB();
59
+ const pendingUploads = await db.getAll('pendingUploads');
60
+
61
+ for (const upload of pendingUploads) {
62
+ try {
63
+ await fetch('/api/upload', {
64
+ method: 'POST',
65
+ body: upload.data
66
+ });
67
+ await db.delete('pendingUploads', upload.id);
68
+ } catch (error) {
69
+ console.error('Background upload failed:', error);
70
+ }
71
+ }
72
+ }
73
+
74
+ // IndexedDB for offline storage
75
+ function openDB() {
76
+ return new Promise((resolve, reject) => {
77
+ const request = indexedDB.open('NeuroMorphGallery', 1);
78
+
79
+ request.onerror = () => reject(request.error);
80
+ request.onsuccess = () => resolve(request.result);
81
+
82
+ request.onupgradeneeded = (event) => {
83
+ const db = event.target.result;
84
+
85
+ // Create object store for artworks
86
+ if (!db.objectStoreNames.contains('artworks')) {
87
+ const store = db.createObjectStore('artworks', { keyPath: 'id' });
88
+ store.createIndex('title', 'title', { unique: false });
89
+ store.createIndex('artist', 'artist.name', { unique: false });
90
+ };
91
+ });
92
+ }
upload.html ADDED
@@ -0,0 +1,208 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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>Upload AI Art - NeuroMorph Gallery</title>
7
+ <meta name="description" content="Upload your AI-generated artworks to NeuroMorph Gallery">
8
+ <link rel="manifest" href="manifest.json">
9
+ <link rel="icon" type="image/x-icon" href="/static/favicon.ico">
10
+ <link rel="stylesheet" href="style.css">
11
+ <script src="https://cdn.tailwindcss.com"></script>
12
+ <script src="https://cdn.jsdelivr.net/npm/feather-icons/dist/feather.min.js"></script>
13
+ <script src="https://unpkg.com/feather-icons"></script>
14
+ <script>
15
+ tailwind.config = {
16
+ theme: {
17
+ extend: {
18
+ colors: {
19
+ primary: '#f97316',
20
+ secondary: '#0ea5e9'
21
+ }
22
+ }
23
+ }
24
+ }
25
+ </script>
26
+ </head>
27
+ <body class="bg-gray-100 min-h-screen flex flex-col">
28
+ <custom-navbar></custom-navbar>
29
+
30
+ <main class="flex-grow py-12 px-4">
31
+ <div class="max-w-4xl mx-auto">
32
+ <div class="text-center mb-12">
33
+ <h1 class="text-4xl font-bold text-gray-800 mb-4">Upload Your AI Art</h1>
34
+ <p class="text-xl text-gray-600">Share your machine-generated masterpieces with the world</p>
35
+ </div>
36
+
37
+ <div class="neomorphic-card p-8">
38
+ <form id="upload-form" class="space-y-6">
39
+ <div class="grid grid-cols-1 md:grid-cols-2 gap-6">
40
+ <div>
41
+ <label class="block text-sm font-medium text-gray-700 mb-2">Artwork Title</label>
42
+ <input
43
+ type="text"
44
+ required
45
+ class="neomorphic-input w-full"
46
+ placeholder="Enter a captivating title"
47
+ >
48
+ </div>
49
+
50
+ <div>
51
+ <label class="block text-sm font-medium text-gray-700 mb-2">Description</label>
52
+ <textarea
53
+ required
54
+ class="neomorphic-input w-full h-32 resize-none"
55
+ placeholder="Describe your artwork, the AI model used, inspiration, etc."
56
+ ></textarea>
57
+ </div>
58
+
59
+ <div>
60
+ <label class="block text-sm font-medium text-gray-700 mb-2">AI Model Used</label>
61
+ <select class="neomorphic-input w-full">
62
+ <option value="">Select AI Model</option>
63
+ <option value="dalle">DALL-E</option>
64
+ <option value="midjourney">Midjourney</option>
65
+ <option value="stable-diffusion">Stable Diffusion</option>
66
+ <option value="gpt-art">GPT Art</option>
67
+ <option value="custom">Custom Model</option>
68
+ </select>
69
+ </div>
70
+
71
+ <div>
72
+ <label class="block text-sm font-medium text-gray-700 mb-2">Artwork Image</label>
73
+ <div class="border-2 border-dashed border-gray-300 rounded-2xl p-8 text-center transition-all duration-300 hover:border-primary" id="drop-zone">
74
+ <i data-feather="upload-cloud" class="w-12 h-12 text-gray-400 mx-auto mb-4"></i>
75
+ <p class="text-gray-500 mb-2">Drag & drop your image here</p>
76
+ <p class="text-sm text-gray-400 mb-4">PNG, JPG, WEBP up to 10MB</p>
77
+ <button type="button" class="bg-secondary hover:bg-sky-600 text-white px-6 py-2 rounded-xl font-semibold transition-colors duration-300">
78
+ Choose File
79
+ </button>
80
+ <input type="file" accept="image/*" class="hidden" id="file-input">
81
+ </div>
82
+ </div>
83
+
84
+ <div>
85
+ <label class="block text-sm font-medium text-gray-700 mb-2">Tags</label>
86
+ <input
87
+ type="text"
88
+ class="neomorphic-input w-full"
89
+ placeholder="AI, digital art, abstract, etc."
90
+ >
91
+ <p class="text-xs text-gray-500 mt-1">Separate tags with commas</p>
92
+ </div>
93
+
94
+ <div>
95
+ <label class="block text-sm font-medium text-gray-700 mb-2">License Type</label>
96
+ <select class="neomorphic-input w-full">
97
+ <option value="cc-by">Creative Commons Attribution</option>
98
+ <option value="cc-by-nc">Creative Commons Non-Commercial</option>
99
+ <option value="all-rights">All Rights Reserved</option>
100
+ </select>
101
+ </div>
102
+
103
+ <div>
104
+ <label class="flex items-center">
105
+ <input type="checkbox" class="rounded text-primary">
106
+ <span class="ml-2 text-gray-700">Make this artwork premium</span>
107
+ </label>
108
+ <p class="text-xs text-gray-500 mt-1">Premium artworks get featured placement and higher visibility</p>
109
+ </div>
110
+ </div>
111
+
112
+ <div class="flex flex-col sm:flex-row gap-4 justify-end">
113
+ <button type="button" class="bg-gray-500 hover:bg-gray-600 text-white px-6 py-3 rounded-xl font-semibold transition-colors duration-300">
114
+ Cancel
115
+ </button>
116
+ <button type="submit" class="bg-primary hover:bg-orange-600 text-white px-8 py-3 rounded-xl font-semibold transition-colors duration-300">
117
+ <i data-feather="upload" class="inline mr-2"></i>
118
+ Upload Artwork
119
+ </button>
120
+ </div>
121
+ </form>
122
+ </div>
123
+
124
+ <!-- Upload Guidelines -->
125
+ <div class="neomorphic-card p-8 mt-8">
126
+ <h2 class="text-2xl font-bold text-gray-800 mb-4">Upload Guidelines</h2>
127
+ <div class="grid grid-cols-1 md:grid-cols-2 gap-6">
128
+ <div>
129
+ <h3 class="font-semibold text-gray-700 mb-2">Quality Standards</h3>
130
+ <ul class="text-gray-600 space-y-1">
131
+ <li>• High-resolution images preferred</li>
132
+ <li>• Must be AI-generated artwork</li>
133
+ <li>• No offensive or harmful content</li>
134
+ <li>• Proper attribution to AI models</li>
135
+ </ul>
136
+ </div>
137
+
138
+ <div>
139
+ <h3 class="font-semibold text-gray-700 mb-2">Best Practices</h3>
140
+ <ul class="text-gray-600 space-y-1">
141
+ <li>• Include detailed descriptions</li>
142
+ <li>• Use relevant tags for discoverability</li>
143
+ <li>• Consider watermarking for protection</li>
144
+ <li>• Choose appropriate licensing</li>
145
+ </ul>
146
+ </div>
147
+ </div>
148
+ </div>
149
+ </div>
150
+ </main>
151
+
152
+ <custom-footer></custom-footer>
153
+
154
+ <script src="components/navbar.js"></script>
155
+ <script src="components/footer.js"></script>
156
+ <script src="script.js"></script>
157
+ <script>
158
+ feather.replace();
159
+
160
+ // File upload handling
161
+ const dropZone = document.getElementById('drop-zone');
162
+ const fileInput = document.getElementById('file-input');
163
+ const chooseFileBtn = dropZone.querySelector('button');
164
+
165
+ chooseFileBtn.addEventListener('click', () => fileInput.click());
166
+
167
+ fileInput.addEventListener('change', handleFileSelect);
168
+ dropZone.addEventListener('dragover', handleDragOver);
169
+ dropZone.addEventListener('drop', handleFileDrop);
170
+
171
+ function handleDragOver(e) {
172
+ e.preventDefault();
173
+ dropZone.classList.add('border-primary', 'bg-orange-50');
174
+ }
175
+
176
+ function handleFileDrop(e) {
177
+ e.preventDefault();
178
+ dropZone.classList.remove('border-primary', 'bg-orange-50');
179
+
180
+ const files = e.dataTransfer.files;
181
+ if (files.length > 0) {
182
+ handleFiles(files);
183
+ }
184
+ }
185
+
186
+ function handleFileSelect(e) {
187
+ const files = e.target.files;
188
+ handleFiles(files);
189
+ }
190
+
191
+ function handleFiles(files) {
192
+ const file = files[0];
193
+ if (file && file.type.startsWith('image/')) {
194
+ // Preview the image
195
+ const reader = new FileReader();
196
+ reader.onload = (e) => {
197
+ dropZone.innerHTML = `
198
+ <img src="${e.target.result}" alt="Preview" class="max-h-64 mx-auto mb-4 rounded-xl">
199
+ <p class="text-primary font-semibold">${file.name}</p>
200
+ <p class="text-sm text-gray-500">Click to change</p>
201
+ `;
202
+ };
203
+ reader.readAsDataURL(file);
204
+ }
205
+ }
206
+ </script>
207
+ </body>
208
+ </html>