initial commit

This commit is contained in:
Niklas Kapelle 2025-10-05 15:34:39 +02:00
commit df0c4cf3b1
Signed by: niklas
GPG Key ID: 4EB651B36D841D16
12 changed files with 3480 additions and 0 deletions

25
.gitignore vendored Normal file
View File

@ -0,0 +1,25 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
node_modules
dist
dist-ssr
*.local
# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?

97
context.json Normal file
View File

@ -0,0 +1,97 @@
{
"firstname": "Max",
"lastname": "Musterman",
"title": "Software Engineer B.Sc.",
"image_url": "https://www.ardeaprints.com/p/172/cat-british-shorthair-silver-spotted-tabby-646703.jpg.webp",
"address": "Deutschland, 10557 Berlin, Willy-Brandt-Straße 1",
"email": "me@example.com",
"tel": "0162-4468215244",
"nationality": "deutsch",
"marital_status": "ledig",
"place_of_birth": "Northpol",
"skils": [
"Rust",
"C",
".."
],
"languages": [
"Deutsch",
"Englisch"
],
"linkos": [
{
"link": "//images.unsplash.com/photo-1529778873920-4da4926a72c2?q=80&w=1936&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D",
"icon": "link zur seite"
},
{
"link": "https://images.unsplash.com/photo-1529778873920-4da4926a72c2?q=80&w=1936&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D",
"text": "link zur seite"
}
],
"jobs": [
{
"from": "2015",
"to": "2022",
"title": "Wissenschaflicher Mitarbeiter",
"subtitle": "Springfield University of atomar physics",
"desc": [
"Lorem ipsum",
"Lorem ipsum",
"Lorem ipsum",
"Lorem ipsum"
]
},
{
"from": "2022",
"to": "2025",
"title": "Geological Reserch",
"subtitle": "United States Geological Survey, Southpark",
"desc": [
"Lorem ipsum",
"Lorem ipsum",
"Lorem ipsum"
]
}
],
"schools": [
{
"from": "2022",
"to": "2025",
"title": "Software Engineering, Bachelor of Science",
"subtitle": "University of Applied Science",
"desc": [
"Lorem ipsum",
"Lorem ipsum",
"Lorem ipsum",
"Lorem ipsum",
"Lorem ipsum",
"Lorem ipsum",
"Lorem ipsum"
]
},
{
"from": "2022",
"to": "2025",
"title": "Wizarding Examinations (N.E.W.T.s)",
"subtitle": "Hogwarts school of magic for young wizards",
"desc": [
"Lorem ipsum",
"Lorem ipsum",
"Lorem ipsum",
"Lorem ipsum",
"Lorem ipsum",
"Lorem ipsum",
"Lorem ipsum"
]
},
{
"from": "2015",
"to": "2022",
"title": "Primary School",
"subtitle": "Harry Herpson High School (HHHS)",
"desc": [
"Lorem ipsum"
]
}
]
}

118
index.html Normal file
View File

