new minimal retro theme, progress on parallax hero, refactor into semantic html,
add htmx and alpine, etc
|
|
@ -1,5 +1,25 @@
|
||||||
|
import htmx from "astro-htmx";
|
||||||
// @ts-check
|
// @ts-check
|
||||||
import { defineConfig } from 'astro/config';
|
import { defineConfig } from "astro/config";
|
||||||
|
import alpinejs from "@astrojs/alpinejs";
|
||||||
|
import partytown from "@astrojs/partytown";
|
||||||
|
import sitemap from "@astrojs/sitemap";
|
||||||
|
import bun from "@nurodev/astro-bun";
|
||||||
|
|
||||||
// https://astro.build/config
|
// https://astro.build/config
|
||||||
export default defineConfig({});
|
export default defineConfig({
|
||||||
|
site: "https://badblocks.dev",
|
||||||
|
adapter: bun(),
|
||||||
|
output: "static",
|
||||||
|
integrations: [
|
||||||
|
alpinejs(),
|
||||||
|
partytown(),
|
||||||
|
sitemap(),
|
||||||
|
htmx(),
|
||||||
|
// sitemap({
|
||||||
|
// filter: (page) =>
|
||||||
|
// page !== "https://example.com/secret-vip-lounge-1/" &&
|
||||||
|
// page !== "https://example.com/secret-vip-lounge-2/",
|
||||||
|
// }),
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
|
||||||
BIN
bun.lockb
15
package.json
|
|
@ -1,17 +1,26 @@
|
||||||
{
|
{
|
||||||
"name": "",
|
"name": "badblocks-personal-site",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "astro dev",
|
"dev": "astro dev",
|
||||||
|
"start": "bun run ./dist/server/entry.mjs",
|
||||||
"build": "astro build",
|
"build": "astro build",
|
||||||
"preview": "astro preview",
|
"preview": "astro preview",
|
||||||
"astro": "astro"
|
"astro": "astro"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"astro": "^5.16.6"
|
"@astrojs/alpinejs": "^0.4.9",
|
||||||
|
"@astrojs/partytown": "^2.1.4",
|
||||||
|
"@astrojs/sitemap": "^3.6.0",
|
||||||
|
"@nurodev/astro-bun": "^2.1.2",
|
||||||
|
"@types/alpinejs": "^3.13.11",
|
||||||
|
"alpinejs": "^3.15.3",
|
||||||
|
"astro": "^5.16.6",
|
||||||
|
"astro-htmx": "^1.0.6",
|
||||||
|
"htmx.org": "^2.0.8"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/bun": "^1.3.5"
|
"@types/bun": "^1.3.5"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
BIN
public/parallax/city-destroyed/0-sky.png
Normal file
|
After Width: | Height: | Size: 44 KiB |
BIN
public/parallax/city-destroyed/1-buildingssmoke.png
Normal file
|
After Width: | Height: | Size: 87 KiB |
BIN
public/parallax/city-destroyed/2-water.png
Normal file
|
After Width: | Height: | Size: 19 KiB |
BIN
public/parallax/city-destroyed/3-buildings.png
Normal file
|
After Width: | Height: | Size: 53 KiB |
BIN
public/parallax/city-destroyed/4-buildingreflection.png
Normal file
|
After Width: | Height: | Size: 108 KiB |
BIN
public/parallax/city-destroyed/5-frontsmoke.png
Normal file
|
After Width: | Height: | Size: 29 KiB |
|
Before Width: | Height: | Size: 3.9 KiB After Width: | Height: | Size: 3.9 KiB |
|
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 3.1 KiB |
|
Before Width: | Height: | Size: 6.2 KiB After Width: | Height: | Size: 6.2 KiB |
BIN
public/parallax/winternight/0-sky.png
Normal file
|
After Width: | Height: | Size: 19 KiB |
BIN
public/parallax/winternight/1-backmountain.png
Normal file
|
After Width: | Height: | Size: 166 KiB |
BIN
public/parallax/winternight/2-midmountain.png
Normal file
|
After Width: | Height: | Size: 25 KiB |
BIN
public/parallax/winternight/3-midforest.png
Normal file
|
After Width: | Height: | Size: 65 KiB |
BIN
public/parallax/winternight/4-frontfloor.png
Normal file
|
After Width: | Height: | Size: 69 KiB |
1172
public/style.css
Normal file
3
src/env.d.ts
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
interface Window {
|
||||||
|
Alpine: import("alpinejs").Alpine;
|
||||||
|
}
|
||||||
|
|
@ -5,20 +5,38 @@
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
||||||
<meta name="generator" content={Astro.generator} />
|
<meta name="generator" content={Astro.generator} />
|
||||||
<link rel="stylesheet" type="text/css" href="/snes.min.css" />
|
<link rel="stylesheet" type="text/css" href="/style.css" />
|
||||||
<script src="https://cdn.jsdelivr.net/npm/htmx.org@2.0.8/dist/htmx.min.js"
|
<link rel="sitemap" href="/sitemap-index.xml" />
|
||||||
></script>
|
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||||
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||||||
|
<link
|
||||||
|
href="https://fonts.googleapis.com/css2?family=VT323&display=swap"
|
||||||
|
rel="stylesheet"
|
||||||
|
/>
|
||||||
<style>
|
<style>
|
||||||
div.container {
|
:root {
|
||||||
|
--min-body-width: 30ch;
|
||||||
|
--max-body-width: 120ch;
|
||||||
|
font-size: 16px;
|
||||||
|
font-family: "VT323", monospace;
|
||||||
|
font-weight: 400;
|
||||||
|
font-style: normal;
|
||||||
|
}
|
||||||
|
body {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: 1fr;
|
grid-template-columns:
|
||||||
|
minmax(0.8rem, 1fr)
|
||||||
|
minmax(var(--min-body-width), var(--max-body-width))
|
||||||
|
minmax(0.8rem, 1fr);
|
||||||
grid-template-rows: auto 1fr auto;
|
grid-template-rows: auto 1fr auto;
|
||||||
grid-template-areas:
|
grid-template-areas:
|
||||||
"header"
|
". header ."
|
||||||
"content"
|
". content ."
|
||||||
"footer";
|
". footer .";
|
||||||
min-height: 100vh;
|
min-height: 100vh;
|
||||||
width: 100vw;
|
place-items: center;
|
||||||
|
width: 100%;
|
||||||
|
min-width: var(--min-body-width);
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
|
|
@ -26,100 +44,64 @@
|
||||||
|
|
||||||
header {
|
header {
|
||||||
grid-area: header;
|
grid-area: header;
|
||||||
display: grid;
|
|
||||||
grid-template-columns: auto 1fr;
|
|
||||||
align-items: center;
|
|
||||||
gap: 2rem;
|
|
||||||
padding: 1.5rem 2rem;
|
|
||||||
border-bottom: 1px solid #e5e5e5;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
nav {
|
header h1 {
|
||||||
justify-self: end;
|
text-transform: none;
|
||||||
}
|
border-bottom: none;
|
||||||
|
margin-bottom: 0;
|
||||||
nav ul {
|
padding-bottom: 0;
|
||||||
display: flex;
|
|
||||||
gap: 2rem;
|
|
||||||
list-style: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.logo {
|
|
||||||
padding: 1rem 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
nav li {
|
nav li {
|
||||||
height: 3.5rem;
|
align-content: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
nav li a {
|
nav li select {
|
||||||
display: inline-block;
|
margin: 0;
|
||||||
line-height: 3.5rem;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
section.content {
|
main {
|
||||||
grid-area: content;
|
grid-area: content;
|
||||||
padding: 4rem 2rem;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
footer {
|
footer {
|
||||||
grid-area: footer;
|
grid-area: footer;
|
||||||
display: grid;
|
display: grid;
|
||||||
place-items: center;
|
place-items: center;
|
||||||
padding: 2rem;
|
|
||||||
border-top: 1px solid #e5e5e5;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Tablet and up */
|
|
||||||
@media (min-width: 768px) {
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Desktop */
|
|
||||||
@media (min-width: 1024px) {
|
|
||||||
div.container {
|
|
||||||
grid-template-columns: repeat(12, 1fr);
|
|
||||||
grid-template-areas:
|
|
||||||
"header header header header header header header header header header header header"
|
|
||||||
"content content content content content content content content content content content content"
|
|
||||||
"footer footer footer footer footer footer footer footer footer footer footer footer";
|
|
||||||
}
|
|
||||||
|
|
||||||
header {
|
|
||||||
padding: 1.5rem 4rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
content {
|
|
||||||
padding-left: 4rem;
|
|
||||||
padding-right: 4rem;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
<slot name="head" />
|
<slot name="head" />
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body x-data="{ theme: 'winternight'}">
|
||||||
<div class="container">
|
<header>
|
||||||
<header>
|
<h1><a href="/">badblocks.dev</a></h1>
|
||||||
<a href="/"><div class="logo">badblocks.dev</div></a>
|
<nav>
|
||||||
<nav>
|
<ul>
|
||||||
<ul>
|
<li>
|
||||||
<li><a href="/">Home</a></li>
|
<select id="theme" x-model="theme">
|
||||||
<li><a href="/projects">Projects</a></li>
|
<option value="winternight">Winternight</option>
|
||||||
<li><a href="/contact">Contact</a></li>
|
<option value="sunnyvale-forest">SunnyVale</option>
|
||||||
<li><a href="https://git.badblocks.dev">Git</a></li>
|
<option value="city-destroyed">Apocalypse</option>
|
||||||
</ul>
|
</select>
|
||||||
</nav>
|
</li>
|
||||||
</header>
|
<li><a href="/tools">Tools</a></li>
|
||||||
<section id="content" class="content">
|
<li><a href="/contact">Contact</a></li>
|
||||||
<slot name="content" />
|
<li><a href="https://git.badblocks.dev" target="_blank">Git</a></li>
|
||||||
</section>
|
</ul>
|
||||||
<footer>
|
</nav>
|
||||||
<p>
|
</header>
|
||||||
© <script is:inline>
|
<main id="content">
|
||||||
document.write(new Date().getFullYear());
|
<slot name="content" />
|
||||||
</script>
|
</main>
|
||||||
badblocks
|
<footer>
|
||||||
</p>
|
<p>
|
||||||
</footer>
|
© <script is:inline>
|
||||||
</div>
|
document.write(new Date().getFullYear());
|
||||||
|
</script>
|
||||||
|
badblocks
|
||||||
|
</p>
|
||||||
|
<p>Made from scratch with BAHA: Bun, Astro, Htmx, and Alpine!</p>
|
||||||
|
</footer>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
||||||
|
|
@ -1,24 +1,52 @@
|
||||||
---
|
---
|
||||||
import Layout from "../layouts/BaseLayout.astro";
|
import Layout from "../layouts/BaseLayout.astro";
|
||||||
|
export const prerender = false;
|
||||||
---
|
---
|
||||||
|
|
||||||
<Layout>
|
<Layout>
|
||||||
<title slot="head">Contact</title>
|
<title slot="head">Contact</title>
|
||||||
<style>
|
<style>
|
||||||
.contact {
|
form {
|
||||||
grid-area: contact;
|
|
||||||
display: grid;
|
display: grid;
|
||||||
place-items: center;
|
gap: 1rem;
|
||||||
padding: 4rem 2rem;
|
width: 100%;
|
||||||
background: #f8f9fa;
|
margin: 0 auto;
|
||||||
|
grid-template-areas:
|
||||||
|
"header header "
|
||||||
|
"name phone"
|
||||||
|
"msg msg"
|
||||||
|
" . submit";
|
||||||
|
}
|
||||||
|
label[for="name"] {
|
||||||
|
grid-area: name;
|
||||||
|
}
|
||||||
|
label[for="phone"] {
|
||||||
|
grid-area: phone;
|
||||||
|
}
|
||||||
|
label[for="msg"] {
|
||||||
|
grid-area: msg;
|
||||||
|
}
|
||||||
|
button#submit {
|
||||||
|
grid-area: submit;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
<Fragment slot="content">
|
<Fragment slot="content">
|
||||||
<section class="contact" id="contact">
|
<h2>Contact</h2>
|
||||||
<div>
|
<p>Use the below form to shoot me a quick text!</p>
|
||||||
<h2>Contact</h2>
|
<form x-data="{}">
|
||||||
<p>Contact information here</p>
|
<label for="name">
|
||||||
</div>
|
Name
|
||||||
</section>
|
<input type="text" id="name" placeholder="John Doe" />
|
||||||
|
</label>
|
||||||
|
<label for="phone">
|
||||||
|
Phone
|
||||||
|
<input type="text" id="phone" placeholder="555-555-5555" />
|
||||||
|
</label>
|
||||||
|
<label for="msg">
|
||||||
|
Msg
|
||||||
|
<textarea id="msg" placeholder="I think badblocks rocks!"></textarea>
|
||||||
|
</label>
|
||||||
|
<button id="submit" type="submit">Submit</button>
|
||||||
|
</form>
|
||||||
</Fragment>
|
</Fragment>
|
||||||
</Layout>
|
</Layout>
|
||||||
|
|
|
||||||
|
|
@ -6,11 +6,63 @@ import Layout from "../layouts/BaseLayout.astro";
|
||||||
<title slot="head">Home</title>
|
<title slot="head">Home</title>
|
||||||
<style>
|
<style>
|
||||||
:root {
|
:root {
|
||||||
--scroll-speed: 10s;
|
--scroll-multiplier: 5;
|
||||||
|
--theme: winternight;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.parallax-theme-winternight {
|
||||||
|
--layer-0-speed: 6250s;
|
||||||
|
--layer-1-speed: 1250s;
|
||||||
|
--layer-2-speed: 500s;
|
||||||
|
--layer-3-speed: 250s;
|
||||||
|
--layer-4-speed: 80s;
|
||||||
|
--layer-0-url: url("/parallax/winternight/0-sky.png");
|
||||||
|
--layer-1-url: url("/parallax/winternight/1-backmountain.png");
|
||||||
|
--layer-2-url: url("/parallax/winternight/2-midmountain.png");
|
||||||
|
--layer-3-url: url("/parallax/winternight/3-midforest.png");
|
||||||
|
--layer-4-url: url("/parallax/winternight/4-frontfloor.png");
|
||||||
|
--parallax-width: calc(3800px * 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
.parallax-theme-sunnyvale-forest {
|
||||||
|
--layer-0-speed: 2000s;
|
||||||
|
--layer-1-speed: 400s;
|
||||||
|
--layer-2-speed: 50s;
|
||||||
|
--layer-0-url: url("/parallax/sunnyvale-forest/0-clouds.png");
|
||||||
|
--layer-1-url: url("/parallax/sunnyvale-forest/1-mountains.png");
|
||||||
|
--layer-2-url: url("/parallax/sunnyvale-forest/2-trees.png");
|
||||||
|
--parallax-width: calc(160px * 200);
|
||||||
|
}
|
||||||
|
|
||||||
|
.parallax-theme-city-destroyed {
|
||||||
|
--layer-0-speed: 1000s;
|
||||||
|
--layer-1-speed: 275s;
|
||||||
|
--layer-2-speed: 250s;
|
||||||
|
--layer-3-speed: 250s;
|
||||||
|
--layer-4-speed: 250s;
|
||||||
|
--layer-5-speed: 100s;
|
||||||
|
--layer-0-url: url("/parallax/city-destroyed/0-sky.png");
|
||||||
|
--layer-1-url: url("/parallax/city-destroyed/1-buildingssmoke.png");
|
||||||
|
--layer-2-url: url("/parallax/city-destroyed/2-water.png");
|
||||||
|
--layer-3-url: url("/parallax/city-destroyed/3-buildings.png");
|
||||||
|
--layer-4-url: url("/parallax/city-destroyed/4-buildingreflection.png");
|
||||||
|
--layer-5-url: url("/parallax/city-destroyed/5-frontsmoke.png");
|
||||||
|
--parallax-width: calc(3800px * 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
.parallax-theme-city-destroyed .layer.layer-1,
|
||||||
|
.parallax-theme-city-destroyed .layer.layer-3,
|
||||||
|
.parallax-theme-city-destroyed .layer.layer-4 {
|
||||||
|
background-repeat: repeat-x;
|
||||||
|
}
|
||||||
|
|
||||||
|
.parallax-theme-city-destroyed .layer.layer-4 {
|
||||||
|
background-position-y: 16rem;
|
||||||
|
}
|
||||||
|
|
||||||
.parallax-container {
|
.parallax-container {
|
||||||
position: relative;
|
position: relative;
|
||||||
height: 208px;
|
height: 30rem;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
z-index: 0;
|
z-index: 0;
|
||||||
|
|
@ -21,28 +73,52 @@ import Layout from "../layouts/BaseLayout.astro";
|
||||||
top: 0;
|
top: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
width: 1600vw; /* bg images are 160px, so use 16*vw for smooth scrolling */
|
width: var(--parallax-width);
|
||||||
background-repeat: round;
|
background-repeat: round;
|
||||||
background-position: bottom;
|
background-position: bottom;
|
||||||
background-size: contain;
|
background-size: contain;
|
||||||
}
|
}
|
||||||
|
|
||||||
.layer-back {
|
.layer-0 {
|
||||||
background-image: url("/bg-clouds.png");
|
background-image: var(--layer-0-url);
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
animation: scroll calc(var(--scroll-speed) * 42) linear infinite;
|
animation: scroll calc(var(--scroll-multiplier) * var(--layer-0-speed))
|
||||||
|
linear infinite;
|
||||||
}
|
}
|
||||||
|
|
||||||
.layer-middle {
|
.layer-1 {
|
||||||
background-image: url("/bg-mountains.png");
|
background-image: var(--layer-1-url);
|
||||||
z-index: 2;
|
z-index: 2;
|
||||||
animation: scroll calc(var(--scroll-speed) * 32) linear infinite;
|
animation: scroll calc(var(--scroll-multiplier) * var(--layer-1-speed))
|
||||||
|
linear infinite;
|
||||||
}
|
}
|
||||||
|
|
||||||
.layer-front {
|
.layer-2 {
|
||||||
background-image: url("/bg-trees.png");
|
background-image: var(--layer-2-url);
|
||||||
z-index: 3;
|
z-index: 3;
|
||||||
animation: scroll calc(var(--scroll-speed) * 11) linear infinite;
|
animation: scroll calc(var(--scroll-multiplier) * var(--layer-2-speed))
|
||||||
|
linear infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
.layer-3 {
|
||||||
|
background-image: var(--layer-3-url);
|
||||||
|
z-index: 4;
|
||||||
|
animation: scroll calc(var(--scroll-multiplier) * var(--layer-3-speed))
|
||||||
|
linear infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
.layer-4 {
|
||||||
|
background-image: var(--layer-4-url);
|
||||||
|
z-index: 5;
|
||||||
|
animation: scroll calc(var(--scroll-multiplier) * var(--layer-4-speed))
|
||||||
|
linear infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
.layer-5 {
|
||||||
|
background-image: var(--layer-5-url);
|
||||||
|
z-index: 6;
|
||||||
|
animation: scroll calc(var(--scroll-multiplier) * var(--layer-5-speed))
|
||||||
|
linear infinite;
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes scroll {
|
@keyframes scroll {
|
||||||
|
|
@ -53,42 +129,22 @@ import Layout from "../layouts/BaseLayout.astro";
|
||||||
transform: translateX(-50%);
|
transform: translateX(-50%);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
section#hero {
|
|
||||||
position: relative;
|
|
||||||
padding: 2rem;
|
|
||||||
background-color: #f8f9fa;
|
|
||||||
z-index: -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.hero {
|
|
||||||
position: relative;
|
|
||||||
top: calc(-4 * 0.9rem);
|
|
||||||
left: 12px;
|
|
||||||
width: calc(100% - 24px);
|
|
||||||
}
|
|
||||||
div.hero > h1 {
|
|
||||||
color: #fff;
|
|
||||||
margin-bottom: 16px;
|
|
||||||
}
|
|
||||||
div.hero > p {
|
|
||||||
font-size: 16px;
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
<Fragment slot="content">
|
<Fragment slot="content">
|
||||||
<section id="hero">
|
<article id="hero">
|
||||||
<div class="parallax-container">
|
<div class="parallax-container" :class="'parallax-theme-' + theme">
|
||||||
<div class="layer layer-back"></div>
|
<div class="layer layer-0"></div>
|
||||||
<div class="layer layer-middle"></div>
|
<div class="layer layer-1"></div>
|
||||||
<div class="layer layer-front"></div>
|
<div class="layer layer-2"></div>
|
||||||
|
<div class="layer layer-3"></div>
|
||||||
|
<div class="layer layer-4"></div>
|
||||||
|
<div class="layer layer-5"></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="hero">
|
<h2>Lorem Ipsum</h2>
|
||||||
<h1>Lorem Ipsum</h1>
|
<p>
|
||||||
<p>
|
Neque porro quisquam est qui dolorem ipsum quia dolor sit amet,
|
||||||
Neque porro quisquam est qui dolorem ipsum quia dolor sit amet,
|
consectetur, adipisci velit.
|
||||||
consectetur, adipisci velit.
|
</p>
|
||||||
</p>
|
</article>
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
</Fragment>
|
</Fragment>
|
||||||
</Layout>
|
</Layout>
|
||||||
|
|
|
||||||
|
|
@ -1,33 +0,0 @@
|
||||||
---
|
|
||||||
import Layout from "../layouts/BaseLayout.astro";
|
|
||||||
---
|
|
||||||
|
|
||||||
<Layout>
|
|
||||||
<title slot="head">Projects</title>
|
|
||||||
<style>
|
|
||||||
.projects-grid {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: repeat(auto-fit, minmax(min(100%, 150px), 1fr));
|
|
||||||
gap: 2rem;
|
|
||||||
max-width: 1200px;
|
|
||||||
margin: 2rem auto 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.project-card {
|
|
||||||
background: #f8f9fa;
|
|
||||||
padding: 2rem;
|
|
||||||
border-radius: 8px;
|
|
||||||
min-height: 250px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
<Fragment slot="content">
|
|
||||||
<section class="projects" id="projects">
|
|
||||||
<h2>Projects</h2>
|
|
||||||
<div class="projects-grid">
|
|
||||||
<div class="project-card">Project 1</div>
|
|
||||||
<div class="project-card">Project 2</div>
|
|
||||||
<div class="project-card">Project 3</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
</Fragment>
|
|
||||||
</Layout>
|
|
||||||
78
src/pages/robots.txt.ts
Normal file
|
|
@ -0,0 +1,78 @@
|
||||||
|
import type { APIRoute } from "astro";
|
||||||
|
|
||||||
|
const getRobotsTxt = (sitemapURL: URL) => `\
|
||||||
|
# Block all known AI crawlers and assistants
|
||||||
|
# from using content for training AI models.
|
||||||
|
# Source: https://robotstxt.com/ai
|
||||||
|
User-Agent: GPTBot
|
||||||
|
User-Agent: ClaudeBot
|
||||||
|
User-Agent: Claude-User
|
||||||
|
User-Agent: Claude-SearchBot
|
||||||
|
User-Agent: CCBot
|
||||||
|
User-Agent: Google-Extended
|
||||||
|
User-Agent: Applebot-Extended
|
||||||
|
User-Agent: Facebookbot
|
||||||
|
User-Agent: Meta-ExternalAgent
|
||||||
|
User-Agent: Meta-ExternalFetcher
|
||||||
|
User-Agent: diffbot
|
||||||
|
User-Agent: PerplexityBot
|
||||||
|
User-Agent: Perplexity‑User
|
||||||
|
User-Agent: Omgili
|
||||||
|
User-Agent: Omgilibot
|
||||||
|
User-Agent: webzio-extended
|
||||||
|
User-Agent: ImagesiftBot
|
||||||
|
User-Agent: Bytespider
|
||||||
|
User-Agent: TikTokSpider
|
||||||
|
User-Agent: Amazonbot
|
||||||
|
User-Agent: Youbot
|
||||||
|
User-Agent: SemrushBot-OCOB
|
||||||
|
User-Agent: Petalbot
|
||||||
|
User-Agent: VelenPublicWebCrawler
|
||||||
|
User-Agent: TurnitinBot
|
||||||
|
User-Agent: Timpibot
|
||||||
|
User-Agent: OAI-SearchBot
|
||||||
|
User-Agent: ICC-Crawler
|
||||||
|
User-Agent: AI2Bot
|
||||||
|
User-Agent: AI2Bot-Dolma
|
||||||
|
User-Agent: DataForSeoBot
|
||||||
|
User-Agent: AwarioBot
|
||||||
|
User-Agent: AwarioSmartBot
|
||||||
|
User-Agent: AwarioRssBot
|
||||||
|
User-Agent: Google-CloudVertexBot
|
||||||
|
User-Agent: PanguBot
|
||||||
|
User-Agent: Kangaroo Bot
|
||||||
|
User-Agent: Sentibot
|
||||||
|
User-Agent: img2dataset
|
||||||
|
User-Agent: Meltwater
|
||||||
|
User-Agent: Seekr
|
||||||
|
User-Agent: peer39_crawler
|
||||||
|
User-Agent: cohere-ai
|
||||||
|
User-Agent: cohere-training-data-crawler
|
||||||
|
User-Agent: DuckAssistBot
|
||||||
|
User-Agent: Scrapy
|
||||||
|
User-Agent: Cotoyogi
|
||||||
|
User-Agent: aiHitBot
|
||||||
|
User-Agent: Factset_spyderbot
|
||||||
|
User-Agent: FirecrawlAgent
|
||||||
|
|
||||||
|
Disallow: /
|
||||||
|
DisallowAITraining: /
|
||||||
|
|
||||||
|
# Block any non-specified AI crawlers (e.g., new
|
||||||
|
# or unknown bots) from using content for training
|
||||||
|
# AI models, while allowing the website to be
|
||||||
|
# indexed and accessed by bots. These directives
|
||||||
|
# are still experimental and may not be supported
|
||||||
|
# by all AI crawlers.
|
||||||
|
User-Agent: *
|
||||||
|
DisallowAITraining: /
|
||||||
|
Content-Usage: ai=n
|
||||||
|
Allow: /
|
||||||
|
|
||||||
|
Sitemap: ${sitemapURL.href}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const GET: APIRoute = ({ site }) => {
|
||||||
|
const sitemapURL = new URL("sitemap-index.xml", site);
|
||||||
|
return new Response(getRobotsTxt(sitemapURL));
|
||||||
|
};
|
||||||
26
src/pages/tools.astro
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
---
|
||||||
|
import Layout from "../layouts/BaseLayout.astro";
|
||||||
|
---
|
||||||
|
|
||||||
|
<Layout>
|
||||||
|
<title slot="head">Tools</title>
|
||||||
|
<style>
|
||||||
|
.tools-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fit, minmax(min(100%, 150px), 1fr));
|
||||||
|
gap: 2rem;
|
||||||
|
max-width: 1200px;
|
||||||
|
margin: 2rem auto 0;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<Fragment slot="content">
|
||||||
|
<section class="tools" id="tools">
|
||||||
|
<h2>Tools</h2>
|
||||||
|
<div class="tools-grid">
|
||||||
|
<div class="tool-card">Tool 1</div>
|
||||||
|
<div class="tool-card">Tool 2</div>
|
||||||
|
<div class="tool-card">Tool 3</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</Fragment>
|
||||||
|
</Layout>
|
||||||