First Commit

This commit is contained in:
2025-10-27 05:00:02 +09:00
commit 5d3fb2a5d0
37 changed files with 4118 additions and 0 deletions
+43
View File
@@ -0,0 +1,43 @@
---
export interface Props {
title: string;
description: string;
img: string;
href?: URL;
isFullWidth?: true;
}
---
<a class={`
flex
flex-grow
items-center
${Astro.props.isFullWidth
? "w-full"
: "w-fit"}
p-3
rounded
shadow-sm
mb-3
bg-white
text-black
`} href={Astro.props.href} target="_blank">
<img
src={new URL(`/icons/${Astro.props.img}`, Astro.url.origin).toString()}
alt="アイコン"
class={`
w-10
h-10
rounded
mr-5
object-contain
border
border-neutral-200
shadow-xs
`}
/>
<div class="flex flex-col">
<span class="text-lg">{Astro.props.title}</span>
<span class="text-xs">{Astro.props.description}</span>
</div>
</a>
+24
View File
@@ -0,0 +1,24 @@
---
function getYears(start: number) {
const currentYear = new Date().getFullYear();
if (currentYear > start) {
return `${start}-${currentYear}`;
} else {
return String(start);
}
}
---
<footer class={`
p-[2em]
bg-gray-200
text-slate-500
text-center
text-[16px]
font-[BIZ_UDPGothic]
`}>
&copy; {getYears(2025)} Last2014. All rights reserved.
</footer>
<style>
@import url("https://fonts.googleapis.com/css2?family=BIZ+UDPGothic&display=swap");
</style>
+41
View File
@@ -0,0 +1,41 @@
---
import Link from "@/components/header/Link.astro";
---
<header class={`
backdrop-blur-sm
bg-white/80
m-auto
mx-5
mb-8
top-[1rem]
rounded-[1em]
h-[5rem]
sticky
p-[1em]
flex
items-center
justify-center
shadow-sm
`}>
<a class={`
flex
items-center
font-[Atkinson_Hyperlegible]
font-lg
`} href="/">
<img
src={new URL("/last2014.png", Astro.url.origin).toString()}
alt="アバター"
class={`
w-10
mr-2
!rounded-[100%]
`}
/>
Last2014
</a>
</header>
<style>
@import url("https://fonts.googleapis.com/css2?family=Atkinson+Hyperlegible:wght@400;700&display=swap");
</style>
+27
View File
@@ -0,0 +1,27 @@
---
import type { HTMLAttributes } from "astro/types";
type Props = HTMLAttributes<"a">;
const { href, class: className, ...props } = Astro.props;
const pathname = Astro.url.pathname.replace(/\/$/, "");
const isActive = href === "/"
? pathname === ""
: pathname === href
---
<a
class={`
${isActive && `
font-bold
underline
decoration-blue-500
decoration-3
underline-offset-5
`}
`}
href={href}
{...props}
>
<slot />
</a>
+28
View File
@@ -0,0 +1,28 @@
import { type Props as CardProps } from "@/components/Card.astro";
export default [
{
title: "お問い合わせフォーム",
description: "メールアドレスが必要です",
img: "contact.svg",
href: new URL("https://last2014.com/contact"),
},
{
title: "メール(last2014.com)",
description: "info@last2014.com",
img: "mail.svg",
href: new URL("mailto:info@last2014.com"),
},
{
title: "メール(yahoo.co.jp)",
description: "last2014yh@yahoo.co.jp",
img: "mail.svg",
href: new URL("mailto:last2014yh@yahoo.co.jp"),
},
{
title: "Activity Pub",
description: "@last2014@misskey.systems",
img: "mistems.png",
href: new URL("https://misskey.systems/@last2014"),
},
] as CardProps[];
+29
View File
@@ -0,0 +1,29 @@
import { type Props as CardProps } from "@/components/Card.astro";
export default [
{
title: "活動開始日",
description: "2025/5/31",
img: "calendar.svg",
},
{
title: "誕生日",
description: "2014/12/8",
img: "cake.svg",
},
{
title: "場所",
description: "神奈川県",
img: "location.svg",
},
{
title: "性別",
description: "男性",
img: "gender.svg",
},
{
title: "出身",
description: "神奈川県川崎市",
img: "world.svg",
},
] as CardProps[];
+58
View File
@@ -0,0 +1,58 @@
import { type Props as CardProps } from "@/components/Card.astro";
export default [
{
title: "Last2014's Blog",
description: "@last2014@last2014.com",
img: "rss.svg",
href: new URL("https://last2014.com"),
},
{
title: "WakaTime",
description: "@last2014@wakatime.com",
img: "wakatime.png",
href: new URL("https://wakatime.com/@last2014"),
},
{
title: "Gitea",
description: "@last2014@gitea.last2014.com",
img: "gitea.svg",
href: new URL("https://gitea.last2014.com/last2014"),
},
{
title: "みすてむず いず みすきーしすてむず",
description: "@last2014@misskey.systems",
img: "mistems.png",
href: new URL("https://misskey.systems/@last2014"),
},
{
title: "ゆずねっと",
description: "@last2014@uwuzu.net",
img: "uwuzunet.png",
href: new URL("https://uwuzu.net/@last2014"),
},
{
title: "Zenn",
description: "@last2014@zenn.dev",
img: "zenn.svg",
href: new URL("https://zenn.dev/last2014"),
},
{
title: "Qiita",
description: "@last2014@qiita.com",
img: "qiita.png",
href: new URL("https://qiita.com/last2014"),
},
{
title: "ニコニコ動画",
description: "@140339612@nicovideo.jp",
img: "nicovideo.png",
href: new URL("https://nicovideo.jp/user/140339612"),
},
{
title: "Yahoo! 知恵袋",
description: "@1154047737@chiebukuro.yahoo.co.jp",
img: "yahoo.png",
href: new URL("https://chiebukuro.yahoo.co.jp/user/1154047737"),
},
] as CardProps[];
+74
View File
@@ -0,0 +1,74 @@
---
import Header from "@/components/header/Header.astro";
import Footer from "@/components/Footer.astro";
import "@/styles/global.css";
import "@/styles/tailwind.css";
interface Props {
title?: string;
description?: string;
}
const title = Astro.props.title
? Astro.props.title + " - Last2014"
: "Last2014";
---
<!DOCTYPE HTML>
<html lang="ja" prefix="og: https://ogp.me/ns#">
<head>
<!-- Global -->
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="generator" content={Astro.generator} />
<link rel="icon" href="/favicon.ico" />
<meta name="color-scheme" content="light dark" />
{Astro.site && (
<link rel="canonical" href={Astro.site.href} />
)}
<!-- Primary -->
{Astro.props.description && (
<meta name="description" content={Astro.props.description} />
)}
<title>{title}</title>
<meta name="title" content={title}>
<!-- Open Graph -->
<meta property="og:type" content="website" />
<meta property="og:url" content={Astro.url.href} />
<meta property="og:site_name" content="Last2014" />
<meta property="og:title" content={Astro.props.title ?? "Last2014"} />
{Astro.props.description && (
<meta property="og:description" content={Astro.props.description}>
)}
<meta property="og:locale" content="ja_JP" />
<meta property="og:image" content={new URL("/last2014.png", Astro.url)} />
<!-- Twitter Card -->
<meta name="twitter:card" content="summary">
<meta name="twitter:url" content={Astro.url.href}>
<meta name="twitter:domain" content={Astro.url.hostname} />
<meta name="twitter:title" content={title}>
{Astro.props.description && (
<meta name="twitter:description" content={Astro.props.description}>
)}
<meta name="twitter:image" content={new URL("/last2014.png", Astro.url)}>
<!-- Astro -->
</head>
<body class={`
bg-neutral-100
text-black
min-h-screen
flex
flex-col
`}>
<Header />
<main class={`
flex
flex-grow
flex-col
items-center
`}>
<slot />
</main>
<Footer />
</body>
</html>
+24
View File
@@ -0,0 +1,24 @@
---
import Layout from "@/layouts/Layout.astro";
const legacyLink = new URL(Astro.url.pathname, "https://last2014.com").toString();
---
<Layout>
<span class="text-4xl font-bold">Not Found</span>
<p><code>{Astro.url.pathname}</code>が見つかりませんでした。</p>
<span class="mt-3 text-2xl">もしかして...</span>
<p>
<a
href="https://legacy.last2014.com"
class="underline text-blue-500"
>従来のサイト</a>のページをお探しですか?
</p>
<a
class="underline text-blue-500"
href={legacyLink}
>
<code>{legacyLink}</code>に移動できます
</a>
</Layout>
+96
View File
@@ -0,0 +1,96 @@
---
import Layout from "@/layouts/Layout.astro";
import Card from "@/components/Card.astro";
import details from "@/constants/details";
import links from "@/constants/links";
import contacts from "@/constants/contacts";
---
<Layout>
<div class={`
flex
justify-between
bg-white
shadow-sm
w-fit
rounded
p-5
`}>
<img
src={new URL("/last2014.png", Astro.url.origin).toString()}
alt="アバター"
class={`
w-15
h-15
mr-2
!rounded-[100%]
`}
/>
<div class="flex flex-grow flex-col">
<span class="text-xl font-bold">Last2014</span>
<p class="text-sm">
ウェブ開発一生やってる小学生です。<br />
TypeScriptをメインに色々作っています。
</p>
</div>
</div>
<div class={`
flex
flex-col
gap-3
w-full
p-5
`}>
<span class="font-bold text-4xl w-full mb-3">詳細</span>
{details.map((detail) => (
<Card
title={detail.title}
description={detail.description}
img={detail.img}
href={detail.href}
isFullWidth
/>
))}
</div>
<div class={`
flex
flex-wrap
gap-3
w-fit
p-5
`}>
<span class="font-bold text-4xl w-full mb-3">リンク</span>
{links.map((link) => (
<Card
title={link.title}
description={link.description}
img={link.img}
href={link.href}
/>
))}
</div>
<div class={`
flex
flex-col
gap-3
w-full
p-5
`}>
<span class="font-bold text-4xl w-full mb-3">連絡先</span>
{contacts.map((contact) => (
<Card
title={contact.title}
description={contact.description}
img={contact.img}
href={contact.href}
isFullWidth
/>
))}
</div>
</Layout>
+90
View File
@@ -0,0 +1,90 @@
@import url("https://fonts.googleapis.com/css2?family=Noto+Sans+JP:wght@400;700&display=swap");
@layer base {
*, ::after, ::before, ::backdrop, ::file-selector-button {
font-family: "Noto Sans JP";
font-weight: 400;
box-sizing: border-box;
margin: 0;
padding: 0;
border: 0 solid;
line-height: 1.7;
font-size: 18px;
word-wrap: break-word;
overflow-wrap: break-word;
}
a {
color: var(--color-blue-600);
}
}
html {
scroll-padding-top: 6rem;
overscroll-behavior: none;
}
h1, h2, h3, h4, h5, h6 {
line-height: 1.2;
margin-top: 1rem;
}
h1 {
font-size: 3.052em;
}
h2 {
font-size: 2.441em;
}
h3 {
font-size: 1.953em;
}
h4 {
font-size: 1.563em;
}
h5 {
font-size: 1.25em;
}
code {
padding: 2px 5px;
background-color: var(--color-gray-300);
color: var(--color-black);
border-radius: 2px;
}
pre {
padding: 1.5em;
border-radius: 8px;
}
pre > code {
all: unset;
}
strong, b {
font-weight: 700;
}
textarea {
width: 100%;
font-size: 16px;
}
input {
font-size: 16px;
}
table {
width: 100%;
}
blockquote {
border-left: 4px solid var(--color-blue-600);
padding: 0 0 0 20px;
margin: 0px;
font-size: 1.333em;
}
+1
View File
@@ -0,0 +1 @@
@import "tailwindcss";