Compare commits

..

No commits in common. "d6c6542ad15adea420b6433f54c812b33f48e013" and "0ec930bf95af78e5497ccbb6603a7c2fb31bfd87" have entirely different histories.

16 changed files with 71 additions and 6799 deletions

44
.lovable/plan.md Normal file
View file

@ -0,0 +1,44 @@
## Markdown blog
Posts live as `.md` files in `src/content/blog/`. Each file has frontmatter (title, date, description, tags) and a markdown body. Vite's `import.meta.glob` loads them at build time — no backend, fully static, fast.
### Writing a post
Create `src/content/blog/my-post.md`:
```md
---
title: My first post
date: 2026-05-19
description: A short summary shown on the index and in meta tags.
tags: [self-hosting, linux]
---
# Heading
Body in **markdown**. Code blocks, lists, links, images all work.
```
The filename (minus `.md`) becomes the URL slug: `/blog/my-post`.
### What I'll build
1. Add deps: `gray-matter` (frontmatter parsing), `react-markdown` + `remark-gfm` (rendering), `rehype-highlight` (code syntax highlighting).
2. `src/lib/blog.ts` — loads all posts via `import.meta.glob`, parses frontmatter, sorts by date, exposes `getAllPosts()` and `getPostBySlug()`.
3. `src/pages/Blog.tsx``/blog` index page styled to match the site (glass cards, orange accents, mouse glow). Lists posts with title, date, description, tags.
4. `src/pages/BlogPost.tsx``/blog/:slug` page rendering the markdown with themed typography (prose styles using existing design tokens).
5. Wire routes in `src/App.tsx`.
6. Update the hub card on `/` so "Blog" links to `/blog` internally (instead of the external damaj.tech link).
7. Add one starter post `src/content/blog/hello-world.md` so the index isn't empty.
### Authoring workflow
- Connect the project to GitHub (Plus menu → GitHub) for easiest editing.
- Add/edit `.md` files in `src/content/blog/` from any editor or directly on GitHub — changes sync back to Lovable automatically and appear on the site on next build.
- Or just ask me to add a new post and paste the content here.
### Notes
- Fully static, no database, no auth needed.
- Draft support: posts with `draft: true` in frontmatter can be hidden from the index.
- SEO: per-post `<title>` and meta description set from frontmatter.

View file

@ -40,7 +40,6 @@
"date-fns": "^3.6.0",
"embla-carousel-react": "^8.6.0",
"gray-matter": "^4.0.3",
"highlight.js": "^11.11.1",
"input-otp": "^1.4.2",
"lucide-react": "^0.462.0",
"next-themes": "^0.3.0",

View file

@ -3,15 +3,22 @@
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Damaj</title>
<meta name="description" content="Personal site and blog. Writing on engineering, systems, and craft." />
<meta name="author" content="Damaj" />
<!-- TODO: Set the document title to the name of your application -->
<title>Lovable App</title>
<meta name="description" content="Lovable Generated Project" />
<meta name="author" content="Lovable" />
<meta property="og:title" content="Damaj" />
<meta property="og:description" content="Personal site and blog. Writing on engineering, systems, and craft." />
<!-- TODO: Update og:title to match your application name -->
<meta property="og:title" content="Lovable App" />
<meta property="og:description" content="Lovable Generated Project" />
<meta property="og:type" content="website" />
<meta property="og:image" content="https://lovable.dev/opengraph-image-p98pqg.png" />
<link rel="alternate" type="application/rss+xml" title="damaj.tech - Blog" href="/rss.xml" />
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:site" content="@Lovable" />
<meta name="twitter:image" content="https://lovable.dev/opengraph-image-p98pqg.png" />
<link rel="alternate" type="application/rss+xml" title="damaj.tech — Blog" href="/rss.xml" />
</head>
<body>

View file

@ -48,7 +48,6 @@
"date-fns": "^3.6.0",
"embla-carousel-react": "^8.6.0",
"gray-matter": "^4.0.3",
"highlight.js": "^11.11.1",
"input-otp": "^1.4.2",
"lucide-react": "^0.462.0",
"next-themes": "^0.3.0",

6769
pnpm-lock.yaml generated

File diff suppressed because it is too large Load diff

View file

@ -1,3 +0,0 @@
allowBuilds:
'@swc/core': true
esbuild: true

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 385 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 779 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 20 KiB

Before After
Before After

