A stream.place VOD client inspired by icarly.com
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Update branding to match iCarly aesthetic

- Replace favicon with iStream logo
- Enhance header styling with better gradients and 3D effects
- Update navigation tabs with improved shadows and colors
- Set all video thumbnails to use atmosphere-conf-thumb.png
- Improve overall layout spacing and positioning

jack 8b964cdd c38d0802

+73 -118
public/favicon.ico

This is a binary file and will not be displayed.

+69 -95
src/app/icarly.css
··· 62 62 63 63 /* Header Section - Clean Layout */ 64 64 .icarly-header { 65 - background: linear-gradient(180deg, #4A5A8A 0%, #7BA05B 40%, #A6CC3A 100%); 65 + background: linear-gradient(180deg, #384C8B 0%, #5A7A9B 30%, #7BA05B 60%, #A6CC3A 100%); 66 66 border: 4px solid #fff; 67 67 border-bottom: none; 68 - padding: 15px 250px 25px 30px; 68 + padding: 20px 30px 30px 30px; 69 69 position: relative; 70 - min-height: 280px; 70 + min-height: 300px; 71 71 box-shadow: 0 0 20px rgba(0,0,0,0.3); 72 72 display: grid; 73 - grid-template-columns: 320px 1fr 220px; 74 - grid-template-rows: auto 1fr auto; 73 + grid-template-columns: 1fr auto 1fr; 74 + grid-template-rows: auto auto 1fr; 75 75 grid-template-areas: 76 - "homepage homepage rightcol" 77 - "logo search rightcol" 78 - "date search rightcol"; 76 + "homepage . rightcol" 77 + "logo logo rightcol" 78 + "search date rightcol"; 79 79 gap: 15px 30px; 80 80 } 81 81 ··· 97 97 box-shadow: 4px 4px 0 rgba(0,0,0,0.3); 98 98 animation: glow 2s infinite; 99 99 z-index: 20; 100 - margin-bottom: 10px; 100 + align-self: start; 101 101 } 102 102 103 103 .homepage-btn:hover { ··· 106 106 107 107 .homepage-btn::before { 108 108 content: "✦"; 109 - color: var(--icarly-green); 109 + color: var(--icarly-yellow); 110 110 animation: spin 3s linear infinite; 111 111 } 112 112 113 113 /* Logo styling - ENLARGED */ 114 114 .icarly-logo { 115 115 grid-area: logo; 116 - align-self: start; 117 - justify-self: start; 116 + align-self: center; 117 + justify-self: center; 118 118 background: var(--icarly-magenta); 119 119 padding: 20px 40px; 120 - border: 4px solid #fff; 121 - box-shadow: 6px 6px 0 rgba(0,0,0,0.3); 120 + border: 5px solid #fff; 121 + box-shadow: 8px 8px 0 rgba(0,0,0,0.4); 122 122 z-index: 10; 123 - transform: rotate(-3deg); 123 + transform: rotate(-2deg); 124 124 display: flex; 125 125 align-items: center; 126 126 justify-content: center; ··· 131 131 } 132 132 133 133 .icarly-logo img { 134 - height: 90px; 134 + height: 100px; 135 135 width: auto; 136 136 object-fit: contain; 137 137 } ··· 139 139 /* Date display */ 140 140 .date-display { 141 141 grid-area: date; 142 - align-self: end; 142 + align-self: start; 143 + justify-self: start; 143 144 color: #fff; 144 145 font-size: 18px; 145 146 font-weight: bold; 146 147 text-shadow: 2px 2px 0 rgba(0,0,0,0.3); 147 148 z-index: 5; 149 + padding-left: 30px; 148 150 } 149 151 150 152 .lemon-tube { 151 153 color: #FF6347; 152 154 font-size: 24px; 153 155 font-weight: bold; 154 - text-shadow: 2px 2px 0 #fff; 156 + text-shadow: 3px 3px 0 #fff, 3px 3px 8px rgba(0,0,0,0.3); 155 157 margin-top: 5px; 156 158 } 157 159 ··· 159 161 .search-section { 160 162 grid-area: search; 161 163 align-self: center; 162 - justify-self: center; 164 + justify-self: end; 163 165 text-align: center; 164 166 z-index: 5; 167 + margin-right: 30px; 165 168 } 166 169 167 170 .search-label { 168 171 color: #fff; 169 - font-size: 28px; 172 + font-size: 24px; 170 173 font-weight: bold; 171 174 text-shadow: 2px 2px 0 rgba(0,0,0,0.3); 172 - margin-bottom: 12px; 173 - animation: float 4s ease-in-out infinite; 175 + margin-bottom: 10px; 174 176 } 175 177 176 178 .search-box { 177 179 display: flex; 178 180 align-items: center; 179 - gap: 12px; 181 + gap: 10px; 180 182 } 181 183 182 184 .search-input { 183 - width: 280px; 184 - padding: 10px 20px; 185 + width: 260px; 186 + padding: 10px 18px; 185 187 border: 3px solid #fff; 186 - font-size: 18px; 188 + font-size: 16px; 187 189 outline: none; 188 190 font-family: 'Comic Neue', cursive; 189 191 box-shadow: 4px 4px 0 rgba(0,0,0,0.2); ··· 196 198 .search-btn { 197 199 background: #fff; 198 200 border: 3px solid #000; 199 - width: 45px; 200 - height: 45px; 201 + width: 42px; 202 + height: 42px; 201 203 cursor: pointer; 202 204 display: flex; 203 205 align-items: center; 204 206 justify-content: center; 205 - font-size: 20px; 207 + font-size: 18px; 206 208 box-shadow: 4px 4px 0 rgba(0,0,0,0.3); 207 - animation: float 3s ease-in-out infinite; 208 209 } 209 210 210 211 .search-btn:hover { ··· 217 218 display: flex; 218 219 flex-direction: column; 219 220 align-items: center; 220 - gap: 15px; 221 - padding-top: 10px; 221 + gap: 12px; 222 + padding-top: 0px; 223 + justify-self: end; 222 224 } 223 225 224 226 /* Character image */ 225 227 .character-image { 226 - width: 200px; 227 - height: 200px; 228 - border: 5px solid #fff; 229 - box-shadow: 6px 6px 0 rgba(0,0,0,0.3); 228 + width: 220px; 229 + height: 220px; 230 + border: 6px solid #fff; 231 + box-shadow: 8px 8px 0 rgba(0,0,0,0.4); 230 232 overflow: hidden; 231 - animation: float 5s ease-in-out infinite; 232 233 background: #fff; 234 + position: relative; 233 235 } 234 236 235 237 .character-image:hover { 236 - animation: wiggle 0.3s ease-in-out; 238 + transform: scale(1.05); 237 239 } 238 240 239 241 .character-image img { ··· 246 248 .header-buttons { 247 249 display: flex; 248 250 flex-direction: column; 249 - gap: 10px; 251 + gap: 8px; 250 252 width: 100%; 251 253 align-items: center; 252 254 } ··· 259 261 line-height: 1.3; 260 262 border: 3px solid #fff; 261 263 cursor: pointer; 262 - width: 180px; 264 + width: 200px; 263 265 transition: transform 0.2s; 264 266 text-decoration: none; 265 267 display: block; 268 + box-shadow: 4px 4px 0 rgba(0,0,0,0.3); 266 269 } 267 270 268 271 .header-btn:hover { 269 - transform: translateY(-3px); 272 + transform: translateY(-2px); 270 273 box-shadow: 0 6px 0 rgba(0,0,0,0.2); 271 274 } 272 275 ··· 277 280 } 278 281 279 282 .info-header-btn { 280 - background: #FF6B6B; 283 + background: linear-gradient(180deg, #FF8888 0%, #FF6B6B 100%); 281 284 color: #fff; 282 285 font-size: 13px; 283 286 } 284 287 285 288 .info-header-btn .btn-highlight { 286 289 color: #FFD700; 290 + font-weight: 900; 287 291 } 288 292 289 293 .feedback-header-btn { 290 - background: #FF4444; 294 + background: linear-gradient(180deg, #FF5555 0%, #FF4444 100%); 291 295 color: #fff; 292 - font-size: 14px; 296 + font-size: 13px; 293 297 } 294 298 295 299 .feedback-header-btn small { ··· 300 304 } 301 305 302 306 /* Character image - positioned in top right */ 303 - .character-image { 304 - position: absolute; 305 - right: 20px; 306 - top: 15px; 307 - width: 200px; 308 - height: 200px; 309 - border: 6px solid #fff; 310 - box-shadow: 8px 8px 0 rgba(0,0,0,0.3); 311 - overflow: hidden; 312 - z-index: 10; 313 - animation: float 5s ease-in-out infinite; 314 - background: #fff; 315 - } 316 - 317 - .character-image:hover { 318 - animation: wiggle 0.3s ease-in-out; 319 - } 320 - 321 - .character-image img { 322 - width: 100%; 323 - height: 100%; 324 - object-fit: cover; 325 - } 326 - 327 - .character-image:hover { 328 - animation: wiggle 0.3s ease-in-out; 329 - } 330 - 331 - .character-image img { 332 - width: 100%; 333 - height: 100%; 334 - object-fit: cover; 335 - } 336 307 337 308 /* Fun floating labels */ 338 309 .fun-label { ··· 348 319 .nav-tabs { 349 320 display: flex; 350 321 justify-content: center; 351 - background: linear-gradient(180deg, #A6CC3A 0%, #7BA03A 100%); 352 - padding: 10px 20px 0; 353 - gap: 0; 322 + background: linear-gradient(180deg, #A6CC3A 0%, #8BAE32 50%, #7BA03A 100%); 323 + padding: 8px 20px 0; 324 + gap: 2px; 354 325 position: relative; 355 326 border-left: 4px solid #fff; 356 327 border-right: 4px solid #fff; 328 + box-shadow: inset 0 10px 20px rgba(0,0,0,0.15); 357 329 } 358 330 359 331 /* You are here indicator */ ··· 375 347 } 376 348 377 349 .nav-tab { 378 - background: linear-gradient(180deg, #9B59B6 0%, #7B3F8C 50%, #62166F 100%); 350 + background: linear-gradient(180deg, #B8A6D9 5%, #9B59B6 20%, #8844AA 50%, #7B3F8C 70%, #62166F 95%); 379 351 color: #fff; 380 - padding: 15px 20px; 352 + padding: 12px 18px; 381 353 font-weight: bold; 382 - font-size: 14px; 354 + font-size: 13px; 383 355 text-transform: uppercase; 384 356 cursor: pointer; 385 357 border: 3px solid #fff; 386 358 border-bottom: none; 387 359 position: relative; 388 - top: 4px; 360 + top: 3px; 389 361 display: flex; 390 362 align-items: center; 391 363 gap: 6px; 392 364 font-family: 'Comic Neue', cursive; 393 365 text-decoration: none; 394 366 box-shadow: 395 - inset 0 2px 5px rgba(255,255,255,0.3), 396 - 0 -3px 10px rgba(0,0,0,0.2); 397 - text-shadow: 1px 1px 0 rgba(0,0,0,0.5); 367 + inset 0 3px 8px rgba(255,255,255,0.4), 368 + inset 0 -2px 5px rgba(0,0,0,0.3), 369 + 0 -2px 8px rgba(0,0,0,0.2); 370 + text-shadow: 1px 1px 2px rgba(0,0,0,0.6); 398 371 } 399 372 400 373 .nav-tab:first-child { 401 - border-radius: 15px 0 0 0; 374 + border-radius: 12px 0 0 0; 402 375 } 403 376 404 377 .nav-tab:last-child { 405 - border-radius: 0 15px 0 0; 378 + border-radius: 0 12px 0 0; 406 379 } 407 380 408 381 .nav-tab:hover { 409 - background: linear-gradient(180deg, #B069C6 0%, #9B4F9C 50%, #82267F 100%); 410 - top: 2px; 382 + background: linear-gradient(180deg, #C8B6E9 5%, #B069C6 20%, #9B54BA 50%, #9B4F9C 70%, #82267F 95%); 383 + top: 1px; 411 384 } 412 385 413 386 .nav-tab.active { 414 - background: linear-gradient(180deg, #fff 0%, #f0f0f0 100%); 387 + background: linear-gradient(180deg, #fff 0%, #f8f8f8 50%, #f0f0f0 100%); 415 388 color: #62166F; 416 389 top: 0; 417 - padding-bottom: 19px; 390 + padding-bottom: 16px; 418 391 box-shadow: 419 - inset 0 2px 5px rgba(255,255,255,1), 420 - 0 -5px 15px rgba(0,0,0,0.1); 392 + inset 0 3px 8px rgba(255,255,255,1), 393 + inset 0 -2px 5px rgba(200,200,200,0.3), 394 + 0 -3px 12px rgba(0,0,0,0.15); 421 395 text-shadow: none; 422 396 } 423 397
+3 -3
src/app/layout.tsx
··· 6 6 title: "iStream - Video on Demand", 7 7 description: "Watch videos from the stream.place community! The coolest VOD site inspired by iCarly.", 8 8 icons: { 9 - icon: "/favicon.ico", 10 - shortcut: "/favicon.ico", 11 - apple: "/favicon.ico", 9 + icon: "/iStream_Logo.png", 10 + shortcut: "/iStream_Logo.png", 11 + apple: "/iStream_Logo.png", 12 12 }, 13 13 openGraph: { 14 14 title: "iStream - Video on Demand",
+1 -20
src/components/VideoCard.tsx
··· 51 51 const id = video.uri.split('/').pop(); 52 52 const displayName = getDisplayName(video.handle); 53 53 54 - // Check if this is an AtmosphereConf stream 55 - const isAtmosphereConf = ['stream1.atmosphereconf.org', 'stream2.atmosphereconf.org', 'stream3.atmosphereconf.org'].includes(video.handle); 56 - 57 - // Generate gradient based on title (only for non-AtmosphereConf videos) 58 - const colors = [ 59 - ['#FF6B6B', '#4ECDC4'], 60 - ['#667eea', '#764ba2'], 61 - ['#f093fb', '#f5576c'], 62 - ['#4facfe', '#00f2fe'], 63 - ['#43e97b', '#38f9d7'], 64 - ]; 65 - let hash = 0; 66 - for (let i = 0; i < video.value.title.length; i++) { 67 - hash = video.value.title.charCodeAt(i) + ((hash << 5) - hash); 68 - } 69 - const [color1, color2] = colors[Math.abs(hash) % colors.length]; 70 - 71 54 return ( 72 55 <a 73 56 href={`/watch?id=${id}`} ··· 79 62 <div 80 63 className="video-thumbnail" 81 64 style={{ 82 - background: isAtmosphereConf 83 - ? 'url(/atmosphere-conf-thumb.png) center/cover no-repeat' 84 - : `linear-gradient(135deg, ${color1}, ${color2})` 65 + background: 'url(/atmosphere-conf-thumb.png) center/cover no-repeat' 85 66 }} 86 67 > 87 68 <div className="play-overlay">▶</div>