Squashed commit of the following:

commit f97a703e0da24e9c98caad7c48cb5882471abdb1
Author: Ivan Dimitrov <ivan@idimitrov.dev>
Date:   Fri Dec 15 06:42:21 2023 +0200

    fix build error

commit dc759d9e3db46cb77cad34e72472c08553211c1c
Author: Ivan Dimitrov <ivan@idimitrov.dev>
Date:   Thu Dec 14 18:05:53 2023 +0200

    birthday easter egg maybe not working at all but whatever

commit 60dbe3ffe9da67abdf3f1dc2bb3f5c0c5bf86643
Author: Ivan Dimitrov <ivan@idimitrov.dev>
Date:   Fri Dec 8 17:47:33 2023 +0200

    newlines

commit 1a7230c4d784077e4156fba4cb017cdc24391e42
Author: Ivan Dimitrov <ivan@idimitrov.dev>
Date:   Fri Dec 8 17:46:50 2023 +0200

    links

commit e1b9e5b00890f9b35e7052a8b5b12b711bfe0911
Author: Ivan Dimitrov <ivan@idimitrov.dev>
Date:   Fri Dec 1 15:49:52 2023 +0200

    add public key and some svg shadow

commit b5dfb5bfab7d4fdd3bbbfe6457a776533f69730c
Author: Ivan Dimitrov <ivan@idimitrov.dev>
Date:   Wed Nov 29 16:32:17 2023 +0200

    make it lighter

commit b065b62975af24de7fd89717ea55ea67984c1b0e
Author: Ivan Dimitrov <ivan@idimitrov.dev>
Date:   Wed Nov 29 15:58:10 2023 +0200

    formatting

commit bb5bd2e5f16b637680075f89e85b0f6e99851734
Author: Ivan Dimitrov <ivan@idimitrov.dev>
Date:   Wed Nov 29 15:57:22 2023 +0200

    metadata and some optimizations

commit 3d1fd8a2fa4882bbfefcf19d47df18b44d3962f9
Author: Ivan Dimitrov <ivan@idimitrov.dev>
Date:   Wed Nov 29 15:38:28 2023 +0200

    sitemap and robots

commit 327f4b7f43b6936f4b0f9dce595837faeb1ac9bf
Author: Ivan Dimitrov <ivan@idimitrov.dev>
Date:   Wed Nov 29 10:06:47 2023 +0200

    flake update

commit 16e08c84c691f8bc69b5e56a2efe37d384be943b
Author: Ivan Dimitrov <ivan@idimitrov.dev>
Date:   Tue Nov 28 19:11:41 2023 +0200

    flake update

commit a7eb0513e6fb22eacaa365f37ad4482272e9bc4d
Author: Ivan Dimitrov <ivan@idimitrov.dev>
Date:   Sun Nov 26 12:59:41 2023 +0200

    set build inputs to only node

commit 59776102f521e20dbede3edb022305d26e69c539
Author: Ivan Dimitrov <ivan@idimitrov.dev>
Date:   Sun Nov 26 12:55:12 2023 +0200

    making the site run on nixos
This commit is contained in:
Ivan Dimitrov 2023-12-17 11:35:42 +02:00
parent c178ca98e7
commit 180e38ab65
14 changed files with 6262 additions and 20 deletions

View File

@ -1,5 +1,11 @@
This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app).
DNS: idimitrov.dev
I2P: s7zr3m6jvhiu6feourmgccxvxbrlnfbugxcn2m45ms44t24q2zgq.b32.i2p
TOR: http://sxfx23zafag4lixkb4s6zwih7ga5jnzfgtgykcerd354bvb6u7alnkid.onion
## Getting Started
First, run the development server:

BIN
bun.lockb

Binary file not shown.

View File

