Non-official site for The Life Series Minecraft hardcore survival multiplayer series housing every video www.life-series.online
0
fork

Configure Feed

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

Nice life (#40)

authored by

Ghustvn and committed by
GitHub
cd04332e ed19425a

+239 -17
src/assets/images/og/seasons/nice-life.png

This is a binary file and will not be displayed.

src/assets/images/seasons/nice-life.webp

This is a binary file and will not be displayed.

+1 -1
src/components/SessionList.astro
··· 20 20 sessionNumbers.map((session) => ( 21 21 <li> 22 22 <a 23 - href={`/seasons/${season.data.seasonNumber}/sessions/${session}`} 23 + href={`/seasons/${season.id}/sessions/${session}`} 24 24 class:list={[ 25 25 'bg-canvas-text/5 border-canvas-text/25 flex items-center justify-center rounded-full border-1 p-8 shadow-xs', 26 26 { 'mx-6 aspect-square h-44': !withText },
-1
src/content.config.ts
··· 5 5 loader: file('src/data/seasons.json'), 6 6 schema: z.object({ 7 7 title: z.string(), 8 - seasonNumber: z.number(), 9 8 sessionCount: z.number().optional(), 10 9 seo: z.object({ 11 10 description: z.object({
+91
src/data/seasons.json
··· 1 1 [ 2 2 { 3 + "id": "nice-life", 4 + "title": "Nice Life", 5 + "sessionCount": 1, 6 + "seo": { 7 + "description": { 8 + "twist": "A 3 part holiday special" 9 + } 10 + }, 11 + "videos": { 12 + "BdoubleO100": [], 13 + "BigB": [ 14 + { 15 + "id": "bG8661ptl8U", 16 + "title": "Nice Life SMP | Ep.1 | THE BIG SURPRISE!" 17 + } 18 + ], 19 + "GeminiTay": [ 20 + { 21 + "id": "8g50TLYu9hw", 22 + "title": "A Cute Christmas Cottage! Nice Life: Episode 1" 23 + } 24 + ], 25 + "GoodTimesWithScar": [ 26 + { 27 + "id": "VXVJfPU_moo", 28 + "title": "Santa Burned Down My House - Nice Life Episode 1" 29 + } 30 + ], 31 + "Grian": [ 32 + { 33 + "id": "2teag5QC7NA", 34 + "title": "Nice Life: Episode 1 - It's A Wonderful Life" 35 + } 36 + ], 37 + "Impulse": [ 38 + { 39 + "id": "5_dByS3XdRg", 40 + "title": "How Am I On The Naughty List!? | Nice Life Ep 01" 41 + } 42 + ], 43 + "InTheLittleWood": [ 44 + { 45 + "id": "Du3gkzYxgng", 46 + "title": "GET ME ON THE NAUGHTY LIST! - Minecraft Nice Life #1" 47 + } 48 + ], 49 + "PearlescentMoon": [ 50 + { 51 + "id": "2Z7TokffUlI", 52 + "title": "Christmas, But Not Quite Right | Nice Life: Episode 1" 53 + } 54 + ], 55 + "Rendog": [ 56 + { 57 + "id": "y5fAMDD-7Po", 58 + "title": "THANKS ALOT SANTA! | Nice Life SMP | Ep 01" 59 + } 60 + ], 61 + "Skizzleman": [ 62 + { 63 + "id": "VnC0cwZNhTg", 64 + "title": "My WORST Start EVER! - Nice Life - Ep.1" 65 + } 66 + ], 67 + "Smajor1995": [ 68 + { 69 + "id": "9zvwCwImBxM", 70 + "title": "Say One More Thing About My House! - NICE LIFE EP 1" 71 + } 72 + ], 73 + "SmallishBeans": [ 74 + { 75 + "id": "S5-mVaa7eMA", 76 + "title": "I've Been Naughty! | Nice Life | Ep.1" 77 + } 78 + ], 79 + "Solidarity": [ 80 + { 81 + "id": "1u1TOZwpI74", 82 + "title": "I'm Already On The NAUGHTY LIST!! | Nice Life | #1" 83 + } 84 + ], 85 + "ZombieCleo": [ 86 + { 87 + "id": "h6eQiU_imEE", 88 + "title": "Can I Survive the Red Christmas Curse? - 01 - Nice Life" 89 + } 90 + ] 91 + } 92 + }, 93 + { 3 94 "id": "7", 4 95 "title": "Past Life", 5 96 "seasonNumber": 7,
+1 -3
src/pages/index.astro
··· 72 72 loading="eager" 73 73 class="max-w-180" 74 74 /> 75 - <span class="sr-only"> 76 - {season.data.title} (Season {season.data.seasonNumber}) 77 - </span> 75 + <span class="sr-only">{season.data.title}</span> 78 76 </a> 79 77 </li> 80 78 ))
+4 -4
src/pages/seasons/7/sessions/[session_id].astro
··· 42 42 43 43 const { season, sessions, sessionNumbers, sessionNumber } = Astro.props; 44 44 45 - const title = `Session ${sessionNumber} · ${season.data.title} (S${season.data.seasonNumber})`; 45 + const title = `Session ${sessionNumber} · ${season.data.title}`; 46 46 --- 47 47 48 48 <SeasonsLayout ··· 51 51 > 52 52 <SEO 53 53 slot="seo" 54 - description={`Session ${sessionNumber} of ${season.data.title} (S${season.data.seasonNumber}).`} 54 + description={`Session ${sessionNumber} of ${season.data.title}.`} 55 55 /> 56 56 <div class="@container pt-8"> 57 57 <h2 58 58 id="all-sessions-title" 59 59 class="mx-fluid-v-320-768-16-24 md:mx-fluid-v-768-1930-24-128 text-base font-normal" 60 60 > 61 - {season.data.title} (S{season.data.seasonNumber}) sessions 61 + {season.data.title} sessions 62 62 </h2> 63 63 <div 64 64 class="mx-fluid-v-320-768-16-24 md:mx-fluid-v-768-1930-24-128 bg-canvas border-canvas-text/25 sticky top-0 z-1 max-w-720 overflow-x-auto overflow-y-clip border-b-1 py-12 motion-safe:scroll-smooth" ··· 80 80 tabindex="-1" 81 81 class="custom-trim-start mb-8 w-fit text-base text-balance" 82 82 > 83 - Session {sessionNumber} of {season.data.title} (S{season.data.seasonNumber}) 83 + Session {sessionNumber} of {season.data.title} 84 84 </h1> 85 85 <ul 86 86 role="list"
+4 -4
src/pages/seasons/[season_id].astro
··· 24 24 25 25 const { season, sessions } = Astro.props; 26 26 27 - const title = `${season.data.title} (S${season.data.seasonNumber})`; 27 + const title = `${season.data.title}`; 28 28 29 - const ogTitle = `${season.data.title} - Season ${season.data.seasonNumber} of The Life Series Minecraft hardcore survival multiplayer series.`; 29 + const ogTitle = `${season.data.title} - The Life Series Minecraft hardcore survival multiplayer series.`; 30 30 const ogDescription = `Watch all sessions. ${season.data.seo.description.twist}.`; 31 31 const ogImage = await getSeasonOGImage(season.id); 32 - const ogImageAlt = `The Life Series season ${season.data.seasonNumber} logo - ${season.data.title}`; 32 + const ogImageAlt = `The Life Series logo - ${season.data.title}`; 33 33 --- 34 34 35 35 <SeasonsLayout ··· 71 71 tabindex="-1" 72 72 class="text-3xl" 73 73 > 74 - {season.data.title} (S{season.data.seasonNumber}) 74 + {season.data.title} 75 75 </h1> 76 76 { 77 77 sessions.length > 0 ? (
+4 -4
src/pages/seasons/[season_id]/[member_name].astro
··· 44 44 const movie = videos.find((video) => video.isMovie); 45 45 const sessions = videos.filter((video) => !video.isMovie); 46 46 47 - const title = `${member.data.name} · ${season.data.title} (S${season.data.seasonNumber})`; 47 + const title = `${member.data.name} · ${season.data.title}`; 48 48 --- 49 49 50 50 <SeasonsLayout ··· 54 54 > 55 55 <SEO 56 56 slot="seo" 57 - description={`${member.data.name} point of view for ${season.data.title} (S${season.data.seasonNumber}).`} 57 + description={`${member.data.name} point of view for ${season.data.title}.`} 58 58 /> 59 59 <main class="@container"> 60 60 <div class="mx-fluid-v-320-768-16-24 md:mx-fluid-v-768-1930-24-128 max-w-1080 pb-[25vh]"> ··· 71 71 { 72 72 season.data.sessionCount && ( 73 73 <a 74 - href={`/seasons/${season.data.seasonNumber}/sessions/${season.data.sessionCount}`} 74 + href={`/seasons/${season.id}/sessions/${season.data.sessionCount}`} 75 75 class="py-8 text-base underline decoration-1 underline-offset-4 hover:no-underline" 76 76 > 77 - All {season.data.title} (S{season.data.seasonNumber}) sessions 77 + All {season.data.title} sessions 78 78 </a> 79 79 ) 80 80 }
+131
src/pages/seasons/nice-life/sessions/[session_id].astro
··· 1 + --- 2 + import { Image } from 'astro:assets'; 3 + import { getEntry, type CollectionEntry } from 'astro:content'; 4 + import { SEO } from 'astro-seo'; 5 + import { YouTube } from '@astro-community/astro-embed-youtube'; 6 + import SeasonsLayout from '@/layouts/SeasonsLayout.astro'; 7 + import SessionList from '@/components/SessionList.astro'; 8 + import { getMemberImage } from '@/utils/images'; 9 + 10 + export async function getStaticPaths() { 11 + function createSeasonSessionList(season: CollectionEntry<'seasons'>, sessionNumber: number) { 12 + return Object.entries(season.data.videos).map(([member, memberVideos]) => { 13 + return { 14 + [member]: memberVideos.filter((video) => !video.isMovie)[sessionNumber - 1], 15 + }; 16 + }); 17 + } 18 + 19 + const season = await getEntry('seasons', 'nice-life'); 20 + if (!season) { 21 + return; 22 + } 23 + 24 + const sessionNumbers = season.data.sessionCount 25 + ? Array.from(Array(season.data.sessionCount).keys()) 26 + .map((sessionIndex) => ++sessionIndex) 27 + .reverse() 28 + : []; 29 + 30 + return sessionNumbers.map((sessionNumber) => { 31 + return { 32 + params: { season_id: season.id, session_id: sessionNumber }, 33 + props: { 34 + season: season, 35 + sessions: createSeasonSessionList(season, sessionNumber), 36 + sessionNumbers, 37 + sessionNumber, 38 + }, 39 + }; 40 + }); 41 + } 42 + 43 + const { season, sessions, sessionNumbers, sessionNumber } = Astro.props; 44 + 45 + const title = `Session ${sessionNumber} · ${season.data.title}`; 46 + --- 47 + 48 + <SeasonsLayout 49 + title={title} 50 + season={season} 51 + > 52 + <SEO 53 + slot="seo" 54 + description={`Session ${sessionNumber} of ${season.data.title}.`} 55 + /> 56 + <div class="@container pt-8"> 57 + <h2 58 + id="all-sessions-title" 59 + class="mx-fluid-v-320-768-16-24 md:mx-fluid-v-768-1930-24-128 text-base font-normal" 60 + > 61 + {season.data.title} sessions 62 + </h2> 63 + <div 64 + class="mx-fluid-v-320-768-16-24 md:mx-fluid-v-768-1930-24-128 bg-canvas border-canvas-text/25 sticky top-0 z-1 max-w-720 overflow-x-auto overflow-y-clip border-b-1 py-12 motion-safe:scroll-smooth" 65 + > 66 + <nav aria-labelledby="all-sessions-title"> 67 + <SessionList 68 + season={season} 69 + sessionNumbers={sessionNumbers} 70 + withText={false} 71 + /> 72 + </nav> 73 + </div> 74 + <main> 75 + <div 76 + class="mx-fluid-v-320-768-16-24 md:mx-fluid-v-768-1930-24-128 pt-fluid-v-320-768-16-24 md:pt-fluid-c-320-1930-24-80 max-w-720 pb-[25vh]" 77 + > 78 + <h1 79 + id="main-content" 80 + tabindex="-1" 81 + class="custom-trim-start mb-8 w-fit text-base text-balance" 82 + > 83 + Session {sessionNumber} of {season.data.title} 84 + </h1> 85 + <ul 86 + role="list" 87 + aria-labelledby="main-content" 88 + class="space-y-fluid-c-320-768-24-64" 89 + > 90 + { 91 + sessions.map((session) => { 92 + return Object.entries(session).map( 93 + ([member, video]) => 94 + video && ( 95 + <li> 96 + <h2 class="grid gap-y-4 pb-8 text-base font-normal text-balance"> 97 + <div class="flex items-center gap-8"> 98 + <Image 99 + src={getMemberImage(member)} 100 + width="64" 101 + height="64" 102 + alt="" 103 + loading="eager" 104 + class="aspect-square max-w-32 rounded-full" 105 + /> 106 + <span>{member}</span> 107 + </div> 108 + <span class="text-h3">{video.title}</span> 109 + </h2> 110 + {import.meta.env.PROD ? ( 111 + <YouTube 112 + id={video.id} 113 + title={video.title} 114 + poster={`https://i.ytimg.com/vi_webp/${video.id}/maxresdefault.webp`} 115 + playlabel={`Play video: ${video.title}`} 116 + posterQuality="max" 117 + class="rounded-lg" 118 + /> 119 + ) : ( 120 + <div class="bg-canvas-text aspect-video max-w-720 rounded-lg" /> 121 + )} 122 + </li> 123 + ), 124 + ); 125 + }) 126 + } 127 + </ul> 128 + </div> 129 + </main> 130 + </div> 131 + </SeasonsLayout>
+3
src/styles/global.css
··· 183 183 li:nth-child(7) { 184 184 --angle: 1deg; 185 185 } 186 + li:nth-child(8) { 187 + --angle: -2deg; 188 + } 186 189 187 190 a { 188 191 transition: