5 Commits

Author SHA1 Message Date
25a38d2f0e 🔖 Replaced heroimage with an image of me, fix typo
All checks were successful
Build and deploy website / build (push) Successful in 32s
2025-02-16 13:50:27 +01:00
e1c3ae7d87 Latest projects on landing page, moved landing page components
All checks were successful
Build and deploy website / build (push) Successful in 34s
2025-02-16 12:01:51 +01:00
22cdc634f9 More Catppuccin colours, colour links by default 2025-02-16 11:49:06 +01:00
1b3c6c629e More mobile friendly, fix wrong URL, Hamburger menu
All checks were successful
Build and deploy website / build (push) Successful in 33s
- Hamburger menu on mobile
- title is moved into header on mobile
- Smaller titles on mobile
- Fix wrong import of env in config
- Cleaned up unused imports
2025-02-15 23:00:38 +01:00
ff2f65bf59 🚑 Fix build error
All checks were successful
Build and deploy website / build (push) Successful in 32s
Signed-off-by: Martin Berg Alstad <git@martials.no>
2025-02-15 19:31:44 +01:00
31 changed files with 221 additions and 102 deletions

23
TODO.md
View File

@ -1,21 +1,31 @@
# TODO # TODO
## Code ## Code
- [ ] Temporal API or day.js for dates - [ ] day.js for dates
- [ ] Nix Shell
## SSE
- [x] Correct Sitemap.xml
- [x] Correct robots.txt
- [x] Correct security.txt
## Layout ## Layout
- [ ] Show current page in navbar - [x] Show current page
- [x] Correct bg colour on entire page - [x] Correct bg colour on entire page
- [x] Hamburger menu on mobile
- [ ] Dark mode toggle
- [ ] Navigate using pathname / breadcrumbs
## Accessibility ## Accessibility
- [ ] Fix colours on buttons - [x] Fix colours on buttons
- [ ] Correct contrast - [x] Correct contrast
- [ ] All interactable elements have labels - [ ] All interactable elements have labels
- [ ] Colour links, also in MDX posts - [x] Colour links, also in MDX posts
## ~/ ## ~/
- [ ] About me description - [ ] About me description
- [ ] Non-cat image - [x] Latest projects
- [x] Non-cat image
## ~/about ## ~/about
- [ ] About me - [ ] About me
@ -23,6 +33,7 @@
## ~/links ## ~/links
- [ ] Add Bluesky link - [ ] Add Bluesky link
- [ ] Add MusicBrainz link - [ ] Add MusicBrainz link
- [ ] Add Archidekt link
## ~/slashes ## ~/slashes
- [ ] List of all slashes - [ ] List of all slashes

View File