@ -130,11 +130,11 @@
"systems": "systems_3"
},
"locked": {
"lastModified": 1700381416,
"narHash": "sha256-aRPRwB6Wq7IeqAzYBfmOvmJhBL8vtWLinBzC2unIdFI=",
"lastModified": 1701244257,
"narHash": "sha256-rJHTSJlDa0gkJubwdsNKZHQe0Is54Uk1f2chTYTxnO4=",
"owner": "ivandimitrov8080",
"repo": "flake-ide",
"rev": "2bb917c7b939e00166ef3a04ced321313036e0ce",
"rev": "1f702a622d51814e8a11f72f389eff73239c1082",
"type": "github"
},
"original": {
@ -145,11 +145,11 @@
},
"nixpkgs": {
"locked": {
"lastModified": 1700108881,
"narHash": "sha256-+Lqybl8kj0+nD/IlAWPPG/RDTa47gff9nbei0u7BntE=",
"lastModified": 1701141680,
"narHash": "sha256-qaPcwKI0RR6mxfn4sMrHEjjDl6VCEPUTRZhN+OFB6zg=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "7414e9ee0b3e9903c24d3379f577a417f0aae5f1",
"rev": "4469e22700c47792f93daa882786d36f9bf8bc2a",
"type": "github"
},
"original": {
@ -184,11 +184,11 @@
"pre-commit-hooks": "pre-commit-hooks"
},
"locked": {
"lastModified": 1700240304,
"narHash": "sha256-nR5Ot2nN0msfGD1Vj76/4zb6+5ksJ28gfsit/BhK/oA=",
"lastModified": 1701194385,
"narHash": "sha256-35s/DHukB+qddspQHT1+QjJvWVAOhX1lZYhRLPKepXE=",
"owner": "nix-community",
"repo": "nixvim",
"rev": "440c449c0a13f7864bb8406baf19f4e9f61abc55",
"rev": "fda9e1e9a478c8dbe14cc7e2d8ff1db82619e515",
"type": "github"
},
"original": {
@ -239,11 +239,11 @@
"nixpkgs-stable": "nixpkgs-stable"
},
"locked": {
"lastModified": 1699271226,
"narHash": "sha256-8Jt1KW3xTjolD6c6OjJm9USx/jmL+VVmbooADCkdDfU=",
"lastModified": 1700064067,
"narHash": "sha256-1ZWNDzhu8UlVCK7+DUN9dVQfiHX1bv6OQP9VxstY/gs=",
"owner": "cachix",
"repo": "pre-commit-hooks.nix",
"rev": "ea758da1a6dcde6dc36db348ed690d09b9864128",
"rev": "e558068cba67b23b4fbc5537173dbb43748a17e8",
"type": "github"
},
"original": {

View File

@ -51,6 +51,23 @@
${tmuxConfig}
'';
};
packages.${system}.default = pkgs.buildNpmPackage rec {
buildInputs = with pkgs; [ nodejs_20 ];
pname = "idimitrov.dev";
version = "0.0.1";
src = ./.;
npmDepsHash = "sha256-DtnXn7/FP9Ccc5qXKQezi9StKOnhZnqVSbz0HJ3TQ0g=";
postInstall = ''
mkdir -p $out/bin/
cp -r ./.next/standalone/* $out/
cp -r ./.next/standalone/.* $out/
cp -r ./.next/static $out/.next/
cp -r ./public $out/
rm -rf $out/lib
echo "${pkgs.nodejs_20}/bin/node $out/server.js" > $out/bin/$pname
chmod +x $out/bin/$pname
'';
};
};
}

View File

@ -1,6 +1,7 @@
/** @type {import('next').NextConfig} */
const nextConfig = {
output: "export"
output: "standalone",
images: { unoptimized: true }
}
module.exports = nextConfig

6086
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

52
public/pgp.txt Normal file
View File

@ -0,0 +1,52 @@
-----BEGIN PGP PUBLIC KEY BLOCK-----
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
6zqS+1KfisZGORlLHR9MDijZxOSPT/PUCFr5l8c=
=HoX6
-----END PGP PUBLIC KEY BLOCK-----

View File

@ -11,6 +11,7 @@ import CopyButton from "$components/copy-button";
import { getText } from "$lib/react";
import { Prism as SyntaxHighlighter } from "react-syntax-highlighter";
import codeStyle from "react-syntax-highlighter/dist/esm/styles/prism/coldark-dark";
import { Metadata } from "next";
type Params = {
slug: string[];
@ -20,6 +21,14 @@ type Props = {
params: Params;
};
export async function generateMetadata({ params }: Props): Promise<Metadata> {
const { data } = getContent(params.slug);
return {
title: data.title,
description: data.goal || "Software development notes",
};
}
export async function generateStaticParams(): Promise<Params[]> {
return getAllPaths().map(p => ({ slug: p.split("/") }));
}

View File

@ -1,5 +1,6 @@
import { faEnvelope } from "@fortawesome/free-solid-svg-icons";
import { faEnvelope, faFile, faLock } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import Link from "next/link";
const email = "ivan@idimitrov.dev";
const mailto = `mailto:${email}`;
@ -9,6 +10,9 @@ const Contact = () => (
<a aria-label={mailto} href={mailto}>
<FontAwesomeIcon className="w-14 h-14" icon={faEnvelope} />
</a>
<Link aria-label="GPG public key" href="/pgp.txt">
<FontAwesomeIcon className="w-14 h-14" mask={faFile} icon={faLock} transform={"shrink-10 right-2 down-4"} />
</Link>
</div>
</div>
);

View File

@ -27,5 +27,9 @@ main {
}
svg {
@apply hover:text-sky-400 transition duration-200 ease-in;
@apply transition duration-200 ease-in;
}
svg:hover {
@apply text-sky-400;
filter: drop-shadow(0px 0px 20px #38bdf8);
}

View File

@ -1,6 +1,8 @@
import "./globals.css";
import Navbar from "$components/navbar";
import type { Metadata } from "next";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faCakeCandles, faSquareFull } from "@fortawesome/free-solid-svg-icons";
export const metadata: Metadata = {
title: "Ivan Dimitrov",
@ -8,12 +10,21 @@ export const metadata: Metadata = {
};
export default function RootLayout({ children }: { children: React.ReactNode }) {
let today = new Date();
return (
<html lang="en">
<body>
<main>
<Navbar />
{children}
{today.getDate() === new Date(today.getFullYear(), 12, 17).getDate() && (
<div className="absolute bottom-14 right-14">
<div className="flex flex-col">
<FontAwesomeIcon mask={faSquareFull} className="w-20 h-20 text-neutral-950 bg-gradient-to-t from-slate-950 via-red-700 to-yellow-400" icon={faCakeCandles} />
<span>It&apos;s my birthday.</span>
</div>
</div>
)}
</main>
</body>
</html>

11
src/app/robots.ts Normal file
View File

@ -0,0 +1,11 @@
import { MetadataRoute } from "next";
export default function robots(): MetadataRoute.Robots {
return {
rules: {
userAgent: "*",
allow: "/",
},
sitemap: "https://idimitrov.dev/sitemap.xml",
};
}

35
src/app/sitemap.ts Normal file
View File

@ -0,0 +1,35 @@
import { getAllContent } from "$lib/content";
import { MetadataRoute } from "next";
export default function sitemap(): MetadataRoute.Sitemap {
return [
{
url: "https://idimitrov.dev/",
lastModified: new Date(),
changeFrequency: "weekly",
priority: 1,
},
{
url: "https://idimitrov.dev/cases",
lastModified: new Date(),
changeFrequency: "weekly",
priority: 0.8,
},
{
url: "https://idimitrov.dev/contact",
lastModified: new Date(),
changeFrequency: "weekly",
priority: 0.5,
},
...getAllContent()
.map(c => c.data)
.map(d => {
return {
url: `https://idimitrov.dev${d.slug}`,
lastModified: new Date(),
changeFrequency: "weekly",
priority: d.priority || 0.8,
} as any;
}),
];
}

View File

@ -4,15 +4,21 @@ import path from "path";
export const baseDir = "./_content/";
const contentMap: Record<string, GrayMatterFile<string>> = {};
export const getContent = (slug: string[]): GrayMatterFile<string> => {
let p = path.join(baseDir);
let p: string = path.join(baseDir);
slug.forEach(s => {
p = path.join(p, s);
});
const file = fs.readFileSync(p, "utf8");
const m = matter(file);
m.data.slug = `/c/${slug.join("/")}`;
return m;
if (!contentMap[p]) {
const file = fs.readFileSync(p, "utf8");
const m = matter(file);
m.data.slug = `/c/${slug.join("/")}`;
contentMap[p] = m;
return m;
}
return contentMap[p];
};
const getAllPathsRecursive = (base = baseDir): string[] => {