1
public/placeholder.svg Normal file
View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="1200" height="1200" fill="none"><rect width="1200" height="1200" fill="#EAEAEA" rx="3"/><g opacity=".5"><g opacity=".5"><path fill="#FAFAFA" d="M600.709 736.5c-75.454 0-136.621-61.167-136.621-136.62 0-75.454 61.167-136.621 136.621-136.621 75.453 0 136.62 61.167 136.62 136.621 0 75.453-61.167 136.62-136.62 136.62Z"/><path stroke="#C9C9C9" stroke-width="2.418" d="M600.709 736.5c-75.454 0-136.621-61.167-136.621-136.62 0-75.454 61.167-136.621 136.621-136.621 75.453 0 136.62 61.167 136.62 136.621 0 75.453-61.167 136.62-136.62 136.62Z"/></g><path stroke="url(#a)" stroke-width="2.418" d="M0-1.209h553.581" transform="scale(1 -1) rotate(45 1163.11 91.165)"/><path stroke="url(#b)" stroke-width="2.418" d="M404.846 598.671h391.726"/><path stroke="url(#c)" stroke-width="2.418" d="M599.5 795.742V404.017"/><path stroke="url(#d)" stroke-width="2.418" d="m795.717 796.597-391.441-391.44"/><path fill="#fff" d="M600.709 656.704c-31.384 0-56.825-25.441-56.825-56.824 0-31.384 25.441-56.825 56.825-56.825 31.383 0 56.824 25.441 56.824 56.825 0 31.383-25.441 56.824-56.824 56.824Z"/><g clip-path="url(#e)"><path fill="#666" fill-rule="evenodd" d="M616.426 586.58h-31.434v16.176l3.553-3.554.531-.531h9.068l.074-.074 8.463-8.463h2.565l7.18 7.181V586.58Zm-15.715 14.654 3.698 3.699 1.283 1.282-2.565 2.565-1.282-1.283-5.2-5.199h-6.066l-5.514 5.514-.073.073v2.876a2.418 2.418 0 0 0 2.418 2.418h26.598a2.418 2.418 0 0 0 2.418-2.418v-8.317l-8.463-8.463-7.181 7.181-.071.072Zm-19.347 5.442v4.085a6.045 6.045 0 0 0 6.046 6.045h26.598a6.044 6.044 0 0 0 6.045-6.045v-7.108l1.356-1.355-1.282-1.283-.074-.073v-17.989h-38.689v23.43l-.146.146.146.147Z" clip-rule="evenodd"/></g><path stroke="#C9C9C9" stroke-width="2.418" d="M600.709 656.704c-31.384 0-56.825-25.441-56.825-56.824 0-31.384 25.441-56.825 56.825-56.825 31.383 0 56.824 25.441 56.824 56.825 0 31.383-25.441 56.824-56.824 56.824Z"/></g><defs><linearGradient id="a" x1="554.061" x2="-.48" y1=".083" y2=".087" gradientUnits="userSpaceOnUse"><stop stop-color="#C9C9C9" stop-opacity="0"/><stop offset=".208" stop-color="#C9C9C9"/><stop offset=".792" stop-color="#C9C9C9"/><stop offset="1" stop-color="#C9C9C9" stop-opacity="0"/></linearGradient><linearGradient id="b" x1="796.912" x2="404.507" y1="599.963" y2="599.965" gradientUnits="userSpaceOnUse"><stop stop-color="#C9C9C9" stop-opacity="0"/><stop offset=".208" stop-color="#C9C9C9"/><stop offset=".792" stop-color="#C9C9C9"/><stop offset="1" stop-color="#C9C9C9" stop-opacity="0"/></linearGradient><linearGradient id="c" x1="600.792" x2="600.794" y1="403.677" y2="796.082" gradientUnits="userSpaceOnUse"><stop stop-color="#C9C9C9" stop-opacity="0"/><stop offset=".208" stop-color="#C9C9C9"/><stop offset=".792" stop-color="#C9C9C9"/><stop offset="1" stop-color="#C9C9C9" stop-opacity="0"/></linearGradient><linearGradient id="d" x1="404.85" x2="796.972" y1="403.903" y2="796.02" gradientUnits="userSpaceOnUse"><stop stop-color="#C9C9C9" stop-opacity="0"/><stop offset=".208" stop-color="#C9C9C9"/><stop offset=".792" stop-color="#C9C9C9"/><stop offset="1" stop-color="#C9C9C9" stop-opacity="0"/></linearGradient><clipPath id="e"><path fill="#fff" d="M581.364 580.535h38.689v38.689h-38.689z"/></clipPath></defs></svg>

After

Width:  |  Height:  |  Size: 3.2 KiB

View file

@ -1 +0,0 @@
{"name":"","short_name":"","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"}

View file

@ -1,24 +1,19 @@
---
title: New Website!
date: 2026-06-18
description: Finally, a new facelift. Here's what new and what's to come
title: Hello, world
date: 2026-05-19
description: First post on the new site. A quick note on what's coming.
tags: [meta]
---
# Hello, world!
# Hello, world
Welcome to my new website.
I have to admit that this website is a hybrid of vibe-code and a manual coder. But worry not, this blog is and always will be written by hand!
This is the first post on the rebuilt site. Posts here live as plain markdown
files inside `src/content/blog/` — no database, no CMS, just files.
I did redo everything so that it can finally be modern, up to date and worth showing around :P. As the old one was very basic and wasn't my vision.
## What to expect
## What's new?
What isn't new?
- Notes on self-hosting (Forgejo, SearXNG, and friends)
- Linux tinkering
- Random thoughts
- Finally a functional blog(0 manual HTML, it's all [markdown](https://git.damaj.tech/Damaj301damaj/damaj.tech/src/content/blog)!).
- Make the website much more fancier as I am a huge fan of Apple's "Liquid Glass" as I was also a fan of Frutiger Aero when it was still a trend.
- Fixed up stuff here and there.
...and that's it for now. Stay tuned :p
Stay tuned.

View file

@ -5,10 +5,10 @@ import avatar from '@/assets/avatar.png';
import { MessageCircle, Rss, GitBranch, Search, ExternalLink, ArrowUpRight } from 'lucide-react';
const items = [
{ icon: Search, label: 'SearXNG', href: 'https://search.damaj.tech/', desc: 'Self-hosted search' },
{ icon: MessageCircle, label: 'Who Am I?', href: '/whoami', desc: 'About me', internal: true },
{ icon: Rss, label: 'Blog', href: '/blog', desc: 'My writings', internal: true },
{ icon: GitBranch, label: 'Git Server', href: 'https://git.damaj.tech/', desc: 'Self-hosted Forgejo' },
{ icon: MessageCircle, label: 'Who Am I?', href: '/whoami', desc: 'About me', internal: true },
{ icon: Search, label: 'SearXNG', href: 'https://searxng.damaj.tech/', desc: 'Private search' },
];
const Index = () => {