@ -10,13 +10,13 @@ import icon from "astro-icon"
import { loadEnv } from "vite" import { loadEnv } from "vite"
const { url } = process.env.URL const { URL } = process.env.NODE_ENV
? loadEnv(process.env.URL, process.cwd(), "") ? loadEnv(process.env.NODE_ENV, process.cwd(), "")
: { url: "http://localhost:3000" } : { URL: "http://localhost:3000" }
// https://astro.build/config // https://astro.build/config
export default defineConfig({ export default defineConfig({
site: url, site: URL,
output: "server", output: "server",
i18n: { i18n: {
defaultLocale: "nb", defaultLocale: "nb",

View File

@ -2,7 +2,7 @@
"$schema": "https://inlang.com/schema/inlang-message-format", "$schema": "https://inlang.com/schema/inlang-message-format",
"hiIm": "Hei, jeg er", "hiIm": "Hei, jeg er",
"position": "Programvareutvikler", "position": "Programvareutvikler",
"aboutMe": "Engasjert utvikler som for tiden jobber hos Capgemini Bergen", "aboutMe": "Engasjert utvikler som for tiden jobber hos Capgemini Bergen.",
"home": "Hjem", "home": "Hjem",
"contactMe": "Kontakt meg", "contactMe": "Kontakt meg",
"myLinks": "Mine lenker", "myLinks": "Mine lenker",

View File

@ -1,7 +1,7 @@
{ {
"name": "martials-no-v2", "name": "martials-no-v2",
"type": "module", "type": "module",
"version": "0.0.1", "version": "1.0.0",
"scripts": { "scripts": {
"dev": "astro dev", "dev": "astro dev",
"start": "astro dev", "start": "astro dev",

View File

@ -4,20 +4,28 @@ import * as m from "@/paraglide/messages.js"
// TODO self-host email server // TODO self-host email server
--- ---
<form <div class="max-w-[500px] mx-auto">
class="flex flex-col gap-2 max-w-[500px] mx-auto" <form
method="post" class="flex flex-col gap-2 w-full"
action="https://formspree.io/f/mknykgbn" method="post"
> action="https://formspree.io/f/mknykgbn"
<Input label={m.name()} type="text" name="name" required /> >
<Input label={m.subject()} name="subject" required /> <Input label={m.name()} type="text" name="name" required />
<Input label={m.email()} name="_replyto" /> <Input label={m.subject()} name="subject" required />
{/*Honeypot spam filter*/} <Input label={m.email()} name="_replyto" />
<input name="_gotcha" type="text" class={"hidden"} /> {/*Honeypot spam filter*/}
<label class="flex flex-col"> <input name="_gotcha" type="text" class={"hidden"} />
{m.message()} <label class="flex flex-col">
<textarea name="message" class="textarea textarea-bordered w-full" required {m.message()}
></textarea> <textarea
</label> name="message"
</form> class="textarea textarea-bordered w-full bg-cat-base"
<button type="submit" class="btn mt-2" title={m.send()}>{m.send()}</button> required></textarea>
</label>
</form>
<button
type="submit"
class="btn mt-2 bg-cat-base border-cat-surface0"
title={m.send()}>{m.send()}</button
>
</div>

View File

@ -11,11 +11,15 @@ const giteaLink = `${GIT_URL}/martials/martials.no`
<div class="divider bg-inherit"></div> <div class="divider bg-inherit"></div>
<div <div
class="py-5 flex flex-row gap-1 justify-around w-full items-center bg-inherit" class="max-w-[1000px] sm:min-w-[500px] mx-auto py-5 flex flex-row flex-wrap gap-5 justify-around items-center bg-inherit px-5"
> >
<div> <div>
<GiteaLink href={giteaLink} /> <GiteaLink href={giteaLink} class="!text-cat-text" />
<ExternalLink href={STATUS_URL} class="flex items-center" title="Status"> <ExternalLink
href={STATUS_URL}
class="flex items-center !text-cat-text"
title="Status"
>
<PajamasIcon <PajamasIcon
name="pajamas:status-health" name="pajamas:status-health"
class="w-6 h-6 mr-2" class="w-6 h-6 mr-2"

View File

@ -16,10 +16,10 @@ const {
} = Astro.props } = Astro.props
--- ---
<label class="flex flex-col"> <label class="flex flex-col w-full">
{label} {label}
<input <input
class="input input-bordered w-full" class="input input-bordered w-full bg-cat-base"
type={type} type={type}
name={name} name={name}
required={required} required={required}

View File

@ -2,14 +2,26 @@
import LocaleLink from "./links/LocaleLink.astro" import LocaleLink from "./links/LocaleLink.astro"
import { type NavLink, resolvePathname } from "@/utils/linking" import { type NavLink, resolvePathname } from "@/utils/linking"
const currentPath = resolvePathname(Astro.url.pathname) const pathname = Astro.url.pathname
const currentPath = resolvePathname(pathname)
const isEnglish = pathname.startsWith("/en")
--- ---
<div class="join"> <div class="join">
<LocaleLink to={currentPath as NavLink} lang="nb" class="btn join-item" <LocaleLink
>Norsk</LocaleLink to={currentPath as NavLink}
lang="nb"
class:list={[
"btn join-item !text-cat-text border-cat-surface0",
!isEnglish ? "bg-cat-mantle" : "bg-cat-base",
]}>Norsk</LocaleLink
> >
<LocaleLink to={currentPath as NavLink} lang="en" class="btn join-item" <LocaleLink
>English</LocaleLink to={currentPath as NavLink}
lang="en"
class:list={[
"btn join-item !text-cat-text border-cat-surface0",
isEnglish ? "bg-cat-mantle" : "bg-cat-base",
]}>English</LocaleLink
> >
</div> </div>

View File

@ -1,5 +1,4 @@
--- ---
import Select from "./Select.svelte"
import * as m from "@/paraglide/messages" import * as m from "@/paraglide/messages"
import CollapseList from "@/components/collapse/CollapseList.svelte" import CollapseList from "@/components/collapse/CollapseList.svelte"
import type { CollectionEntry } from "astro:content" import type { CollectionEntry } from "astro:content"

View File

@ -7,6 +7,6 @@ interface Props {
const { tags } = Astro.props const { tags } = Astro.props
--- ---
<div class="flex flex-wrap gap-1"> <div class="flex flex-wrap gap-1 py-0.5">
{tags.map((tag) => <Badge tag={tag} />)} {tags.map((tag) => <Badge tag={tag} />)}
</div> </div>

View File

@ -0,0 +1,17 @@
---
import PajamasIcon from "@/components/icons/PajamasIcon.astro"
interface Props {
id: string
}
const { id } = Astro.props
---
<label for={id} aria-label="open sidebar" class="btn btn-square btn-ghost">
<PajamasIcon
name="pajamas:hamburger"
class="w-6 h-6"
aria-label="Hamburger menu"
/>
</label>

View File

@ -1,7 +1,38 @@
--- ---
import Navbar from "./Navbar.astro" import Navbar from "./Navbar.astro"
import NavbarDrawer from "./NavbarDrawer.astro"
import HamburgerMenuButton from "./HamburgerMenuButton.astro"
import { resolvePathname } from "@/utils/linking"
const currentPath = `~${resolvePathname(Astro.originPathname)}`
--- ---
<div class="m-auto"> <div class="sm:m-auto">
<Navbar /> <div class="drawer drawer-end">
<input id="my-drawer-3" type="checkbox" class="drawer-toggle" />
<div class="drawer-content flex flex-col">
<!-- Navbar -->
<div class="navbar w-full justify-end">
<div class="flex justify-between items-center w-full h-full sm:hidden">
<h1 class="!text-2xl h-5">
{currentPath}
</h1>
<HamburgerMenuButton id="my-drawer-3" />
</div>
<div class="hidden flex-none sm:block">
<Navbar />
</div>
</div>
</div>
<div class="drawer-side z-50">
<label for="my-drawer-3" aria-label="close sidebar" class="drawer-overlay"
></label>
<ul class="menu bg-cat-base min-h-full w-80 p-4">
<li class="text-xl font-bold my-5">
{currentPath}
</li>
<NavbarDrawer />
</ul>
</div>
</div>
</div> </div>

View File

@ -8,7 +8,7 @@ import Links from "@/links"
Links.map(({ to, label }) => ( Links.map(({ to, label }) => (
<LocaleLink <LocaleLink
to={to} to={to}
class={"m-2 hover:text-cat-mauve font-bold font-mono"} class={"m-2 not-hover:!text-cat-text font-bold font-mono"}
> >
~/{label()} ~/{label()}
</LocaleLink> </LocaleLink>

View File

@ -0,0 +1,12 @@
---
import Links from "../../links"
import LocaleLink from "../links/LocaleLink.astro"
---
{
Links.map((link) => (
<li>
<LocaleLink to={link.to}>{link.label}</LocaleLink>
</li>
))
}

View File

@ -1,6 +1,6 @@
--- ---
import { Image } from "astro:assets" import { Image } from "astro:assets"
import me from "@/images/polite-cat.jpg" import me from "@/images/me.jpg"
import * as m from "@/paraglide/messages.js" import * as m from "@/paraglide/messages.js"
import "@/styles/global.css" import "@/styles/global.css"
--- ---
@ -18,10 +18,10 @@ import "@/styles/global.css"
</div> </div>
<Image <Image
src={me} src={me}
alt="Me on a hike" alt="Me on a stand in front of a poster that says 'anbudsassistent'"
width="400" width="400"
height="400" height="400"
class="p-5 mx-auto" class="p-5 mx-auto rounded-full"
loading={"eager"} loading={"eager"}
/> />
</div> </div>

View File

@ -0,0 +1,7 @@
---
import Greeting from "./Greeting.astro"
import LatestProjects from "./LatestProjects.astro"
---
<Greeting />
<LatestProjects />

View File

@ -0,0 +1,10 @@
---
import { getCollection } from "astro:content"
import ProjectGrid from "@/components/projects/ProjectGrid.astro"
const projects = await getCollection("projects")
---
<div class="divider"></div>
<ProjectGrid projects={projects} />

View File

@ -9,11 +9,10 @@ interface Props extends MyLink {
const { title, message, url, icon, class: clazz } = Astro.props const { title, message, url, icon, class: clazz } = Astro.props
const iconStyle = "w-6 h-6" const iconStyle = "w-6 h-6"
console.log(icon)
--- ---
<ExternalLink href={url} noStyle> <ExternalLink href={url} noStyle>
<div class:list={["card bg-base-300", clazz]}> <div class:list={["card bg-cat-mantle text-cat-text", clazz]}>
<div class="card-body p-5 flex flex-row items-center"> <div class="card-body p-5 flex flex-row items-center">
{ {
icon ? ( icon ? (

View File

@ -1,33 +1,12 @@
--- ---
import ProjectCard from "./ProjectCard.astro" import ProjectGrid from "./ProjectGrid.astro"
import * as m from "@/paraglide/messages"
import { type CollectionEntry } from "astro:content" import { type CollectionEntry } from "astro:content"
import { type NavLink } from "@/utils/linking"
interface Props { interface Props {
projects: CollectionEntry<"projects">[] projects: CollectionEntry<"projects">[]
} }
const { projects } = Astro.props const { projects } = Astro.props
const baseUrl: NavLink = "/projects"
--- ---
<div class="flex flex-wrap justify-around"> <ProjectGrid projects={projects} />
{
projects.map(
({ data: { title, description, tags, heroImage, heroImageAlt }, id }) => (
<div class="my-5 px-2">
<ProjectCard
title={title}
linkTo={`${baseUrl}/${id}`}
description={description}
tags={tags}
image={heroImage}
imageAlt={heroImageAlt}
/>
</div>
),
)
}
</div>

View File

@ -19,12 +19,13 @@ const { title, description, tags, image, imageAlt, linkTo } = Astro.props
<LocaleLink <LocaleLink
to={linkTo} to={linkTo}
class="card bg-cat-base max-w-96 shadow-xl hover:scale-105 transition" class="card bg-cat-base max-w-96 shadow-xl hover:scale-105 transition border border-cat-surface0"
> >
<figure> <figure>
<Image src={image} alt={imageAlt} /> <Image src={image} alt={imageAlt} />
<figcaption class="sr-only">{imageAlt}</figcaption>
</figure> </figure>
<div class="card-body"> <div class="card-body text-cat-text">
<h2 class="card-title"> <h2 class="card-title">
{title} {title}
</h2> </h2>

View File

@ -0,0 +1,32 @@
---
import type { Project } from "@/types/types"
import type { NavLink } from "@/utils/linking"
import ProjectCard from "./ProjectCard.astro"
interface Props {
projects: ReadonlyArray<Project>
}
const { projects } = Astro.props
const baseUrl: NavLink = "/projects"
---
<div class="flex flex-wrap justify-around">
{
projects.map(
({ data: { title, description, tags, heroImage, heroImageAlt }, id }) => (
<div class="my-5 px-2">
<ProjectCard
title={title}
linkTo={`${baseUrl}/${id}`}
description={description}
tags={tags}
image={heroImage}
imageAlt={heroImageAlt}
/>
</div>
),
)
}
</div>

View File

@ -1,11 +1,11 @@
--- ---
import Layout from "@/layouts/Layout.astro" import Layout from "@/layouts/Layout.astro"
import { Image } from "astro:assets"
import { getEntry, render } from "astro:content"
import BadgeList from "@/components/badge/BadgeList.astro" import BadgeList from "@/components/badge/BadgeList.astro"
import * as m from "@/paraglide/messages"
import { languageTag } from "@/paraglide/runtime"
import GiteaLink from "@/components/links/GiteaLink.astro" import GiteaLink from "@/components/links/GiteaLink.astro"
import { languageTag } from "@/paraglide/runtime"
import { getEntry, render } from "astro:content"
import { Image } from "astro:assets"
import * as m from "@/paraglide/messages"
import "@/styles/global.css" import "@/styles/global.css"
interface Props { interface Props {
@ -32,7 +32,7 @@ const {
<Layout title={title} class="mx-auto max-w-[750px]"> <Layout title={title} class="mx-auto max-w-[750px]">
<div class="flex justify-between my-2"> <div class="flex justify-between my-2">
<div> <div>
<h1>{title}</h1> <h2>{title}</h2>
<BadgeList tags={tags} /> <BadgeList tags={tags} />
</div> </div>
<div class="flex flex-col items-end"> <div class="flex flex-col items-end">
@ -46,7 +46,7 @@ const {
</div> </div>
<Image src={heroImage} alt={heroImageAlt} class="m-auto" /> <Image src={heroImage} alt={heroImageAlt} class="m-auto" />
<GiteaLink href={source} class="text-cat-mauve my-2" /> <GiteaLink href={source} class="my-2" />
<p class="my-2">{description}</p> <p class="my-2">{description}</p>
<Content /> <Content />

View File

@ -1,5 +1,5 @@
--- ---
title: "Hjemmeside" title: "Welcome"
description: "Welcome to my homepage / portfolio" description: "Welcome to my homepage / portfolio"
heroImage: "assets/recursive-meme.png" heroImage: "assets/recursive-meme.png"
heroImageAlt: "A recursive meme that says: Self-reference, recursive meme is self-referential" heroImageAlt: "A recursive meme that says: Self-reference, recursive meme is self-referential"

BIN
src/images/me.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 135 KiB

View File

@ -9,7 +9,8 @@ interface Props {
class?: string class?: string
} }
const { title, class: clazz } = Astro.props const { title, class: clazz } = Astro.props
const mainClass = "grow max-w-[1000px] m-auto sm:min-w-[500px] mt-5" const mainClass =
"grow max-w-[1000px] m-auto sm:min-w-[500px] not-sm:w-full px-5"
--- ---
<!doctype html> <!doctype html>
@ -26,8 +27,12 @@ const mainClass = "grow max-w-[1000px] m-auto sm:min-w-[500px] mt-5"
<body class="flex flex-col min-h-screen bg-cat-base text-cat-text"> <body class="flex flex-col min-h-screen bg-cat-base text-cat-text">
<Header /> <Header />
<main class:list={[mainClass, clazz]}> <main class:list={[mainClass, clazz]}>
<h1 class="text-center">~{resolvePathname(Astro.originPathname)}</h1> <h1 class="text-center not-sm:hidden">
<slot /> ~{resolvePathname(Astro.originPathname)}
</h1>
<div class="my-5">
<slot />
</div>
</main> </main>
<Footer /> <Footer />
</body> </body>

View File

@ -1,9 +1,9 @@
--- ---
import OnePager from "../../components/Greeting.astro" import IndexPage from "@/components/landing/IndexPage.astro"
import Layout from "../../layouts/Layout.astro" import Layout from "@/layouts/Layout.astro"
import "@/styles/global.css" import "@/styles/global.css"
--- ---
<Layout title="Welcome"> <Layout title="Welcome">
<OnePager /> <IndexPage />
</Layout> </Layout>

View File

@ -7,11 +7,7 @@ import "@/styles/global.css"
export const prerender = true export const prerender = true
export function getStaticPaths(): GetStaticPathsResult { export function getStaticPaths(): GetStaticPathsResult {
return [ return [{ params: { project: "homepage" } }]
{ params: { project: "hvl-ics-simplifier" } },
{ params: { project: "homepage" } },
{ params: { project: "simplify-truths" } },
]
} }
const { project } = Astro.params const { project } = Astro.params

View File

@ -1,10 +1,9 @@
--- ---
import IndexPage from "@/components/landing/IndexPage.astro"
import Layout from "@/layouts/Layout.astro" import Layout from "@/layouts/Layout.astro"
import Greeting from "@/components/Greeting.astro" import "@/styles/global.css"
// https://slashpages.net/
--- ---
<Layout title="Velkommen"> <Layout title="Velkommen">
<Greeting /> <IndexPage />
</Layout> </Layout>

View File

@ -7,11 +7,7 @@ import "@/styles/global.css"
export const prerender = true export const prerender = true
export function getStaticPaths(): GetStaticPathsResult { export function getStaticPaths(): GetStaticPathsResult {
return [ return [{ params: { project: "homepage" } }]
{ params: { project: "hvl-ics-simplifier" } },
{ params: { project: "homepage" } },
{ params: { project: "simplify-truths" } },
]
} }
const { project } = Astro.params const { project } = Astro.params

View File

@ -48,6 +48,6 @@ h3 {
/* TODO change default style*/ /* TODO change default style*/
a { a {
@apply link; @apply link text-cat-mauve;
text-decoration-line: none; text-decoration-line: none;
} }

View File

@ -9,5 +9,6 @@ export type Icon =
| "linkedin" | "linkedin"
| "link" | "link"
| "status-health" | "status-health"
| "hamburger"
export type PajamasIcon = `pajamas:${Icon}` export type PajamasIcon = `pajamas:${Icon}`