@ -0,0 +1,118 @@
<!doctype html>
<html lang="de">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Lebenslauf</title>
</head>
<body class="bg-gray-100 print:bg-white text-gray-800">
<script type="module" src="/src/main.ts"></script>
<main
class="max-w-6xl mx-auto p-6 bg-white shadow-lg rounded-lg mt-8 print:mt-0 print:rounded-none print:shadow-none">
<header class="mb-2">
<h1 class="text-5xl text-primary font-bold -ml-1">{{ firstname }} {{ lastname }}</h1>
<h2 class="text-s text-primary italic">{{ title }}</h2>
</header>
<div class="flex justify-between">
<aside class="w-60">
<figure>
<img src="{{ image_url }}" />
</figure>
<div class="mt-1">
<div class="mb-1">
<h2 class="mediumHeader pb-1">Persönliche Daten</h2>
<hr class="line">
</div>
<div class="flex flex-col justify-items-start gap-2">
<div>
<h3 class="smallHeader">Anschrift</h3>
<p>{{ address }}</p>
</div>
<div>
<h3 class="smallHeader">Email</h3>
<a href="mailto:{{ email }}">{{ email }}</a>
</div>
<div>
<h3 class="smallHeader">Telefon</h3>
<a href="tel:{{ tel }}">{{ tel }}</a>
</div>
<div>
<h3 class="smallHeader">Staatsbürgerschaft</h3>
<p>{{ nationality }}</p>
</div>
<div>
<h3 class="smallHeader">Familienstand</h3>
<p>{{ marital_status }}</p>
</div>
<div>
<h3 class="smallHeader">Geburtsort</h3>
<p>{{ place_of_birth }}</p>
</div>
</div>
</div>
<div class="mt-1">
<div class="mb-1">
<h2 class="mediumHeader pb-1">Technologien</h2>
<hr class="line">
</div>
<div class="mb-1">
<ul>
{{#each skils}}
<li>{{this}}</li>
{{/each}}
</ul>
</div>
</div>
<div class="mt-1">
<div class="mb-1">
<h2 class="mediumHeader mb-1">Sprachen</h2>
<hr class="line">
</div>
<div class="mb-1">
<ul>
{{#each languages}}
<li>{{this}}</li>
{{/each}}
</ul>
</div>
</div>
<div class="mt-1">
<div class="mb-1">
<h2 class="mediumHeader pb-1">Links</h2>
<hr class="line">
</div>
<div class="mb-1">
<a class="flex" href="https://github.com/PSenfft">
<img class="object-contain w-16 h-16" src="github-mark.svg" />
<img class="object-contain w-18 h-18" src="qrcode_github.com.svg" />
</a>
</div>
</div>
</aside>
<section class="w-40 grow-2 border-l-1 border-gray-300 ml-3 pl-3">
<div class="ml-2 pb-12">
<h2 class="mediumHeader">Beruflicher Werdegang</h2>
<hr class="line">
{{#each jobs}}
{{> dateList this}}
{{/each}}
<div>
</div>
</div>
<div class="ml-2 pb-12">
<h2 class="mediumHeader">Akademische Laufbahn</h2>
<hr class="line">
{{#each schools}}
{{> dateList this }}
{{/each}}
<div>
</div>
</div>
</section>
</div>
</main>
</body>
</html>

3115
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

21
package.json Normal file
View File

@ -0,0 +1,21 @@
{
"name": "cv",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"build": "tsc && vite build",
"preview": "vite preview"
},
"devDependencies": {
"typescript": "~5.8.3",
"vite": "^7.1.2"
},
"dependencies": {
"@tailwindcss/vite": "^4.1.13",
"puppeteer-core": "^24.21.0",
"tailwindcss": "^4.1.13",
"vite-plugin-handlebars": "^2.0.0"
}
}

14
partials/dateList.hbs Normal file
View File

@ -0,0 +1,14 @@
<div class="flex pt-2 pb-5">
<div class="min-w-50">
{{ from }} - {{ to }}
</div>
<div>
<h2 class="font-bold text-lg">{{title}}</h2>
<p class="italic pt-1">{{subtitle}}</p>
<ul class="list-disc list-inside pt-2">
{{#each desc}}
<li>{{this}}</li>
{{/each}}
</ul>
</div>
</div>

29
pdf.js Normal file
View File

@ -0,0 +1,29 @@
import puppeteer from "puppeteer-core";
import path from 'path';
import { fileURLToPath } from 'url';
import { execSync } from 'child_process';
const filePath = `file:${path.join(path.dirname(fileURLToPath(import.meta.url)), 'dist/index.html')}`;
const chromiumPath = execSync('which chromium').toString().trim();
const browser = await puppeteer.launch({
executablePath: chromiumPath,
args: [
'--disable-web-security',
'--allow-file-access-from-files',
'--disable-site-isolation-trials'
]
});
const page = await browser.newPage();
await page.setBypassCSP(true);
await page.goto(filePath, {
waitUntil: 'networkidle2',
});
await page.pdf({
path: 'out.pdf',
scale: 0.8,
format: 'A4',
});
await browser.close();

2
src/main.ts Normal file
View File

@ -0,0 +1,2 @@
import './style.css'

17
src/style.css Normal file
View File

@ -0,0 +1,17 @@
@import "tailwindcss";
.smallHeader {
@apply text-sm font-bold pb-1
}
.mediumHeader {
@apply text-xl text-primary font-bold
}
.line {
@apply h-px bg-gray-300 border-0
}
@theme {
--color-primary: oklch(52.7% 0.154 150.069);
}

1
src/vite-env.d.ts vendored Normal file
View File

@ -0,0 +1 @@
/// <reference types="vite/client" />

25
tsconfig.json Normal file
View File

@ -0,0 +1,25 @@
{
"compilerOptions": {
"target": "ES2022",
"useDefineForClassFields": true,
"module": "ESNext",
"lib": ["ES2022", "DOM", "DOM.Iterable"],
"skipLibCheck": true,
/* Bundler mode */
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"verbatimModuleSyntax": true,
"moduleDetection": "force",
"noEmit": true,
/* Linting */
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"erasableSyntaxOnly": true,
"noFallthroughCasesInSwitch": true,
"noUncheckedSideEffectImports": true
},
"include": ["src"]
}

16
vite.config.ts Normal file
View File

@ -0,0 +1,16 @@
import { defineConfig } from "vite"
import { resolve } from "path";
import tailwindcss from "@tailwindcss/vite"
import handlebars from "vite-plugin-handlebars";
import ctx from "./context.json"
export default defineConfig({
base: "./",
plugins: [
tailwindcss(),
handlebars({
context: ctx,
partialDirectory: resolve(__dirname, "partials"),
})
],
})