feat: initialize site with config, logo, and basic layout
This commit is contained in:
@@ -2,4 +2,6 @@
|
||||
import { defineConfig } from 'astro/config'
|
||||
|
||||
// https://astro.build/config
|
||||
export default defineConfig({})
|
||||
export default defineConfig({
|
||||
site: 'https://srjuggernaut.dev'
|
||||
})
|
||||
|
||||
BIN
public/DefaultOG.png
Normal file
BIN
public/DefaultOG.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 51 KiB |
71
src/components/SrJuggernautLogo.astro
Normal file
71
src/components/SrJuggernautLogo.astro
Normal file
@@ -0,0 +1,71 @@
|
||||
---
|
||||
interface Props {
|
||||
width?: number
|
||||
height?: number
|
||||
className?: string
|
||||
}
|
||||
const { width = 200, height = 200, className } = Astro.props
|
||||
---
|
||||
|
||||
<svg
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
width={width}
|
||||
height={height}
|
||||
class={className}
|
||||
viewBox="0 0 2500 2500"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<g
|
||||
id="g193"
|
||||
style="display:inline"
|
||||
transform="translate(69.745229,100.53816)"
|
||||
>
|
||||
<path
|
||||
id="path173"
|
||||
d="M 0,0 V 281.011 L 145.56,378.7 193.8,496.063 -38.59,395.585 48.25,712.774 274.98,903.33 c 0,0 71.16,-55.478 137.49,-172.464 V 436.59 Z"
|
||||
transform="matrix(1.1293021,0,0,-1.2103512,1343.6878,1768.72)"
|
||||
/>
|
||||
<path
|
||||
id="path174"
|
||||
d="M 0,0 V 281.011 L -145.554,378.7 -193.796,496.063 38.593,395.585 -48.242,712.774 -274.978,903.33 c 0,0 -71.156,-55.48 -137.488,-172.466 V 436.59 Z"
|
||||
transform="matrix(1.1293021,0,0,-1.2103512,1024.9874,1768.72)"
|
||||
/>
|
||||
<path
|
||||
id="path175"
|
||||
d="m 0,0 -194.55,-164.022 66.71,253.269 c 0,0 91.66,-50.654 127.84,-89.247"
|
||||
transform="matrix(1.1293021,0,0,-1.2103512,1632.4278,656.39878)"
|
||||
/>
|
||||
<path
|
||||
id="path176"
|
||||
d="M 0,0 194.55,-164.022 127.841,89.247 C 127.841,89.247 36.181,38.593 0,0"
|
||||
transform="matrix(1.1293021,0,0,-1.2103512,736.24636,656.39878)"
|
||||
/>
|
||||
<path
|
||||
id="path177"
|
||||
d="m 0,0 68.44,50.654 183.32,677.795 c 0,0 -231.56,229.147 -501.714,0 33.769,-118.192 183.318,-677.8 183.318,-677.8 z"
|
||||
transform="matrix(1.1293021,0,0,-1.2103512,1184.6821,1397.9435)"
|
||||
/>
|
||||
<path
|
||||
id="path178"
|
||||
d="m 0,0 -26.533,74.78 -410.054,446.234 -2.412,168.845 -156.785,-118.192 -125.429,-69.95 -108.543,-106.132 173.669,28.945 176.083,-94.071 -14.473,-50.654 L -62.714,-9.64 Z"
|
||||
transform="matrix(1.1293021,0,0,-1.2103512,992.29978,1894.2576)"
|
||||
/>
|
||||
<path
|
||||
id="path179"
|
||||
d="M 0,0 26.54,74.77 436.59,521.006 439,689.851 595.79,571.659 721.21,501.709 829.76,395.578 656.09,424.522 480.01,330.451 494.48,279.798 62.72,-9.65 Z"
|
||||
transform="matrix(1.1293021,0,0,-1.2103512,1368.2049,1891.3287)"
|
||||
/>
|
||||
<path
|
||||
id="path180"
|
||||
d="M 0,0 28.58,66.523 170.31,141.547 148.07,83.058 Z"
|
||||
transform="matrix(1.1293021,0,0,-1.2103512,1317.2846,1390.9331)"
|
||||
/>
|
||||
<path
|
||||
id="path181"
|
||||
d="m 0,0 -28.579,66.523 -141.731,75.024 22.241,-58.489 z"
|
||||
transform="matrix(1.1293021,0,0,-1.2103512,1067.7417,1393.8525)"
|
||||
/>
|
||||
</g>
|
||||
</svg>
|
||||
58
src/components/layout/Basic.astro
Normal file
58
src/components/layout/Basic.astro
Normal file
@@ -0,0 +1,58 @@
|
||||
---
|
||||
import Footer from '@/components/layout/Footer.astro'
|
||||
import Header from '@/components/layout/Header.astro'
|
||||
import '@/index.css'
|
||||
import { containerClass } from '@/styles/container'
|
||||
import '@fontsource-variable/roboto'
|
||||
import { getSecret } from 'astro:env/server'
|
||||
import { css, cx } from '@styled-system/css'
|
||||
export interface Props {
|
||||
title?: string
|
||||
description?: string
|
||||
imageUrl?: string
|
||||
}
|
||||
|
||||
const { title, description, imageUrl } = Astro.props
|
||||
const permalink = new URL(Astro.url.pathname, Astro.site).href
|
||||
const seoTitle =
|
||||
title === undefined ? 'SrJuggernaut Dev' : `${title} | SrJuggernaut Dev`
|
||||
const seoDescription =
|
||||
description === undefined ? 'SrJuggernaut developer site' : description
|
||||
const seoImage =
|
||||
imageUrl === undefined ? 'https://srjuggernaut.dev/DefaultOG.png' : imageUrl
|
||||
|
||||
const bodyClass = css({
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
minHeight: '100vh'
|
||||
})
|
||||
|
||||
const mainClass = cx(containerClass, css({ flexGrow: 1 }))
|
||||
---
|
||||
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<link rel="icon" type="image/svg+xml" href="/favicon.svg">
|
||||
<link rel="icon" href="/favicon.ico">
|
||||
<meta name="viewport" content="width=device-width">
|
||||
<!-- SEO -->
|
||||
|
||||
<title>{seoTitle}</title>
|
||||
<meta name="description" content={seoDescription}>
|
||||
|
||||
<!-- Open Graph -->
|
||||
|
||||
<meta property="og:title" content={seoTitle}>
|
||||
<meta property="og:description" content={seoDescription}>
|
||||
<meta property="og:url" content={permalink}>
|
||||
<meta property="og:image" content={seoImage}>
|
||||
</head>
|
||||
<body class={bodyClass}>
|
||||
<Header />
|
||||
<main class={mainClass}>
|
||||
<slot />
|
||||
</main>
|
||||
<Footer />
|
||||
</body>
|
||||
</html>
|
||||
93
src/components/layout/Footer.astro
Normal file
93
src/components/layout/Footer.astro
Normal file
@@ -0,0 +1,93 @@
|
||||
---
|
||||
import { css, cx } from '@styled-system/css'
|
||||
import { containerClass } from '@/styles/container'
|
||||
|
||||
interface FooterSection {
|
||||
title?: string
|
||||
links: {
|
||||
label: string
|
||||
href: string
|
||||
}[]
|
||||
}
|
||||
|
||||
const sections: FooterSection[] = [
|
||||
{
|
||||
title: 'Code & Work',
|
||||
links: [
|
||||
{ label: 'GitHub', href: 'https://github.com/SrJuggernaut' },
|
||||
{ label: 'Gitea Instance', href: 'https://git.srjuggernaut.dev/' }
|
||||
]
|
||||
},
|
||||
{
|
||||
title: 'Social & Contact',
|
||||
links: [
|
||||
{ label: 'Twitter', href: 'https://twitter.com/SrJuggernaut' },
|
||||
{
|
||||
label: 'Blue Sky',
|
||||
href: 'https://bsky.app/profile/jugger.srjuggernaut.dev'
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
const footerContainerClass = cx(
|
||||
containerClass,
|
||||
css({
|
||||
display: 'grid',
|
||||
gridTemplateColumns: 'repeat(auto-fit, minmax(256px, 1fr))',
|
||||
gap: 'lg md'
|
||||
})
|
||||
)
|
||||
|
||||
const footerSectionTitleClass = css({
|
||||
display: 'block',
|
||||
fontWeight: 'bold',
|
||||
fontSize: 'h4',
|
||||
textAlign: 'center'
|
||||
})
|
||||
|
||||
const footerSectionListClass = css({
|
||||
listStyle: 'none'
|
||||
})
|
||||
|
||||
const footerSectionItemClass = css({
|
||||
paddingInlineStart: 'sm',
|
||||
textIndent: '-xs',
|
||||
'&:before': {
|
||||
content: '"⟫"',
|
||||
paddingInline: 'xs'
|
||||
}
|
||||
})
|
||||
|
||||
const footerLegendClass = css({
|
||||
paddingBlock: 'md',
|
||||
textAlign: 'center',
|
||||
fontSize: 'sm'
|
||||
})
|
||||
|
||||
const footerLegendHeartClass = css({
|
||||
color: 'red'
|
||||
})
|
||||
---
|
||||
|
||||
<footer>
|
||||
<div class={footerContainerClass}>
|
||||
{sections.map(section => (
|
||||
<section>
|
||||
<span class={footerSectionTitleClass} role="heading" aria-level="3">{section.title}</span>
|
||||
<ul class={footerSectionListClass} >
|
||||
{section.links.map(link => (
|
||||
<li class={footerSectionItemClass}>
|
||||
<a href={link.href}>{link.label}</a>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</section>
|
||||
))}
|
||||
</div>
|
||||
<p class={footerLegendClass}>
|
||||
Made with <span class={footerLegendHeartClass}>♥</span> and
|
||||
<a href="https://astro.build">Astro</a> by
|
||||
<a href="https://srjuggernaut.dev">Jugger</a>
|
||||
</p>
|
||||
</footer>
|
||||
22
src/components/layout/Header.astro
Normal file
22
src/components/layout/Header.astro
Normal file
@@ -0,0 +1,22 @@
|
||||
---
|
||||
import { css, cx } from '@styled-system/css'
|
||||
import SrJuggernautLogo from '@/components/SrJuggernautLogo.astro'
|
||||
import Button from '@/components/ui/button.astro'
|
||||
import { containerClass } from '@/styles/container'
|
||||
import Menu from './header/Menu.astro'
|
||||
|
||||
const headerClass = css({})
|
||||
---
|
||||
|
||||
<header class={headerClass}>
|
||||
<div
|
||||
class={cx(containerClass, css({display: 'flex', alignItems: 'center', justifyContent: 'space-between'}))}
|
||||
>
|
||||
<SrJuggernautLogo
|
||||
width={64}
|
||||
height={64}
|
||||
className={css({fill: "neutral.12"})}
|
||||
/>
|
||||
<Menu />
|
||||
</div>
|
||||
</header>
|
||||
85
src/components/layout/header/Menu.astro
Normal file
85
src/components/layout/header/Menu.astro
Normal file
@@ -0,0 +1,85 @@
|
||||
---
|
||||
import { css, cx } from '@styled-system/css'
|
||||
import { menu } from '@styled-system/recipes/menu'
|
||||
import SrJuggernautLogo from '@/components/SrJuggernautLogo.astro'
|
||||
import Button from '@/components/ui/button.astro'
|
||||
|
||||
const dialogClass = css({
|
||||
marginLeft: 'auto',
|
||||
width: '100%',
|
||||
maxWidth: '256px',
|
||||
height: '100%',
|
||||
maxHeight: '100vh',
|
||||
backgroundColor: 'neutral.3',
|
||||
color: 'neutral.12',
|
||||
transition: 'transform 0.3s',
|
||||
transitionTimingFunction: 'easeOutQuint',
|
||||
transform: 'translateX(0%)',
|
||||
'@starting-style': {
|
||||
transform: 'translateX(100%)'
|
||||
},
|
||||
_backdrop: {
|
||||
transition: 'background-color 0.45s',
|
||||
transitionTimingFunction: 'easeOutQuint',
|
||||
backgroundColor: 'neutral.1/75',
|
||||
'@starting-style': {
|
||||
backgroundColor: 'neutral.1/0'
|
||||
}
|
||||
}
|
||||
})
|
||||
const dialogHeaderClass = css({
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-between'
|
||||
})
|
||||
|
||||
const links = [{ label: 'Home', href: '/' }]
|
||||
---
|
||||
|
||||
<Button id="menu-button" variant="ghost" color="primary">
|
||||
Menu <!-- TODO: Icon -->
|
||||
</Button>
|
||||
<dialog class={dialogClass} id="menu" closedby="any">
|
||||
<div class={dialogHeaderClass}>
|
||||
<SrJuggernautLogo
|
||||
width={64}
|
||||
height={64}
|
||||
className={css({fill: "neutral.12"})}
|
||||
/>
|
||||
<Button id="close-menu" variant="ghost" color="primary">
|
||||
Close <!-- TODO: Icon -->
|
||||
</Button>
|
||||
</div>
|
||||
<nav role="navigation">
|
||||
<menu class={cx(menu({color: "neutral"}).container, css({width: '100%'}))}>
|
||||
{links.map(link => (
|
||||
<li class={css({all: 'unset', width: '100%'})}>
|
||||
<a href={link.href} class={menu({color: "neutral"}).item} >
|
||||
{link.label}
|
||||
</a>
|
||||
</li>
|
||||
))}
|
||||
</menu>
|
||||
</nav>
|
||||
</dialog>
|
||||
|
||||
<script>
|
||||
const menuButton = document.getElementById(
|
||||
'menu-button'
|
||||
) as HTMLButtonElement | null
|
||||
const menu = document.getElementById('menu') as HTMLDialogElement | null
|
||||
const closeMenu = document.getElementById(
|
||||
'close-menu'
|
||||
) as HTMLButtonElement | null
|
||||
if (menuButton === null || menu === null || closeMenu === null) {
|
||||
throw new Error('Menu not found')
|
||||
}
|
||||
|
||||
closeMenu.addEventListener('click', () => {
|
||||
menu.close()
|
||||
})
|
||||
|
||||
menuButton.addEventListener('click', () => {
|
||||
menu.showModal()
|
||||
})
|
||||
</script>
|
||||
@@ -1,18 +0,0 @@
|
||||
---
|
||||
import '@/index.css'
|
||||
import '@fontsource-variable/roboto'
|
||||
---
|
||||
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<link rel="icon" type="image/svg+xml" href="/favicon.svg">
|
||||
<link rel="icon" href="/favicon.ico">
|
||||
<meta name="viewport" content="width=device-width">
|
||||
<meta name="generator" content={Astro.generator}>
|
||||
<title>SrJuggernaut Dev</title>
|
||||
</head>
|
||||
<body>
|
||||
<slot />
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
import { css } from '@styled-system/css'
|
||||
import BasicLayout from '@/layouts/Basic.astro'
|
||||
import BasicLayout from '@/components/layout/Basic.astro'
|
||||
---
|
||||
|
||||
<BasicLayout>
|
||||
|
||||
Reference in New Issue
Block a user