🚀 Init

This commit is contained in:
Korbs 2024-08-15 16:54:57 -04:00
parent 340453c37a
commit 34873130d8
13 changed files with 423 additions and 0 deletions

24
.gitignore vendored Normal file
View file

@ -0,0 +1,24 @@
# build output
dist/
# generated types
.astro/
# dependencies
node_modules/
# logs
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
# environment variables
.env
.env.production
# macOS-specific files
.DS_Store
# jetbrains setting folder
.idea/

20
astro.config.mjs Normal file
View file

@ -0,0 +1,20 @@
import { defineConfig } from 'astro/config'
import node from "@astrojs/node"
export default defineConfig({
output: 'server',
adapter: node({
mode: "standalone"
}),
devToolbar: {
enabled: false
},
vite: {
server: {
hmr: false, // Auto Reload
}
},
experimental: {
serverIslands: true
}
})

BIN
bun.lockb Executable file

Binary file not shown.

19
package.json Normal file
View file

@ -0,0 +1,19 @@
{
"name": "minpluto-server-island",
"type": "module",
"version": "0.0.1",
"scripts": {
"dev": "astro dev",
"start": "astro dev",
"build": "astro build",
"preview": "astro preview",
"astro": "astro"
},
"dependencies": {
"@astrojs/node": "^8.3.3",
"astro": "^4.14.2"
},
"devDependencies": {
"sass-embedded": "^1.77.8"
}
}

BIN
public/default.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

View file

@ -0,0 +1,88 @@
---
import Video from '@components/Video.astro'
const Channel = await fetch("https://yt.sudovanilla.org/api/v1/channels/UCY1kMZp36IQSyNx_9h4mpCg").then((response) => response.json())
---
<div class="channel">
<div class="channel-header">
<div class="channel-header-start">
<img src={Channel.authorThumbnails[5].url}/>
<h2>{Channel.author}</h2>
</div>
<div class="channel-header-end">
<button>Subscribe</button>
</div>
</div>
<div class="tabs">
<a href="#">Videos</a>
<a href="#">Playlists</a>
<a href="#">Posts</a>
<a href="#">About</a>
</div>
<div class="video-grid">
{Channel.latestVideos.map((data) =>
<Video
ID={data.videoId}
Title={data.title}
Creator={data.author}
Views={data.viewCount}
UploadDate={data.published}
Length={data.lengthSeconds}
/>
)}
</div>
</div>
<style lang="scss">
.channel {
.channel-header {
display: flex;
align-items: center;
justify-content: space-between;
padding: 0px 24px;
.channel-header-start {
display: flex;
align-items: center;
gap: 24px;
img {
width: 64px;
height: 64px;
border-radius: 3rem;
}
}
.channel-header-end {
button {
color: black;
background: white;
border: none;
border-radius: 3rem;
padding: 8px 16px;
font-size: 16px;
font-weight: bold;
}
}
}
.tabs {
display: flex;
gap: 12px;
margin: 16px 0px;
padding: 0px 24px;
a {
color: white;
text-decoration: none;
background: #373737;
padding: 12px 24px;
border-radius: 6px;
}
}
}
.video-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
grid-gap: 25px;
max-width: 100%;
margin: auto;
padding: 0px 24px;
}
</style>

View file

@ -0,0 +1,150 @@
---
import Video from '@components/Video.astro'
const Channel = await fetch("https://yt.sudovanilla.org/api/v1/channels/UCY1kMZp36IQSyNx_9h4mpCg").then((response) => response.json())
---
<div class="channel">
<div class="channel-header">
<div class="channel-header-start">
<div class="loading-skel-avatar"></div>
<div class="loading-skel"></div>
</div>
<div class="channel-header-end">
<div class="loading-skel"></div>
</div>
</div>
<div class="tabs">
<div class="loading-skel"></div>
<div class="loading-skel"></div>
<div class="loading-skel"></div>
<div class="loading-skel"></div>
</div>
<div class="video-grid">
<div class="loading-skel-video"></div>
<div class="loading-skel-video"></div>
<div class="loading-skel-video"></div>
<div class="loading-skel-video"></div>
<div class="loading-skel-video"></div>
<div class="loading-skel-video"></div>
<div class="loading-skel-video"></div>
<div class="loading-skel-video"></div>
<div class="loading-skel-video"></div>
<div class="loading-skel-video"></div>
<div class="loading-skel-video"></div>
<div class="loading-skel-video"></div>
<div class="loading-skel-video"></div>
<div class="loading-skel-video"></div>
<div class="loading-skel-video"></div>
<div class="loading-skel-video"></div>
<div class="loading-skel-video"></div>
<div class="loading-skel-video"></div>
<div class="loading-skel-video"></div>
<div class="loading-skel-video"></div>
</div>
</div>
<style lang="scss">
@keyframes wave-lines {
0% {
background-position: -468px 0;
}
100% {
background-position: 468px 0;
}
}
@keyframes wave-squares {
0% {
background-position: -468px 0;
}
100% {
background-position: 468px 0;
}
}
.loading-skel {
height: 32px;
background: linear-gradient(to right, rgba(130, 130, 130, 0.2) 8%, rgba(130, 130, 130, 0.3) 18%, rgba(130, 130, 130, 0.2) 33%);
background-size: 800px 100px;
animation: wave-lines 1s infinite ease-out;
border-radius: 12px;
padding: 12px;
max-width: 100px;
min-width: 100px;
width: 100%;
margin-bottom: 20px;
display: flex;
}
.loading-skel-avatar {
background: linear-gradient(to right, rgba(130, 130, 130, 0.2) 8%, rgba(130, 130, 130, 0.3) 18%, rgba(130, 130, 130, 0.2) 33%);
background-size: 800px 100px;
animation: wave-lines 1s infinite ease-out;
border-radius: 3rem;
margin-bottom: 20px;
display: flex;
aspect-ratio: 1;
width: 137.7px;
height: 65px;
}
.loading-skel-video {
height: 232px;
margin-bottom: 6px;
background: linear-gradient(to right, rgba(130, 130, 130, 0.2) 8%, rgba(130, 130, 130, 0.3) 18%, rgba(130, 130, 130, 0.2) 33%);
background-size: 800px 100px;
animation: wave-lines 2s infinite ease-out;
border-radius: 12px;
}
.channel {
.channel-header {
display: flex;
align-items: center;
justify-content: space-between;
padding: 0px 24px;
.channel-header-start {
display: flex;
align-items: center;
gap: 24px;
img {
width: 64px;
height: 64px;
border-radius: 3rem;
}
}
.channel-header-end {
button {
color: black;
background: white;
border: none;
border-radius: 3rem;
padding: 8px 16px;
font-size: 16px;
font-weight: bold;
}
}
}
.tabs {
display: flex;
gap: 12px;
margin: 16px 0px;
padding: 0px 24px;
a {
color: white;
text-decoration: none;
background: #373737;
padding: 12px 24px;
border-radius: 6px;
}
}
}
.video-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
grid-gap: 25px;
max-width: 100%;
margin: auto;
padding: 0px 24px;
}
</style>

View file

@ -0,0 +1,71 @@
---
// Properties
const {
ID,
Title,
Creator,
Views,
UploadDate,
Length
} = Astro.props
// Format Published Date
const DateFormat = new Date(UploadDate * 1000).toLocaleDateString()
// Format Views
const ViewsConversion = Intl.NumberFormat('en', { notation: 'compact'})
const ViewsFormat = ViewsConversion.format(Views)
---
<a href={'/watch?v=' + ID} class="video-item">
<div class="video-item-thumbnail">
<img onload="this.style.opacity = '1'" src={'https://ipx.sudovanilla.org' + '/https://i.ytimg.com/vi/' + ID + '/hqdefault.jpg'} loading="lazy"/>
<p id="vi-length">{Length}</p>
</div>
<div class="video-item-details">
<p id="vi-title">{Title}</p>
<p id="vi-author">By {Creator}</p>
<p id="vi-viewCount">{ViewsFormat} Views - {DateFormat}</p>
</div>
</a>
<style lang="scss">
.video-item {
display: flex;
flex-direction: column;
color: white;
text-decoration: none;
.video-item-thumbnail {
img {
width: 100%;
border-radius: 6px;
aspect-ratio: 16/9;
object-fit: cover;
opacity: 0;
transition: 0.3s opacity;
}
p#vi-length {
margin: -41px 0px 0px 0px;
background: rgba(0,0,0,0.75);
padding: 12px 6px 6px 16px;
width: max-content;
border-radius: 50px 0px 6px 0px;
position: relative;
float: right;
}
}
.video-item-details {
display: flex;
flex-direction: column;
p {
margin: 0px;
&#vi-title {
font-weight: bold;
}
&#vi-author {
color: darkgrey;
}
}
}
}
</style>

1
src/env.d.ts vendored Normal file
View file

@ -0,0 +1 @@
/// <reference path="../.astro/types.d.ts" />

21
src/layouts/Default.astro Normal file
View file

@ -0,0 +1,21 @@
---
const { Title } = Astro.props
---
<html>
<head>
<title>{Title}</title>
</head>
<body>
<p><a href="/">Without Server Island</a> | <a href="/island">Server Island</a></p>
<slot/>
</body>
</html>
<style>
body {
background: black;
color: white;
font-family: Arial, Helvetica, sans-serif;
}
</style>

9
src/pages/index.astro Normal file
View file

@ -0,0 +1,9 @@
---
import ChannelCard from '@components/ChannelCard.astro'
import ChannelCardSkeleton from '@components/ChannelCardSkeleton.astro'
import Base from '@layouts/Default.astro'
---
<Base Title="Server Island">
<ChannelCard/>
</Base>

11
src/pages/island.astro Normal file
View file

@ -0,0 +1,11 @@
---
import ChannelCard from '@components/ChannelCard.astro'
import ChannelCardSkeleton from '@components/ChannelCardSkeleton.astro'
import Base from '@layouts/Default.astro'
---
<Base Title="Server Island">
<ChannelCard server:defer>
<ChannelCardSkeleton slot='fallback'/>
</ChannelCard>
</Base>

9
tsconfig.json Normal file
View file

@ -0,0 +1,9 @@
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@components/*": ["src/components/*"],
"@layouts/*": ["src/layouts/*"]
}
}
}